## Summary
Desktop Release Candidate only supports PR events today. Add a manual
dispatch with a required version input that validates the existing
`version-bump/<version>` branch. Require the workflow from `main` and
current repository admin permission for both the original actor and any
rerunner before checkout; API failures deny the run. Existing PR
validation and read-only token permissions are preserved.
GitHub can still accept a dispatch from a writer; the workflow rejects
that run before candidate checkout. This validates an existing candidate
and does not create or publish a release. Document the command in
`RELEASING.md`.
### Related issue
None found in open issue/PR title searches for "desktop release
candidate".
### Testing
- `actionlint .github/workflows/desktop-release-candidate.yml` passed.
- `bash scripts/test-desktop-release-candidate.sh` passed, including the
new authorization tests executed from the production workflow shell with
only the GitHub API mocked. Covers admin access, all lesser roles,
missing permission responses, API failures, rerunners, and non-main
dispatches.
- Mutation checks confirmed that removing the admin check, rerunner
check, or main-ref restriction fails the new tests.
- Self-review completed with no blocking findings.
- `just ci` is running locally; results will be updated here.
- Hosted manual dispatch has not been exercised: the new guard requires
dispatch from `main`, where this change is not merged. Human
verification is pending, so this PR remains a draft under `AGENTS.md`.
Once available on `main`, an admin can test with `gh workflow run
desktop-release-candidate.yml --repo block/buzz --ref main -f
version=<existing-candidate-version>`. Expect permission checks to pass
and the immutable candidate validator to run against that candidate. A
writer or a dispatch selecting another workflow branch should fail
before checkout. Manual runs do not replace the candidate PR's required
checks.
---------
Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
Co-authored-by: BigBoss <19a7c9f8477c0dd12d428c2b2faa352556cd13b3ec3d717498b60f85a57a90a9@buzz.block.builderlab.xyz>
## Summary
Redesign the permanent Desktop release flow so unrelated merges to
`main` cannot invalidate an already reviewed, green release candidate.
- Tag the immutable, API-confirmed release PR head instead of its later
squash commit.
- Treat the merged PR—including an authorized owner/admin bypass—as
publication authorization, while requiring trusted check evidence that
was complete at merge time.
- Make tag creation idempotent and collision-safe: an existing tag
succeeds only at the exact candidate SHA, and create races refetch
before accepting equality.
- Replace ancestry-based previous-release discovery with a validated
metadata ledger for side-history candidate tags.
- Compute the next release from the prior frozen base to the new frozen
base, excluding only the prior release squash SHA so unrelated commits
remain in the changelog.
- Preserve schema-1 production-tag migration and reject malformed
metadata or equal/decreasing versions.
- Update operator documentation for the normal squash-merge workflow.
This is the reusable release process for `0.5.6` onward, not the retired
one-shot `0.5.5` recovery path.
### Invariants covered
- Candidate creation → unrelated `main` merge → authorized squash merge
→ immutable candidate tag.
- Trusted producer IDs and merge-time completion timestamps; DCO's
bounded post-merge exception remains isolated.
- Missing/spoofed checks, tampered candidates, ambiguous PR
associations, conflicting tags, and equal/decreasing versions fail
closed.
- Same-SHA retries succeed; different-SHA collisions fail.
- Legacy schema-1 tag-on-main migration and schema-2 side-history
accounting both preserve the correct next-release changelog.
### Related issue
N/A — follows the Desktop release failures in #4788 and #4800 and the
recovery revert in #4808.
### Testing
At clean commit `6a91fbed8147a48cf174997de0c3e4cb2fb26474`:
- `scripts/test-desktop-release-candidate.sh`
- `scripts/test-release-ref-contract.sh`
Both focused suites passed with HEAD unchanged. Princess Donut cleared
the security/provenance surface, including the hostile merge-time
timestamp cases. Mongo cleared the side-history ledger, migration,
version-order, documentation, and contract-test surface.
---------
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary
- validate desktop release candidates before merge and keep the
repository squash-only
- tag the squash commit only after proving frozen-base parent and
complete-tree identity with the validated PR head
- accept either an exact-head approval or the durable Default-ruleset
bypass record as release authorization
- remove the unusable App-backed preparation workflow; retain `just
release-desktop`
## Ruleset follow-up
After this PR merges, update Default ruleset `13596885` to:
- enable strict required status checks
- dismiss stale reviews on push and require approval after the last push
- require the integration-bound `Desktop Release Candidate` check
The next desktop release should be cut only after that settings update.
## Verification
At commit `d8c254db427eedbcffac1a6e078e90d1d0f5e151` with a clean
worktree:
- `scripts/test-release-ref-contract.sh`
- `scripts/test-desktop-release-candidate.sh`
- `bash -n scripts/verify-desktop-release-merge.sh
scripts/prepare-desktop-release.sh scripts/test-release-ref-contract.sh`
- `git diff --check`
The bypass test fixture is the captured rule-suite shape from real
squash merge PR #2864 / suite `3520068134`.
---------
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>