ci(nightly-next tick): one shared job group instead of a polling coalescer; list push runs once per tick

Merged
TE
12d ago
+70-80

The repository's GITHUB_TOKEN (Actions installation token) ran out of hourly quota. Since 21:10Z on 2026-10-25 every NEXT nightly's legacy-identity publish has failed with HTTP 403: API rate limit exceeded for installation (runs 40234225207, 40235404801, 40236532331, 40240049419). Leo's rule is that a nightly is never more than 30 minutes stale.

The nightly-next tick was the biggest GITHUB_TOKEN spender we found by reading the code. This PR cuts both of its loops:

  1. Polling coalescer removed. The coalesce job called listWorkflowRuns every 15 s, up to 48 times per waiting tick. In its place the request job gets a job-level concurrency: {group: nightly-next-tick, cancel-in-progress: false}. GitHub keeps one tick running and the newest one pending, and a newer tick replaces an older pending one. A tick dispatches nothing but main's nightly.yml and reads the branch tip when it starts, so a replaced pending tick loses nothing. This group cannot cancel any build: builds run in nightly.yml, whose groups are unchanged, and tests/test_nightly_delivery_concurrency.py still bans cancel-in-progress: true on every delivery workflow. A dispatch with an explicit sha gets its own group, so a later tick never replaces it.
  2. One listing per tick, not one per commit. The request loop walks up to 120 commits, and each request-nightly-next.sh --tree-ready call listed 99 cmux-next push runs and then read the jobs of every matching run. Two changes, made in the tick so they work for every historical revision of the script:
    • A gh shim placed first on PATH caches only the two read-only listings (actions/workflows/cmux-next.yml/runs?…, actions/runs/N/jobs?…) for the length of the tick. A failed read is never cached.
    • A commit whose v2 cmux-tui tree key a newer commit already asked about gets the same answer, so the loop skips it. This applies only when nightly-next's commit is in the checkout's history, which gives every call the same lower bound.

Estimate from reading the code (not measured): the tick used several hundred to a few thousand GITHUB_TOKEN calls per hour. Now it makes roughly 2 to 15 calls per tick: one runs listing, one jobs read per candidate run, and one dispatch. With ticks on every cmux-next and cmux-tui completion plus the :07/:37 cron, that comes to tens of calls per hour.

Risk: low. The tick is a dispatcher only, the same request-nightly-next.sh makes every decision, and builds are untouched. The companion feat-cmux-next PR switches the legacy publish's DMG download to the public URL.

Review: independent Codex (gpt-6-astra, xhigh). The first pass returned BLOCK on two findings: the dedupe lower bound, and old script revisions bypassing a script-side cache. Both are fixed, and the second pass returned SHIP.

Checks run locally: tests/test_nightly_delivery_concurrency.py, actionlint, and the shim against a fake gh (cache hit, failure not cached, other calls passed through).

šŸ¤– Generated with Claude Code

Agent session: cosmic-gray


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Summary by CodeRabbit

  • Chores
    • Nightly update runs now allow one tick to run at a time, with the newest eligible tick waiting until the current run finishes.
    • Nightly scans skip changes whose matching update has already been encountered in that scan, reducing redundant processing.
    • Nightly update runs are triggered only by push runs from the same repository.