release, nightly: resume a complete staged release; nightly publishes by id (stacked on #21137)

Merged
LA
21d ago
+419-116

Summary

This PR fixes the two follow-ups from the v0.65.2 0-asset publish for main: bead cx-sqadk (the release guard cannot see drafts) and bead cx-9ol90 (nightly uses a softprops tag lookup).

Stacked on #21137. The branch contains #21137's two commits plus one new commit (769cf27b82a02). Merge #21137 first, or merge this PR in its place, because it includes #21137. The same design is already reviewed for feat-cmux-next in #21139.

Changes (new commit)

  • release.yml guard: the guard now also lists drafts, because the tags endpoint returns 404 for them, and it refuses duplicate release objects. When the existing release (draft or published) already has every immutable asset, the run does not rebuild, because a rebuild makes new signed DMG bytes and publish-release-assets.py then refuses. The run resumes instead: it downloads the release's own appcast-arm64.xml, appcast-x86_64.xml and appcast.xml, publishes the release by id and uploads the appcasts to R2. Before this change, a failure between upload and publish could not be fixed by a rerun, and a missed R2 upload stayed missed.
  • New scripts/ci/finalize-release.py: publish publishes a release by id. It refuses when any other release exists for the tag, clears prerelease and sets the metadata, then sets draft=false and make_latest. It then checks that the tag resolves to that id with the expected assets. download takes assets from a staged draft and checks the digest; it does not send the token on the CDN redirect. Publish verified release now uses this script in place of #21137's inline bash.
  • nightly.yml: Publish verified nightly release metadata and Record verified nightly publication now publish the staged channel release by id, with the same body files, in place of the softprops/action-gh-release tag lookup. That lookup can create a second release and publish it with 0 assets when the channel release is still a draft.
  • publish-release-assets.py also reports asset_names. r2-upload-tests.yml now runs a load check of the new script.
  • The existing workflow-text assertions are changed to match the new steps. No new tests (behavior-test rule).

Verification

  • actionlint passes on release.yml, nightly.yml and r2-upload-tests.yml.
  • The script --help paths load correctly.
  • Per the no-tests-on-laptop rule, the Python tests were not run locally. CI runs them.

Changelog

none

Do not merge: Lawrence approval required for main merges.


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


Summary by cubic

Fixes the release and nightly publication paths that shipped v0.65.2 with 0 assets. The softprops/action-gh-release tag lookup cannot see draft releases, so it created a second release and published that one while the real assets stayed on the staged draft. Both workflows now publish the staged release by ID, the guard sees drafts and refuses duplicate release objects, and a rerun can resume a complete staged release instead of failing forever.

Bug Fixes

  • Release guard now lists drafts (the tags endpoint 404s for them) and fails when more than one release object exists for a tag.
  • A rerun resumes only a staged draft that already holds every immutable asset; it downloads the staged appcasts, publishes by ID, and uploads to R2, and requires the exact asset count seen by the guard so a demoted release is never republished.
  • New scripts/ci/finalize-release.py publishes a release by ID, refuses any other release for the tag, and verifies the published release by tag with expected assets.
  • publish-release-assets.py reports release_id, asset_count, and asset_names so following steps target the exact staged release.
  • Both nightly metadata steps publish the staged channel release by ID instead of the tag lookup.
  • r2-upload-tests now load-checks the new script.

Summary by CodeRabbit

  • Release Publishing
    • Release publication now verifies that the expected assets are present before publishing.
    • Staged releases with complete asset sets can resume without rebuilding, while incomplete or duplicate releases are flagged.
    • Published releases are checked to confirm they match the intended tag and assets.
    • Nightly release notes and metadata are finalized as part of the release process.