Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions .github/workflows/ci-failure-comment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: CI Failure Comment

# This workflow runs in the context of the base repo (not the fork) and has
# write access to post PR comments. It is triggered when the Linux Build
# workflow completes and picks up failure artifacts uploaded by status jobs.
#
# Security: This workflow never checks out or executes PR code. It only reads
# markdown artifacts generated by our own status jobs and posts them as
# comments via the GitHub API. The artifact content is read as a string and
# passed through the GitHub REST API (not interpolated into shell commands),
# which prevents injection attacks.
#
# zizmor:disable:dangerous-triggers -- only reads artifacts and posts comments, no PR code execution.
on:
workflow_run:
workflows: [Linux Build using GCC]
types:
- completed

permissions:
pull-requests: write
issues: write
actions: read

jobs:
post-failure-comment:
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion != 'success'
runs-on: ubuntu-latest
steps:
- name: Get PR number
id: pr
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
HEAD_OWNER: ${{ github.event.workflow_run.head_repository.owner.login }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
run: |
pr_number=$(gh api \
"/repos/${REPO}/pulls?head=${HEAD_OWNER}:${HEAD_BRANCH}&state=open" \
-q '.[0].number // empty')

if [ -z "$pr_number" ]; then
echo "No open PR found for branch ${HEAD_BRANCH}"
exit 0
fi
echo "number=$pr_number" >> "$GITHUB_OUTPUT"

- name: Download failure artifacts
if: steps.pr.outputs.number
uses: actions/download-artifact@v4
with:
github-token: ${{ github.token }}
run-id: ${{ github.event.workflow_run.id }}
pattern: ci-failure-*
path: /tmp/ci-failures
merge-multiple: false

- name: Post failure comments on PR
if: steps.pr.outputs.number
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
with:
script: |
const fs = require('fs');
const path = require('path');
const prNumber = parseInt(process.env.PR_NUMBER, 10);
const failuresDir = '/tmp/ci-failures';

if (!fs.existsSync(failuresDir)) {
console.log('No failure artifacts found.');
return;
}

// Collect all comment.md files from artifact subdirectories
const comments = [];
for (const entry of fs.readdirSync(failuresDir)) {
const commentPath = path.join(failuresDir, entry, 'comment.md');
if (fs.existsSync(commentPath)) {
comments.push(fs.readFileSync(commentPath, 'utf8').trim());
}
}

if (comments.length === 0) {
console.log('No failure comment files found in artifacts.');
return;
}

// Combine all failure comments into a single PR comment
const body = comments.join('\n\n---\n\n');

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: body,
});

console.log(`Posted failure comment on PR #${prNumber}`);
1 change: 0 additions & 1 deletion .github/workflows/linux-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ on:

permissions:
contents: read
pull-requests: write

concurrency:
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.head_ref || github.sha }}
Expand Down
1 change: 1 addition & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ rules:
dangerous-triggers:
ignore:
- build-impact-comment.yml
- ci-failure-comment.yml
Loading