pr-status-comment #897
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: pr-status-comment | |
| # Non-blocking. Maintains a single sticky PR comment summarising the | |
| # outcome of every required workflow. Triggered via `workflow_run` so it | |
| # receives write-capable GITHUB_TOKEN in the base-repo context without | |
| # touching PR-authored code. | |
| # | |
| # Security model | |
| # -------------- | |
| # - Uses `workflow_run` on the completion of each tracked workflow. This | |
| # gives the job a base-repo write-capable token. | |
| # - NEVER checks out the PR branch. The checkout step is pinned to the | |
| # repository default branch so the helper script executed here is always | |
| # the base-branch copy, never PR-authored code. This is the mitigation | |
| # for the canonical "pwn request" pattern described by GitHub Security | |
| # Lab (https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/). | |
| # - PR metadata is derived from `github.event.workflow_run.pull_requests` | |
| # (populated for same-repo PRs) with a fallback lookup by head SHA via | |
| # the REST API for fork PRs. | |
| # - If the trigger was not a pull_request (e.g. push to main), the job | |
| # exits successfully without posting anything. | |
| on: | |
| # This workflows list MUST stay in lockstep with | |
| # .github/workflows/tracked-required.json. The two copies exist because | |
| # GitHub parses `workflow_run.workflows` at workflow-load time from a | |
| # static YAML literal and cannot read it from JSON. The `ci-meta` | |
| # workflow's drift check fails the PR if the two lists diverge. | |
| workflow_run: | |
| workflows: | |
| - tests | |
| - lint | |
| - syntax | |
| - format | |
| - types | |
| - build | |
| - cli-smoke | |
| - determinism | |
| - policy-guard | |
| - ci-meta | |
| types: | |
| - completed | |
| permissions: | |
| contents: read | |
| actions: read | |
| pull-requests: write | |
| concurrency: | |
| group: pr-status-comment-${{ github.event.workflow_run.head_sha }} | |
| cancel-in-progress: false | |
| jobs: | |
| comment: | |
| name: update sticky comment | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| if: github.event.workflow_run.event == 'pull_request' | |
| steps: | |
| - name: Checkout default branch only | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| # CRITICAL: never pass the PR head_branch here. This workflow runs | |
| # with a write-capable token; checking out PR-authored code would | |
| # allow an attacker to rewrite the helper script below and | |
| # exfiltrate the token. Always use the repository default branch | |
| # so only trusted base-branch code runs. | |
| ref: ${{ github.event.repository.default_branch }} | |
| repository: ${{ github.repository }} | |
| persist-credentials: false | |
| - name: Resolve PR number | |
| id: pr | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| REPO: ${{ github.repository }} | |
| PR_JSON: ${{ toJSON(github.event.workflow_run.pull_requests) }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Prefer the PR list embedded in the workflow_run event payload. | |
| PR_NUMBER="$( | |
| python - <<'PY' | |
| import json, os | |
| payload = json.loads(os.environ.get("PR_JSON", "[]") or "[]") | |
| if isinstance(payload, list) and payload: | |
| entry = payload[0] | |
| if isinstance(entry, dict) and isinstance(entry.get("number"), int): | |
| print(entry["number"]) | |
| PY | |
| )" | |
| if [[ -z "${PR_NUMBER}" ]]; then | |
| # Fork PR fallback: look up the PR by head sha. | |
| PR_NUMBER="$( | |
| gh api \ | |
| -H 'Accept: application/vnd.github+json' \ | |
| "/repos/${REPO}/commits/${HEAD_SHA}/pulls" \ | |
| --jq '.[0].number // empty' | |
| )" | |
| fi | |
| if [[ -z "${PR_NUMBER}" ]]; then | |
| echo "no PR associated with head_sha=${HEAD_SHA}; skipping" | |
| echo "skip=true" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| echo "pr_number=${PR_NUMBER}" >> "${GITHUB_OUTPUT}" | |
| echo "skip=false" >> "${GITHUB_OUTPUT}" | |
| - name: Build comment body | |
| if: steps.pr.outputs.skip != 'true' | |
| id: body | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| PR_NUMBER: ${{ steps.pr.outputs.pr_number }} | |
| HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python scripts/ci/build_status_comment.py > "${RUNNER_TEMP}/comment.md" | |
| { | |
| echo 'body<<COMMENT_EOF' | |
| cat "${RUNNER_TEMP}/comment.md" | |
| echo 'COMMENT_EOF' | |
| } >> "${GITHUB_OUTPUT}" | |
| - name: Upsert sticky PR comment | |
| if: steps.pr.outputs.skip != 'true' | |
| uses: marocchino/sticky-pull-request-comment@0ea0beb66eb9baf113663a64ec522f60e49231c0 # v3.0.4 | |
| with: | |
| header: bpetite-workflow-status | |
| number: ${{ steps.pr.outputs.pr_number }} | |
| message: ${{ steps.body.outputs.body }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |