feat(ci-status): add an opt-in mode in which no run waits for another - #652
Conversation
A contract-only run could only wait for the full run's ci-lanes verdict, holding a runner for up to the full run's wall and going red at the ceiling whenever the full run was slower. Two opt-in inputs remove the wait: - record-pending, called from the full run's first job, marks ci-lanes pending on the head SHA and stops. A contract-only run that reads the status while the lanes run then fails instead of carrying an older success forward. It writes only on a same-repository pull request event that is not contract-only, and passes with a notice otherwise. - rerun-contract-only-siblings makes a full run that records success call rerun-failed-jobs on every failed run of the same workflow on the SHA whose latest attempt has one failed job and every other job skipped. Full runs and the run itself are never re-run, and a re-run is contract-only again, so it cannot loop. A refusal only warns. carry-forward-wait-seconds '0' already read the status once with no Actions call; tests now pin that, and the README recommends it with a 3-minute job budget. The wait ceiling now counts elapsed wall-clock time instead of summed sleeps, and each carry-forward red names the remedy for the state it read (pending, failure or error, absent) instead of always saying to re-run the full workflow. Every existing input keeps its default; both new inputs default to false. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @kyle-sexton's task in 22s —— View job Security review — skipped
This PR is merged (state: If a security review is wanted on this change, it would need to run as a seat-run pass referencing the merged commit, or be re-triggered on a new PR/branch. |
|
Claude finished @kyle-sexton's task in 14s —— View job
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 89b13739d2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <"$gh_stdout")" | ||
| for id in $candidates; do | ||
| # shellcheck disable=SC2310 # gh_api handles its own errexit; the caller classifies the status. | ||
| if ! gh_api GET "repos/${REPOSITORY}/actions/runs/${id}/jobs?filter=latest&per_page=100"; then |
There was a problem hiding this comment.
Paginate the jobs before classifying contract-only runs
When a valid workflow expands past 100 jobs, this request retrieves only the first page: GitHub documents per_page as capped at 100, while a matrix may create up to 256 jobs (jobs endpoint, matrix limit). The following shape test therefore may not see the failed gate on a later page, so rerun-contract-only-siblings silently leaves that contract-only run red; fetch and combine every jobs page before classifying it.
Useful? React with 👍 / 👎.
No related issue: ci-workflows has no issue for this; it is the upstream half of the no-wait
ci-statusdesign for claude-code-plugins (see Related).Summary
A contract-only run (
edited,labeled,unlabeled) could only wait for the full run'sci-lanesverdict. It held a runner for up to the full run's wall and went red at the ceiling whenever the full run was slower. This adds an opt-in mode in which no run waits for another. Every existing input keeps its default, so current consumers are unaffected.New inputs on
.github/actions/ci-status(both default'false'):record-pending: called from the full run's first job, it marksci-lanespendingon the head SHA and stops. A contract-only run that reads the status while the lanes run then fails instead of carrying an oldersuccessforward (a draft run's, for example). The full run's gate overwrites the marker with its verdict. It writes only on a same-repository pull request event that is not contract-only; otherwise it passes with a notice. Needsstatuses: write.rerun-contract-only-siblings: after a full run recordssuccess, it callsPOST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobson every failed run of the same workflow on the SHA whose latest attempt has one failed job and every other job skipped. Full runs and the run itself are never re-run, and a re-run attempt is contract-only again, so it cannot loop. Needsactions: write; a refusal only warns and never changes the recorded verdict.Recommended consumer setting:
carry-forward-wait-seconds: '0',timeout-minutes: 3, both inputs'true'.Fix
carry-forward-wait-seconds: '0'already read the status once and made no Actions call (run.shgates the wait on> 0). Unchanged; now pinned by tests that count exactly one status read and no sleep, and documented as the recommendation.date +%s), API calls included, instead of summed sleeps. A large ceiling no longer overruns the job budget sized for it.pendingnames the full run in flight (itsci-statussupersedes the red),failure/errornames the run that recorded it, absent gives both cases. Withrerun-contract-only-siblingson, the closing sentence says the full run re-runs this run, and to re-run it by hand only if it stays red.write_statushelper with the same retries; its refusal message now says "the calling job needs statuses: write".Verification
Local (Windows, Git Bash):
bash .github/actions/ci-status/run.test.sh: 81 cases, all pass (61 before this change). New cases cover: wait0reads the status exactly once with no sleep and no Actions call (red and green); the ceiling counts wall-clock time (a listing that takes 10 s reaches a 30 s ceiling after one sleep); pending newer than success fails; the success path re-runs only the failed contract-only sibling, never a failed full run, a single-job run, a green/in-flight/cancelled run, or itself, and only after the status write; failure, default-off and fork runs re-run nothing; a refused re-run, a failed jobs read, a 403 listing and a malformed listing all warn and keep the run green; a contract-only run with the input on never re-runs anything; pending mode writes onpull_request/pull_request_target, skips on contract-only, fork and push, fails on a refused write; invalid values for both inputs are rejected; both inputs default to'false'inaction.yml.node --test .github/scripts/*.test.cjs: 159 pass, 0 fail.shellcheck --rcfile .shellcheckrcandshfmt -don the composite: clean.actionlint .github/workflows/ci.yml: clean.markdownlint-cli2@0.23.2 README.md: 0 issues.Not exercised here: the live
rerun-failed-jobscall with aGITHUB_TOKENholdingactions: write. GitHub's permissions table lists the endpoint under Actions write for installation tokens; the first consumer probe settles it.Related
ci-status1500 s / 28 min values this mode replaces.🤖 Generated with Claude Code