Skip to content

ci(fleet-status): page check runs; pull_request_target workflows refresh the lanes - #83

Merged
askalf merged 2 commits into
mainfrom
ci/fleet-status-paging
Sep 25, 2026
Merged

askalf merged 2 commits into
mainfrom
ci/fleet-status-paging

Conversation

@askalf

@askalf askalf commented Sep 25, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Two fixes to scripts/fleet-status.mjs and its workflow. Both must be in place before the fleet/* contexts become required checks.

  • Check runs are read across every page. The script read one page of 100 check runs at the PR head. Every PR event (push, review, comment, CI completion) adds Fleet status check runs at that head, so a busy PR passes 100. Its required checks, created at push time, then fall off the first page and fleet/verify goes back to pending. Paging is now one pure helper, collectPages(), used for check runs and the list endpoints alike.
  • pull_request_target workflows refresh the lanes too. A pull_request_target run's checks land on the PR head (the run's head_sha is the PR's), so such a workflow can produce a required check. The status job now accepts workflow_run events from both pull_request and pull_request_target runs, and the workflow_run list names PR triage again.

How to test

  • node scripts/fleet-status.test.mjs. Paging tests: 101 rows over two pages, a full last page, a short first page, and a required check found on page 2. The list test requires every pull_request and pull_request_target workflow to be listed, and checks that the status job's condition accepts both events.
  • This PR's own fleet/* statuses come from the copy already on the default branch.

…esh the lanes

- The check-runs list was read as one page of 100. Every PR event adds Fleet
  status check runs at the head, so a busy head passes 100 and its push-time
  required checks drop off the page, sending fleet/verify back to pending.
  Paging is one pure helper, collectPages(), used for check runs and the list
  endpoints, with a test that finds a required check on page 2.
- A pull_request_target run's checks land on the PR head (its head_sha is the
  PR's), so such a workflow can produce a required check. The status job now
  accepts workflow_run events from pull_request and pull_request_target runs,
  the list names PR triage, and the list test covers both kinds and the job's
  condition.
@askalf askalf added the author-fixes The PR's author answers its reviews; no fleet fix ticket label Sep 25, 2026
@github-actions github-actions Bot added github_actions Pull requests that update GitHub Actions code size/M 50-199 hand-written lines labels Sep 25, 2026

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Automated review from the Sprayberry Labs fleet code reviewer.
Reviewed by the GPT gating lane (gating review).

Verdict: APPROVE — no blocking issues found in the live-head diff.

I reviewed the workflow event filter, the paginated check-run/status collection, and the focused regression coverage. The pagination helper terminates on the first short page and the newly paginated check-run request preserves the existing ordering and required-check evaluation. The workflow change includes PR-triage completions and admits both pull-request event types. Required CI is passing at fac49cc2bd61758e4f8c61094584be06b77ab573 (analyze, docker-build, and test).

What's good: the change centralizes the page-walking behavior in a small reusable helper and covers the key page-boundary cases, including a required check appearing on page two.

The fleet now labels PRs whose author answers their own reviews with
`author-fixes`, and the label exists on the repository. The label-manifest check
compares .github/labels.json with the live labels, so every PR's check failed
until the manifest declares it too.

@sprayberry-secondread sprayberry-secondread left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Automated review from the Sprayberry Labs fleet code reviewer.

Reviewed by the Claude second-opinion lane (independent second read; the gating review is posted separately).

Verdict: no blocking issues at 1be3ec0. Paging and the pull_request_target widening are correct, and the new tests fail without the change.

Note: the ticket named head fac49cc. The PR has since moved to 1be3ec0 (chore(labels): declare author-fixes in the label manifest), so this read covers the live head 1be3ec0.

Boundaries (rebuilt from the diff)

collectPages at scripts/fleet-status.mjs:145-152, stop predicate if (rows.length < size) return out;

Input Behaviour Pinned by
empty first page (0 rows) returns [] after one call not directly. The same 0 < 100 branch runs on the empty third page in pager([100, 100])
short first page (5) one page, 5 rows a short first page is the only page
exactly size (100), then 1 reads page 2, 101 rows 101 rows over two pages are all read
full last page (100, 100) reads an empty page 3, 200 rows a full last page reads one more, empty, page
required check only on page 2 counted a required check on page 2 counts
check-runs body missing check_runs ?? [] gives 0 rows, loop stops not tested (inline in the main block)
HTTP error on page n gh() throws, the existing try marks it pending pre-existing behaviour, unchanged

Row order across pages does not matter. runs is still sorted by id after collection (:257). statuses keep their .reverse() over the whole concatenation, so the last-state-wins order in requiredCiState does not change.

fleet-status.yml condition, contains(fromJSON('["pull_request","pull_request_target"]'), github.event.workflow_run.event):

  • pull_request works as before.
  • pull_request_target is now accepted. I checked this against a real run: the PR triage run 36096549203 on this PR has event=pull_request_target, head_sha=1be3ec0… and pull_requests=[83]. So PR: resolves and its checks land on the PR head, as the body says.
  • Any other event is still dropped.
  • Fork PR via pull_request_target: still gated by head_repository.full_name == github.repository, and readFacts re-checks p.head.repo.full_name anyway. The job checks out scripts/fleet-status.mjs from the default branch, not from the PR, so the wider trigger does not run PR code with statuses: write.

Tests fail without the change

  • The paging block imports collectPages, which does not exist on base, so the whole file fails there.
  • workflow_run lists "PR triage" fails against the base yml, which lacks 'PR triage'.
  • The condition regex /\["pull_request","pull_request_target"\]/ fails against the base == 'pull_request'.
  • The if (listed.length) guard does not make the condition check vacuous. An empty listed would already fail the per-workflow listed.includes(...) checks for build/ci/CodeQL/labels.

PR body claims vs diff

  • "one pure helper, collectPages(), used for check runs and the list endpoints alike": true. ghAll (:220-222) and the check-runs read (:255-256) both go through it.
  • "accepts workflow_run events from both": true (yml :29-30).
  • "the workflow_run list names PR triage again": true (yml :18).

Info (non-blocking)

  • .github/labels.json:1 adds {"color":"BFD4F2","description":"The PR's author answers its reviews; no fleet fix ticket","name":"author-fixes"}, but the PR body does not mention it. I checked it against the live label: color and description match exactly, it is in alphabetical order, and manifest matches the repo passes at 1be3ec0. It changes no behaviour, but a one-line mention in the body would keep the description accurate for the squash message.

What's good

  • Pulling the stop rule into a pure, injectable helper removes the duplicate loop and makes the page-2 case testable without the network.
  • The rewritten workflow-list test is simpler than the two-branch version it replaces and still guards the new rule.

Checked: the full diff (4 files, +42/−21), the surrounding readFacts/gh/requiredCiState code, pr-triage.yml's trigger, a live pull_request_target run payload, the live label, and gh pr checks (all required checks pass). I did not run the suite locally; CI test and self-test pass at this head.

SECOND READ: READY

@sprayberry-redline sprayberry-redline left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Automated review from the Sprayberry Labs fleet code reviewer.

Reviewed by the GPT gating lane (gating review).

Verdict: approve — no blocking issues found.

I reviewed the live-head diff in .github/workflows/fleet-status.yml, scripts/fleet-status.mjs, and scripts/fleet-status.test.mjs. The shared collectPages() helper now reads through the first short page for both list endpoints and check runs; the new cases cover a second-page required check, a full final page followed by an empty page, and a short first page. The workflow filter admits both pull_request and pull_request_target completion events while retaining the repository and PR association guards. The label-manifest update matches the live author-fixes label.

What's good: required CI at 1be3ec0ae522f5bafc73f5a47a7e392604d2f48d is green (analyze (javascript-typescript), docker-build, and test). I did not run the local test suite, per review environment policy.

@askalf
askalf merged commit 802e46d into main Sep 25, 2026
24 checks passed
@askalf
askalf deleted the ci/fleet-status-paging branch September 25, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-fixes The PR's author answers its reviews; no fleet fix ticket github_actions Pull requests that update GitHub Actions code size/M 50-199 hand-written lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants