Skip to content

ci(review): self-heal a review gate whose clear run was lost - #4762

Closed
cixzhang wants to merge 1 commit into
mainfrom
review-gate-reconcile
Closed

cixzhang wants to merge 1 commit into
mainfrom
review-gate-reconcile

Conversation

@cixzhang

@cixzhang cixzhang commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The failure

PR #4750 was approved by an entitled code owner at 16:11Z and still sat
BLOCKED an hour later. The approval fired review-clear.yml as designed — and
that run died in "Set up job":

Getting action download info
Failed to resolve action download info. Error: Service Unavailable
##[error]Failed to resolve action download info.

It never reached a line of script. GitHub Actions was in a major incident.
Another PR (#4752) hit the same flake ten minutes later, got a retry on the
download, and cleared normally — so the clear logic is fine. The bug is that
the approval event is one-shot: nothing re-fires it, nothing alerts, and the
gate stays pending indefinitely. Any transient failure has this shape — a
dropped webhook, a cancelled run, a job that times out in the queue.

Worth knowing, because it makes manual recovery a trap: branch protection
requires the review-required context from the GitHub Actions app
(app_id 15368). Posting that status with a personal token turns the PR's
rollup green while the merge stays blocked, because the bot's pending is what
the requirement actually reads. Only a workflow run can truly clear this gate,
so the recovery path has to be automated.

Changes

  • review-clear.yml gains a 15-minute clear-only sweep (schedule), plus a
    workflow_dispatch for an immediate one.
  • The sweep and the approval event now run the same clearOne() — the
    existing body is refactored into a function and the event path is unchanged,
    so recovery can't drift from the live path.
  • A PR counts as unresolved when the needs:code-review label is present or
    the review-required status is pending — a half-applied recovery leaves one
    without the other.
  • REVIEW_GATE.md documents the sweep and the app-id trap.

Why this is safe to run unattended: the sweep only ever removes a gate an
entitled ENGOWNER already approved away. It cannot create one, cannot lower a
gate nobody approved, and still fails closed when the owner list is
empty/unset — the same reasoning that already lets the event path skip risk
detection. A fully-cleared PR is not touched, so there's no 15-minute status
churn.

Test plan

The script is embedded in YAML, so I exercised it the way actions/github-script
does — compiled the body with AsyncFunction and ran it against a stubbed
Octokit recording every write. 12/12 assertions pass:

scenario expected result
A approval event, fork PR resolved by head_branch clears (unchanged) ✅
B the #4750 mode — sweep finds a gate whose clear run died clears ✅
C gated PR, no approval untouched, no status written ✅
D approval from a non-owner untouched ✅
E ENGOWNERS empty/unset clears nothing (fails closed) ✅
F status pending but label already gone still clears ✅
G already-cleared PR untouched (no churn) ✅
H one PR's API call throws mid-sweep others still clear, run marked failed ✅

Also: python3 -c "yaml.safe_load(...)" parses the workflow, and
pnpm check:changesets passes (CI-only change ships no package, so no
changeset).

Happy to hand over the harness if it's worth landing as a real test — I left it
out rather than add a YAML-string-eval test to CI unprompted.

One thing I noticed but did not touch

REVIEW_GATE.md says the gate is backed by "+ 1 required approving review
(native)", but live branch protection has required_approving_review_count: 0 —
review-required is carrying the whole gate on its own. That may well be
deliberate; flagging it rather than changing it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Aug 6, 2026
@vercel

vercel Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
astryx Ready Ready Preview Aug 12, 2026 3:57pm

Request Review

@github-actions

github-actions Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

🧪 Sandbox Preview

View Sandbox for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

No new or modified components detected.

Bundle Size Summary

No component packages changed.

Accessibility Audit

Status: No accessibility violations detected.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

github-actions Bot added a commit that referenced this pull request Aug 12, 2026
The approval event is one-shot: if review-clear's run dies, the gate stays
pending forever and only a human noticing recovers it. During the 2026-08-06
GitHub Actions incident the workflow failed in 'Set up job' (Failed to resolve
action download info: Service Unavailable) before any script ran, and #4750 sat
blocked on an approval it already had.

Add a 15-minute clear-only sweep to review-clear.yml, sharing the exact same
clearOne() as the event path so recovery can never drift from the live path. It
considers an open PR unresolved when the needs:code-review label is present OR
the review-required status is pending, and clears only when an entitled
ENGOWNER has approved -- it can remove a gate an approval already satisfied,
never create one, so it is safe unattended.

Also add workflow_dispatch for an immediate sweep, and document that a human
cannot hand-clear this gate: branch protection requires the review-required
context from the GitHub Actions app, so a status posted with a personal token
greens the rollup without satisfying the requirement.
@cixzhang
cixzhang force-pushed the review-gate-reconcile branch from 8d3b20c to 4d14de4 Compare August 12, 2026 15:55
@cixzhang cixzhang closed this Aug 14, 2026
@github-actions
github-actions Bot deleted the review-gate-reconcile branch August 14, 2026 06:33

This branch was successfully deployed

1 active deployment
Preview — 4d14de4c Deployed Aug 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant