fix(CODEWIKI-004): CU-86akbhg0r 17 review findings across 11 files #75
Workflow file for this run
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
| # Generated by the Flamingo hub — do not edit by hand. | |
| # Per-repo settings live in the hub admin (/admin/code-review); this file is | |
| # byte-identical across every reviewed repository AND every deployment, which | |
| # is what makes drift detectable by comparison. The hub's address arrives in | |
| # the dispatch payload (doc-orchestrator style) or, for pull_request runs, the | |
| # org Actions variable FLAMINGO_HUB_BASE_URL. | |
| # Named like its sibling pipeline ('🦩 Flamingo Code Documentation') so both | |
| # read as one product family in the Actions sidebar. | |
| name: 🦩 Flamingo Code Review | |
| on: | |
| # Push trigger - registers workflow with GitHub Actions (required for | |
| # workflow_dispatch API). Only fires when this file itself changes; the job | |
| # skips it — same pattern as the doc-orchestrator workflow. | |
| push: | |
| paths: | |
| - '.github/workflows/flamingo-code-review.yml' | |
| # ENTERS-REVIEW ONLY (2026-08-12; corrected 2026-09-07). The automatic | |
| # triggers are the moments a pull request ENTERS review, and nothing else. | |
| # | |
| # 'synchronize' (per-push) stays deliberately OFF. Reviewing every commit on | |
| # an open PR is the largest avoidable cost in an AI review pipeline, and it | |
| # trains authors to tune the bot out; the 2026 industry default is to review | |
| # at review moments and offer an explicit re-review on demand. | |
| # | |
| # 'opened' and 'reopened' were OFF between 2026-08-15 and 2026-09-07, on the | |
| # assumption that PRs are opened as drafts and later promoted. They are not | |
| # — PRs here are born non-draft, GitHub NEVER fires ready_for_review for | |
| # those, and so the automatic review effectively never ran. Drafts stay | |
| # excluded: an 'opened' event for a draft is dropped by the job's | |
| # draft == false guard, and that PR is reviewed later, on its | |
| # ready_for_review. | |
| # | |
| # 'labeled' is the on-demand re-review — the affordance that makes the | |
| # no-per-push default liveable. Commits pushed AFTER the first review are not | |
| # auto-reviewed, so adding the flamingo-review label is how a human | |
| # asks for another pass. A SEPARATE job removes it the moment the event | |
| # arrives, so adding it again asks again, and it can never strand itself on a | |
| # pull request the review gate declines. Every other label name is dropped by | |
| # the job's if — a skipped run, zero billable minutes. | |
| # | |
| # A 'synchronize' carrying that label is treated as the same request. GitHub | |
| # runs the workflow from the pull request's HEAD, so a label applied to a | |
| # branch whose head predates this file fires an event no workflow was there | |
| # to handle: the label lands, nothing runs, nothing consumes it, and because | |
| # it is now already present, adding it again fires NOTHING AT ALL. Honouring | |
| # it on the next push is what breaks that stall — the request gets served | |
| # once and consumed, instead of sitting on the pull request looking applied. | |
| # | |
| # 'synchronize' (every push) is otherwise here ONLY to serve the | |
| # flamingo-review-always label, and the job's if drops it on every pull | |
| # request that does not carry it. That is the per-PR escalation: subscribe the | |
| # risky refactor to continuous review, leave everything else on one review per | |
| # pull request. A skipped push run costs no billable minutes. | |
| # | |
| # Every repeat pass diffs only the delta since the last reviewed head — see | |
| # the incremental anchor in code-review-review.mjs. | |
| pull_request: | |
| types: [opened, ready_for_review, reopened, labeled, synchronize] | |
| repository_dispatch: | |
| types: [flamingo-code-review] | |
| # Lets the hub target a SETUP BRANCH before the install PR merges — the same | |
| # test-before-merge flow the doc pipeline uses. repository_dispatch only ever | |
| # fires on the default branch. | |
| workflow_dispatch: | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # GENERATED FROM SINGLE SOURCE OF TRUTH: CODE_REVIEW_PARAMS (this module) | |
| # This section is auto-generated when creating workflow PRs | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| inputs: | |
| run_id: | |
| description: 'Hub run-record id binding this execution to a code_review_runs row. Empty for pull_request runs — the hub creates the row from the callback.' | |
| required: false | |
| default: '' | |
| run_token: | |
| description: 'Per-run token minted by the hub at dispatch. Binds the callback to THIS run — the org-wide secret alone would let any repo report against another repo’s run.' | |
| required: false | |
| default: '' | |
| mode: | |
| description: 'Review mode: pr (diff-scoped), sweep (whole-repo scanner) or mine (rule mining over the full checkout).' | |
| required: false | |
| default: 'sweep' | |
| hub_base_url: | |
| description: 'Absolute hub origin. Dispatches carry it doc-orchestrator style; pull_request runs fall back to the org/repo Actions variable FLAMINGO_HUB_BASE_URL (shipped by Sync Secrets).' | |
| required: false | |
| default: '' | |
| review_budget_chars: | |
| description: 'Sweep corpus budget in characters for this run (review_config.sweep_budget_chars). Empty = UNCAPPED — the whole eligible corpus is reviewed in ~80K batches. The local twin defaults to 80000 instead; set the per-repo value to cap CI spend.' | |
| required: false | |
| default: '' | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # END GENERATED SECTION | |
| # ═══════════════════════════════════════════════════════════════════════════ | |
| # GENERATED FROM SINGLE SOURCE OF TRUTH: CODE_REVIEW_PARAMS (this module) | |
| # The doc-orchestrator's parameter chain for EVERY dispatch param: payload | |
| # first, workflow_dispatch input second, then the param's runtime fallback. | |
| # Workflow-level, so every dispatch var reaches every step and every | |
| # downloaded script. SECURITY: only NON-SENSITIVE values live here — secrets | |
| # are passed per-step, same as the doc workflow. | |
| env: | |
| RUN_ID: ${{ github.event.client_payload.run_id || github.event.inputs.run_id || '' }} | |
| MODE: ${{ github.event.client_payload.mode || github.event.inputs.mode || (github.event_name == 'pull_request' && 'pr' || 'sweep') }} | |
| HUB_BASE_URL: ${{ github.event.client_payload.hub_base_url || github.event.inputs.hub_base_url || vars.FLAMINGO_HUB_BASE_URL }} | |
| REVIEW_BUDGET_CHARS: ${{ github.event.client_payload.review_budget_chars || github.event.inputs.review_budget_chars || '' }} | |
| # Superseding a PR cancels the in-flight review of the stale head SHA; the | |
| # fresh run reviews (and reports on) the new one. The always() report step | |
| # still fires on the cancelled run, so its row records 'cancelled' rather | |
| # than dangling. | |
| concurrency: | |
| group: flamingo-code-review-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| checks: write | |
| jobs: | |
| # Consuming the label is its OWN job, gated on nothing but "that label was | |
| # added". Living inside the review job meant a label applied to a pull request the | |
| # review gate declines — a bot PR, a fork — was never consumed: the label sat | |
| # there permanently, and because it was already present, adding it again did | |
| # nothing. A silent dead end with no feedback. Split out, the request is | |
| # always consumed, whether or not a review follows it. | |
| # | |
| # It does NOT remove flamingo-review-always: that label is durable state | |
| # ("keep reviewing this PR"), not a one-shot request. | |
| consume-review-request: | |
| # The fork clause is not a token guard — a fork pull_request run gets a | |
| # READ-ONLY token whatever this file declares, so the DELETE below could | |
| # not succeed there even without it. It is here because a job that | |
| # provably cannot do its work should not start: on a fork the label | |
| # strands either way, and burning a runner to fail silently only hides | |
| # that. Same clause, same reason, as the review job below. | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name == github.repository && | |
| ((github.event.action == 'labeled' && | |
| github.event.label.name == 'flamingo-review') || | |
| (github.event.action == 'synchronize' && | |
| contains(github.event.pull_request.labels.*.name, 'flamingo-review'))) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Consume the on-demand review label | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO_FULL: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| # Best-effort: losing this race must never fail anything. | |
| run: | | |
| CURL_CFG=$(mktemp) && chmod 600 "$CURL_CFG" | |
| printf 'header = "Authorization: Bearer %s"\n' "$GITHUB_TOKEN" > "$CURL_CFG" | |
| curl -sS --max-time 30 -K "$CURL_CFG" -X DELETE \ | |
| "https://api.github.com/repos/$REPO_FULL/issues/$PR_NUMBER/labels/flamingo-review" > /dev/null || true | |
| rm -f "$CURL_CFG" | |
| review: | |
| # Skip actual work when triggered by push (push only registers the | |
| # workflow with GitHub, which is what lets workflow_dispatch target a | |
| # setup branch before the install PR merges). | |
| # Bots and forks never run, on EVERY event. A fork PR's token is read-only, | |
| # so the run could not post a comment or a check even if it finished; the | |
| # bot clause is what stops a hub-opened ai-fix PR from being reviewed into | |
| # another fix PR, and no label may waive it — "only a human applies a | |
| # label" is an assumption, not an invariant, since anything holding | |
| # pull-requests: write can label. To review a bot PR, dispatch it from the | |
| # hub admin, which is an authenticated, recorded decision. | |
| # | |
| # DRAFT is different, and only the on-demand label waives it: an explicit | |
| # request says "review this now" and means it whether or not the PR is | |
| # finished, which is how every comparable tool treats its manual trigger. | |
| # Automatic events and subscribed pushes still skip drafts. | |
| # NOTE: there is deliberately no vars. kill switch here. The hub's | |
| # per-repo enabled dial already covers it and answers 409 REVIEW_DISABLED, | |
| # which produces a recorded run. A second switch living in GitHub would be | |
| # invisible to the admin screen and would produce no callback at all. | |
| if: >- | |
| github.event_name != 'push' && | |
| (github.event_name == 'repository_dispatch' || | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event.pull_request.user.type != 'Bot' && | |
| github.event.pull_request.head.repo.full_name == github.repository && | |
| ((github.event.action == 'labeled' && | |
| github.event.label.name == 'flamingo-review') || | |
| (github.event.action == 'synchronize' && | |
| (contains(github.event.pull_request.labels.*.name, 'flamingo-review') || | |
| (github.event.pull_request.draft == false && | |
| contains(github.event.pull_request.labels.*.name, 'flamingo-review-always')))) || | |
| (github.event.action != 'labeled' && | |
| github.event.action != 'synchronize' && | |
| github.event.pull_request.draft == false)))) | |
| runs-on: ubuntu-latest | |
| # NO custom timeout-minutes — deliberately. GitHub's 6h hosted-runner | |
| # ceiling is the only clock: on hitting it the always() report step still | |
| # runs, so a sweep ships its per-batch checkpoint home and the NEXT sweep | |
| # resumes from the covered files (nothing is lost, nothing re-paid). Hung | |
| # runs are the hub reaper's job (run-safety-net-utils.ts, no-report cutoff | |
| # sized past the platform ceiling) — a second hand-tuned ceiling here was | |
| # one more number to keep in sync for no added safety. | |
| steps: | |
| # Fail LOUD, not silent: a pull_request run on a repo whose org never set | |
| # FLAMINGO_HUB_BASE_URL would otherwise curl an empty origin and die with | |
| # an unrelated error. Also normalizes a trailing slash ONCE for every | |
| # downstream consumer (a value of https://hub.example/ would otherwise | |
| # yield //api double-slash paths in four places). | |
| - name: Validate configuration | |
| run: | | |
| if [ -z "$HUB_BASE_URL" ]; then | |
| echo "::error::HUB_BASE_URL is empty — set the org Actions variable FLAMINGO_HUB_BASE_URL (or pass hub_base_url in the dispatch payload)." | |
| exit 1 | |
| fi | |
| echo "HUB_BASE_URL=${HUB_BASE_URL%/}" >> "$GITHUB_ENV" | |
| # REPORT CAPABILITY FIRST. Only workflow-helpers.sh + code-review-report.sh | |
| # download here — before checkout, cache, or any other script — so every | |
| # later failure (including the download step for the REST of the scripts | |
| # 404ing or hash-mismatching, the class that produced phantom 'running' | |
| # rows) still has a verified report script to call home with. | |
| - name: Download the report script | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| HASH_WORKFLOW_HELPERS: "3df9f07c408d987a44e9df7ba1584f01ff57502a596f013dd3218d3b4c30fd4c" | |
| HASH_REPORT: "479b45311e6e91e7dc36b90d6a32db57fae25b215fdcd35c2889fb5f0618df07" | |
| run: | | |
| set -euo pipefail | |
| SCRIPTS_BASE_URL="${HUB_BASE_URL}/api/doc-orchestrator/scripts" | |
| download_and_verify() { | |
| local script_name="$1" | |
| local expected_hash="$2" | |
| local output_path="/tmp/$script_name" | |
| curl -fsSL "$SCRIPTS_BASE_URL/$script_name" \ | |
| -H "Authorization: Bearer $WEBHOOK_SECRET" \ | |
| -o "$output_path" | |
| local actual_hash=$(shasum -a 256 "$output_path" | cut -d' ' -f1) | |
| if [ "$actual_hash" != "$expected_hash" ]; then | |
| echo "❌ HASH MISMATCH for $script_name!" | |
| echo " Expected: $expected_hash" | |
| echo " Actual: $actual_hash" | |
| echo " This could indicate tampering or an outdated hash." | |
| exit 1 | |
| fi | |
| # Make shell scripts executable | |
| if [[ "$script_name" == *.sh ]]; then | |
| chmod +x "$output_path" | |
| fi | |
| echo "✅ $script_name verified (hash: ${actual_hash:0:16}...)" | |
| } | |
| download_and_verify "workflow-helpers.sh" "$HASH_WORKFLOW_HELPERS" | |
| download_and_verify "code-review-report.sh" "$HASH_REPORT" | |
| # Early liveness ping — the FIRST real step after report capability is | |
| # secured. Stamps workflow_run_id + status 'running' on the hub's run row, | |
| # so "dispatch accepted but nothing ever ran" (no ping — reaped fast) is | |
| # distinguishable from "started, then crashed" (pinged — longer deadline). | |
| # Best-effort by design: the script exits 0 regardless; the always() | |
| # report below is the authoritative callback. | |
| - name: Tell the hub the run started | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| RUN_TOKEN: ${{ github.event.client_payload.run_token || github.event.inputs.run_token || '' }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} | |
| WF_RUN_ID: ${{ github.run_id }} | |
| REPO_FULL: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: /tmp/code-review-report.sh --started | |
| # v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run). | |
| - name: Check out the code under review | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| # The review job must never hold a push credential. | |
| persist-credentials: false | |
| # The corpus hash has to SURVIVE between runs, or the hash param is empty | |
| # and the 304 path the hub implements is unreachable — the corpus would be | |
| # transferred in full on every run in both modes. | |
| # v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run). | |
| - name: Restore the last corpus hash | |
| uses: actions/cache@v5 | |
| with: | |
| # BOTH files. Caching only the hash meant a 304 left rules.json | |
| # truncated to zero bytes while the run continued as if it had a | |
| # corpus. | |
| path: | | |
| .rules-hash | |
| rules.json | |
| key: flamingo-rules-hash-${{ github.repository }}-${{ github.run_id }} | |
| restore-keys: | | |
| flamingo-rules-hash-${{ github.repository }}- | |
| # The SAME download_and_verify function as the doc-orchestrator workflow | |
| # (single source: lib/config/workflow-scripts-bootstrap.ts, parity with | |
| # the doc template asserted at build time), fetching from the SAME | |
| # scripts endpoint. This bootstrap (and the report-capability step above, | |
| # which shares it) is the ONLY inline bash in the file — every other step | |
| # runs a verified unified script, so a script change ships from the hub | |
| # without touching this caller. Helpers + report already downloaded above; | |
| # this step fetches the rest, and its failure is REPORTABLE. | |
| - name: Download and verify scripts | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| HASH_FETCH_RULES: "a3adb1976b782a6bfe405b68c7adc52f6650535e0d9fbc2ea427c3567f2c9943" | |
| HASH_RUN: "e4ebfe017a09ed3f783c8aea995a079be46b4add3b3f92db1918291d1b3e7412" | |
| HASH_MINE: "c12e6fd532bab44c95e855046efef3b45940fbde87d449d5577d198a0d3c4f62" | |
| HASH_REVIEW: "fb7fa7802d31c7af69af300a0d7f5898f054b78efd44cd1262e880d1ad85c9b7" | |
| HASH_LIB: "adeba0f5d1c68ee2531e6c23f4a2ec206f3dc33f67a2b8228ade99509c6a6149" | |
| HASH_POST: "75404d6cf735f9a9f1332e65efb6e055ccaf18fe678b1fb3d74d0b0b996c6f2d" | |
| run: | | |
| set -euo pipefail | |
| SCRIPTS_BASE_URL="${HUB_BASE_URL}/api/doc-orchestrator/scripts" | |
| download_and_verify() { | |
| local script_name="$1" | |
| local expected_hash="$2" | |
| local output_path="/tmp/$script_name" | |
| curl -fsSL "$SCRIPTS_BASE_URL/$script_name" \ | |
| -H "Authorization: Bearer $WEBHOOK_SECRET" \ | |
| -o "$output_path" | |
| local actual_hash=$(shasum -a 256 "$output_path" | cut -d' ' -f1) | |
| if [ "$actual_hash" != "$expected_hash" ]; then | |
| echo "❌ HASH MISMATCH for $script_name!" | |
| echo " Expected: $expected_hash" | |
| echo " Actual: $actual_hash" | |
| echo " This could indicate tampering or an outdated hash." | |
| exit 1 | |
| fi | |
| # Make shell scripts executable | |
| if [[ "$script_name" == *.sh ]]; then | |
| chmod +x "$output_path" | |
| fi | |
| echo "✅ $script_name verified (hash: ${actual_hash:0:16}...)" | |
| } | |
| download_and_verify "code-review-fetch-rules.sh" "$HASH_FETCH_RULES" | |
| download_and_verify "code-review-run.sh" "$HASH_RUN" | |
| download_and_verify "code-review-mine.mjs" "$HASH_MINE" | |
| download_and_verify "code-review-review.mjs" "$HASH_REVIEW" | |
| download_and_verify "code-review-lib.mjs" "$HASH_LIB" | |
| download_and_verify "code-review-post.mjs" "$HASH_POST" | |
| - name: Fetch the rule corpus | |
| id: rules | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| # PR runs identify the pull request so the hub can answer with the | |
| # last successfully reviewed head SHA (X-Last-Reviewed-Sha) — the | |
| # incremental-review anchor persisted as .last-reviewed-sha. | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: /tmp/code-review-fetch-rules.sh | |
| # Stage checkpoints are their OWN credentialed steps — the review step | |
| # deliberately never holds the webhook secret or run token (it processes | |
| # untrusted PR content), so pings happen at step boundaries, not inside. | |
| - name: Report progress — reviewing | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| RUN_TOKEN: ${{ github.event.client_payload.run_token || github.event.inputs.run_token || '' }} | |
| WF_RUN_ID: ${{ github.run_id }} | |
| REPO_FULL: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: /tmp/code-review-report.sh --progress review | |
| - name: Review | |
| # The id lets the report step read the reviewer's own degraded output | |
| # (e.g. skipped_trivial_diff) alongside the rules step's. | |
| id: review | |
| if: steps.rules.outputs.skip != 'true' | |
| # MODE / RUN_ID arrive via the generated workflow-level env; only the | |
| # secret is scoped to the step (doc-workflow security discipline). | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| run: /tmp/code-review-run.sh | |
| # Post the findings to the PULL REQUEST itself and publish the | |
| # 'Flamingo Code Review' check run. pull_request events only — a sweep | |
| # has no PR to post to (its findings live in the hub dashboard). Uses the | |
| # runner's own GITHUB_TOKEN under the workflow's minimal grant | |
| # (pull-requests: write for the comments, checks: write for the check | |
| # run). One UPSERTED summary comment + inline comments where the diff | |
| # supports them; already-posted fingerprints are never re-commented, so | |
| # a new push adds only NEW findings. The check run is 'neutral' unless | |
| # the repo's served mode is 'blocking' AND action_required findings | |
| # exist. Writes posted.json (fingerprint -> comment id) for the report | |
| # step's callback — the reaction-learning loop reads it. | |
| - name: Report progress — finalizing | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| RUN_TOKEN: ${{ github.event.client_payload.run_token || github.event.inputs.run_token || '' }} | |
| WF_RUN_ID: ${{ github.run_id }} | |
| REPO_FULL: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: /tmp/code-review-report.sh --progress post | |
| - name: Post to the pull request | |
| id: post | |
| if: github.event_name == 'pull_request' && steps.rules.outputs.skip != 'true' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| DEGRADED: ${{ steps.review.outputs.degraded }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: node /tmp/code-review-post.mjs | |
| # A crashed Review step must still leave a trace ON THE PR: default | |
| # step-skip semantics silently skip the post step on failure, so the | |
| # developer saw no signal at all that a review was attempted — the | |
| # failure lived only on the hub's internal dashboard. Best-effort (|| | |
| # true): a failed courtesy comment must not mask the real failure state. | |
| - name: Post crash notice to the pull request | |
| if: failure() && github.event_name == 'pull_request' && steps.review.outcome == 'failure' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| REPO_FULL: ${{ github.repository }} | |
| WF_RUN_ID: ${{ github.run_id }} | |
| run: | | |
| BODY="🦩 **Flamingo Code Review crashed on this push.** No findings were posted — this is an infrastructure failure, not a clean review. See the [workflow run](https://github.com/$REPO_FULL/actions/runs/$WF_RUN_ID)." | |
| CURL_CFG=$(mktemp) && chmod 600 "$CURL_CFG" | |
| printf 'header = "Authorization: Bearer %s"\n' "$GITHUB_TOKEN" > "$CURL_CFG" | |
| curl -s -K "$CURL_CFG" -X POST "https://api.github.com/repos/$REPO_FULL/issues/$PR_NUMBER/comments" \ | |
| -H "Content-Type: application/json" \ | |
| --data "$(printf '%s' "$BODY" | jq -Rs '{body: .}')" > /dev/null || true | |
| rm -f "$CURL_CFG" | |
| # The report script downloads FIRST (dedicated step above), so a missing | |
| # /tmp/code-review-report.sh here means the report-capability bootstrap | |
| # itself failed (endpoint down, hash mismatch before anything else ran). | |
| # The guarded inline curl below still posts a minimal failure callback for | |
| # exactly that case; the hub's tiered reaper remains the last resort. | |
| - name: Report back to the hub | |
| if: always() && env.HUB_BASE_URL != '' | |
| # RUN_ID / MODE / HUB_BASE_URL arrive via the generated workflow-level | |
| # env. RUN_TOKEN is SENSITIVE (per-run bearer) so it is step-scoped | |
| # HERE — the only consumer — and masked by the script; the review step | |
| # that processes untrusted PR content never sees it. Remaining step env | |
| # is the secret plus values that exist nowhere but the GitHub context — | |
| # which enters through env, never interpolated into a script body. | |
| env: | |
| WEBHOOK_SECRET: ${{ secrets.DOC_ORCH_WEBHOOK_SECRET }} | |
| RUN_TOKEN: ${{ github.event.client_payload.run_token || github.event.inputs.run_token || '' }} | |
| JOB_STATUS: ${{ job.status }} | |
| # Either step can degrade a run: the rules step (corpus unavailable) | |
| # or the reviewer itself (trivial-diff skip, unresolvable PR base). | |
| DEGRADED: ${{ steps.rules.outputs.degraded || steps.review.outputs.degraded }} | |
| # Dispatch events carry no pull_request context — github.sha is the | |
| # tip of the checked-out ref, so sweep runs record the commit too. | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} | |
| WF_RUN_ID: ${{ github.run_id }} | |
| REPO_FULL: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| # The ONE justified inline-bash exception beyond the bootstrap: when the | |
| # report script itself never downloaded, no unified script exists to | |
| # report the failure — so a minimal guarded curl posts it. Kept tiny on | |
| # purpose; all real reporting logic stays in code-review-report.sh. | |
| run: | | |
| if [ ! -x /tmp/code-review-report.sh ]; then | |
| echo "::error::code-review-report.sh missing — sending bootstrap-failure callback" | |
| # Secrets NEVER ride argv (ps-visible): the bearer goes through a | |
| # 0600 curl config file and RUN_TOKEN through jq's env — the same | |
| # transport rule the report script itself follows. | |
| CURL_CFG=$(mktemp) && chmod 600 "$CURL_CFG" | |
| printf 'header = "Authorization: Bearer %s"\n' "$WEBHOOK_SECRET" > "$CURL_CFG" | |
| jq -n --arg run_id "${RUN_ID:-}" \ | |
| --arg wf "$WF_RUN_ID" --arg repo "$REPO_FULL" --arg mode "$MODE" \ | |
| '{run_id: $run_id, run_token: ($ENV.RUN_TOKEN // ""), status: "failure", | |
| degraded_reason: "bootstrap_failed", workflow_run_id: $wf, | |
| repo_full_name: $repo, mode: $mode, | |
| error_message: "Script bootstrap failed: the report script never downloaded from the hub."}' | | |
| curl -sS --max-time 30 -K "$CURL_CFG" -X POST "$HUB_BASE_URL/api/code-review/webhook" \ | |
| -H "Content-Type: application/json" -d @- || true | |
| rm -f "$CURL_CFG" | |
| exit 1 | |
| fi | |
| /tmp/code-review-report.sh |