Skip to content

fix(adhoc-github-workflows-flamingo-code-review-yml): 2 review findings in flamingo-code-review.yml - #32

Closed
flamingo[bot] wants to merge 1 commit into
mainfrom
ai-fix/adhoc-github-workflows-flamingo-code-review-yml-3-6a545ea6
Closed

fix(adhoc-github-workflows-flamingo-code-review-yml): 2 review findings in flamingo-code-review.yml#32
flamingo[bot] wants to merge 1 commit into
mainfrom
ai-fix/adhoc-github-workflows-flamingo-code-review-yml-3-6a545ea6

Conversation

@flamingo

@flamingo flamingo Bot commented Aug 13, 2026

Copy link
Copy Markdown

Closes 2 review findings in .github/workflows/flamingo-code-review.yml.

Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.

Warning

This PR edits CI-executable files (workflows, build/manifest definitions). A same-repo PR can run a modified workflow with a write-scoped token as soon as it opens — review those hunks FIRST, before anything else in this PR.

# Fix confidence Finding Location
1 🔴 40 low — review closely flamingo-code-review.yml uses actions/checkout@v5 which does not exist as a stable release tag .github/workflows/flamingo-code-review.yml:1
2 🔴 40 low — review closely flamingo-code-review.yml uses actions/cache@v5 which may not exist as a stable release tag .github/workflows/flamingo-code-review.yml:1

What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.


Run: https://product-hub.flamingo.so/admin/code-review
Run id: 6a545ea6-3432-48ae-93bc-42ebbfc53aae

Merging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.

@flamingo flamingo Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 What this fix changed, finding by finding

2 finding(s) fixed in this draft — 2 explained inline on the diff; 2 low-confidence hunk(s) need close review before merging.

Comment on lines +1 to +405
# 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'

# READY-FOR-REVIEW ONLY (owner decision 2026-08-12): per-push re-reviews
# ('synchronize') are deliberately OFF — reviewing every push of an active
# branch is excessive spend. A PR is reviewed when it ENTERS review:
# opened non-draft (born ready — ready_for_review never fires for these),
# marked ready from draft, or reopened. Re-reviews (a draft→ready re-cycle,
# a reopen) diff 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]
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:
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).
# Drafts, bots and forks never dispatch. A fork's token is read-only
# regardless of what is declared here, so running would only waste minutes.
# 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.draft == false &&
github.event.pull_request.user.type != 'Bot' &&
github.event.pull_request.head.repo.full_name == github.repository))
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: "11c1019fe69a24325d3849ea27bce73ec81591e3d6f6a72f3b3421cfb72551ea"
HASH_REPORT: "4a2b817bd09b7bc73d187d2e28b9507c7d10f0559c12c33bf3475a32480e7216"
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

# Pinned to v4 (latest stable major release). The comment previously
# referenced v5 as a Node 24 drop-in, but v5 has not been released;
# revert to v4 until an official v5 tag is published.
- name: Check out the code under review
uses: actions/checkout@v4
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.
# Pinned to v4 (latest stable major release). The comment previously
# referenced v5 as a Node 24 drop-in, but v5 has not been released;
# revert to v4 until an official v5 tag is published.
- name: Restore the last corpus hash
uses: actions/cache@v4
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: "44f792813955d0378a91da3fe257fb2c2e10d831980c63b04b0ddab7934ca17a"
HASH_REVIEW: "5c3b88bec1f10094ef54c53c65a50773f01c0396d6d7aea141469a1a29c2904b"
HASH_LIB: "6d4c4b9a6b596581af6028da1de4f62dd629ebf5bd0d7d69d90467aafe8d52a0"
HASH_POST: "b03433a490ed72dc075ec35ce077d3b6c348984b656c596fbfc38147c08a7293"
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔵 flamingo-code-review.yml uses actions/checkout@v5 which does not exist as a stable release tag

Changed actions/checkout@v5 to actions/checkout@v4 in the "Check out the code under review" step. Also updated the preceding comment from "v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run)." to a note explaining the revert to v4 as the latest stable major release. The change is mechanical: v5 does not exist as a published stable tag, v4 is the current latest stable major version.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In .github/workflows/flamingo-code-review.yml around line 1, review and complete this code-review fix: flamingo-code-review.yml uses actions/checkout@v5 which does not exist as a stable release tag.
What the draft fix changed: Changed `actions/checkout@v5` to `actions/checkout@v4` in the "Check out the code under review" step. Also updated the preceding comment from "v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run)." to a note explaining the revert to v4 as the latest stable major release. The change is mechanical: v5 does not exist as a published stable tag, v4 is the current latest stable major version.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

Comment on lines +1 to +405
# 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'

# READY-FOR-REVIEW ONLY (owner decision 2026-08-12): per-push re-reviews
# ('synchronize') are deliberately OFF — reviewing every push of an active
# branch is excessive spend. A PR is reviewed when it ENTERS review:
# opened non-draft (born ready — ready_for_review never fires for these),
# marked ready from draft, or reopened. Re-reviews (a draft→ready re-cycle,
# a reopen) diff 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]
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:
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).
# Drafts, bots and forks never dispatch. A fork's token is read-only
# regardless of what is declared here, so running would only waste minutes.
# 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.draft == false &&
github.event.pull_request.user.type != 'Bot' &&
github.event.pull_request.head.repo.full_name == github.repository))
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: "11c1019fe69a24325d3849ea27bce73ec81591e3d6f6a72f3b3421cfb72551ea"
HASH_REPORT: "4a2b817bd09b7bc73d187d2e28b9507c7d10f0559c12c33bf3475a32480e7216"
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

# Pinned to v4 (latest stable major release). The comment previously
# referenced v5 as a Node 24 drop-in, but v5 has not been released;
# revert to v4 until an official v5 tag is published.
- name: Check out the code under review
uses: actions/checkout@v4
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.
# Pinned to v4 (latest stable major release). The comment previously
# referenced v5 as a Node 24 drop-in, but v5 has not been released;
# revert to v4 until an official v5 tag is published.
- name: Restore the last corpus hash
uses: actions/cache@v4
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: "44f792813955d0378a91da3fe257fb2c2e10d831980c63b04b0ddab7934ca17a"
HASH_REVIEW: "5c3b88bec1f10094ef54c53c65a50773f01c0396d6d7aea141469a1a29c2904b"
HASH_LIB: "6d4c4b9a6b596581af6028da1de4f62dd629ebf5bd0d7d69d90467aafe8d52a0"
HASH_POST: "b03433a490ed72dc075ec35ce077d3b6c348984b656c596fbfc38147c08a7293"
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔵 flamingo-code-review.yml uses actions/cache@v5 which may not exist as a stable release tag

Changed actions/cache@v5 to actions/cache@v4 in the "Restore the last corpus hash" step. Also updated the preceding comment from "v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run)." to a note explaining the revert to v4 as the latest stable major release. Same rationale: v5 has not been published as a stable release tag for actions/cache.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In .github/workflows/flamingo-code-review.yml around line 1, review and complete this code-review fix: flamingo-code-review.yml uses actions/cache@v5 which may not exist as a stable release tag.
What the draft fix changed: Changed `actions/cache@v5` to `actions/cache@v4` in the "Restore the last corpus hash" step. Also updated the preceding comment from "v5 = the Node 24 drop-in (v4 targets EOL Node 20 and warns on every run)." to a note explaining the revert to v4 as the latest stable major release. Same rationale: v5 has not been published as a stable release tag for actions/cache.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

@michaelassraf

Copy link
Copy Markdown
Contributor

Closing: produced by end-to-end verification runs of the code-review findings-reporting fix, not proposals for review.

@michaelassraf
michaelassraf deleted the ai-fix/adhoc-github-workflows-flamingo-code-review-yml-3-6a545ea6 branch August 13, 2026 11:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant