ci(nightly-next): the old feed's copy publishes from any run, and its gate reports every run

TE
7d ago
+30-8

Leo: "where's the nightly?" His cmux NIGHTLY.app (com.cmuxterm.app.nightly) reads https://files-next.cmux.com/nightly-next/appcast-arm64.xml, and that feed's newest item has been build 4093446036501 (Thu 29 Oct 19:55 GMT) for 27 hours. Over the same time the cmux NEXT feed (/nightly-next/next/) kept publishing.

Why the old feed got nothing

These are the runs since 29 Oct 19:00Z: 100 nightly-next runs and every attempt of each.

  • legacy-identity-target succeeded 42 times. It picked the newest cmux NEXT build each time.
  • sign-nightly-identity-legacy (owned Mac) never signed: 34 cancelled and 10 failed. The failures were claim-gate refusals. For example, run 41136161064 at 22:42Z: glaeda-signing-hooks.txt at this run's commit does not list this hook (3b7fc168de01). #28548 added that hook at 22:30Z, and glaeda already pins the next one, 5d5ce6e8 (#28569).
  • sign-nightly-identity-legacy-blacksmith never got a runner: 38 cancelled. 26 of them were on blacksmith-6vcpu-macos-26 and 4 on -12vcpu-. Blacksmith macOS reports "slow", with 34 queued on 6 vCPU and the oldest waiting 40 min. After the 600 s stall time, the owned-pool rescue cancels the run and re-runs it. Run 41126559170 went through 4 attempts this way.
  • The re-runs had a second bug. A full re-run (attempts 3 and 4) skips publish-nightly, because the build is already on the NEXT feed. publish-nightly-identity-legacy required this run's publish-nightly to have published the target build, so even a sign that finished in a re-run could never publish. nightly-identity-legacy-published also required publish-nightly success. So that gate skipped instead of going red, and nothing alarmed except the feed watch.

What changes (.github/workflows/nightly.yml)

  • publish-nightly-identity-legacy also runs when legacy-identity-target.outputs.source_run is empty. That means the target came from the live cmux NEXT feed and is not this run's own unpublished build. Any run can now publish it: a rescue's re-run, a run whose app build failed, or a newer run. The job's order check (it refuses a build the old feed already has or has passed), the tested-digest gate and its single-writer concurrency group are unchanged. A target that is this run's own build still needs this run's publish-nightly to have published it.
  • nightly-identity-legacy-published runs in every run where legacy-identity-target ran, whatever cmux NEXT's publication did. It is red when the copy neither published nor is pending. The one exception is a target that is this run's own build which cmux NEXT did not publish (publish-nightly refused, failed or skipped): the gate posts a notice and the old feed waits.

No concurrency or cancel settings change. Every nightly group keeps cancel-in-progress: false. nightly.yml is 489,920 bytes, under the 490,000 cap.

Not in this PR (owned elsewhere)

  • Runner capacity for the legacy sign is the larger cause. #28570 (dep-fleet-3) lets a re-run that picks again sign on an owned Mac first. #28569 (cmux-bot) trusts glaeda hook 5d5ce6e8.
  • #20816 (austinywang, 15 Oct, against nightly-next) defers publication after pending-artifact lookup errors. That is a different failure, and it does not fix this one.

Tests

  • tests/test_nightly_next_post_publish.py: the legacy publish if must contain the source_run == '' clause. Passes locally.
  • tests/test_nightly_next_ring.py LegacyPublishedTests: the gate's if no longer reads publish-nightly. It reads NEXT_OK and SOURCE_RUN instead. New cases: a re-run's feed build that did not publish is red, and this run's own unpublished build waits. CI runs these (workflow-guard-tests).

Risk: medium-low. This is CI only and changes only the old-feed copy. Within a run, publishing still happens only after this run's own sign and verify passed, and only the tested DMG is published.

Agent session: agent session

🤖 Generated with Claude Code