fleet-status: compute the lanes for fork PRs - #107
Conversation
Fork PRs could never get fleet/verify or fleet/review, both required checks: the job skipped a fork head on every event and the script refused one. Redline now reviews fork PRs, so an outside contributor's PR that Redline approved and whose required CI passed stayed blocked. - fleet/review on a fork is Redline's verdict at the head (approved is success, changes requested is failure, none is pending), not held for verification. - fleet/verify on a fork is the base branch's required checks passing at the head. Where none are required it stays pending: the operator verifies and merges. The label and verification comment never verify a fork. - The job runs for a fork only on issue_comment and workflow_run, which run the default branch's workflow with a write token. A fork's pull_request and pull_request_review events run the PR merge ref's workflow with a read-only token, so they stay excluded. The new Fleet review relay workflow turns a fork review into a workflow_run. A fork's workflow_run lists no PRs, so the script finds them by head repo and branch. - No step checks out or runs PR head code; the script only calls the REST API.
Deploying amnesia-site with
|
| Latest commit: |
225aeeb
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://339ed364.amnesia-site.pages.dev |
| Branch Preview URL: | https://fleet-fork-prs-computed.amnesia-site.pages.dev |
sprayberry-redline
left a comment
There was a problem hiding this comment.
Approve at 225aeeb.
The change lets a fork PR earn both required lane statuses without any seat verifying it: fleet/verify becomes the base branch's required checks passing at the head, and fleet/review becomes the verdict at the head with no verification hold. I traced the new if: in .github/workflows/fleet-status.yml for each event shape and it admits a fork only on issue_comment and on workflow_run of a listed workflow whose head_repository is not this repository, which are the two paths that run the default branch's script with a write token; a fork's own pull_request and pull_request_review runs still fall through every branch. The fork workflow_run path hands the script HEAD_REPO and HEAD_BRANCH through env, not inline in run:, and the script only puts the branch through encodeURIComponent into the head=owner:branch query, so an attacker-named branch has nowhere to land. prsFromHead correctly re-checks head.repo.full_name since the head filter matches the owner alone, and the CLI test at scripts/fleet-status.test.mjs pins that with a same-named branch in another of the owner's repos. In laneStatuses, verified still becomes true from requiredCi === 'passed' for a fork, and the !fork guard only removes the label-plus-comment route, which the test with labels: ['verified'] and a matching verification comment covers.
Minor, not blocking: a workflow_run whose head_repository is null (a deleted fork) passes the != github.repository branch and the script then exits 2 for want of a PR number; that run attaches to the default branch, not a PR, so nothing is blocked by it.
Problem
fleet/verify and fleet/review are required checks, and a fork PR could never get either one. The status job skipped a fork head on every event, and the script refused a fork ("the fleet does not review it"). Redline now reviews fork PRs, so an outside contributor's PR that Redline approved and whose required CI passed stayed blocked with no way through.
Rule for a fork PR
Which events run for a fork, and the safety invariant
Tests
The fleet-status test covers a fork approved at head with required CI green (both success), changes requested (review failure), no required checks (verify pending with the operator description), CLI runs against a stubbed GitHub (PR number and head-branch lookup), the job's
if:evaluated per event (a fork's pull_request and pull_request_review do not run it; a fork's workflow_run and a PR comment do), and same-repo behavior unchanged. The new cases fail against the default branch's script and workflows. actionlint is clean.