Desktop — release checklist
Walk this checklist before pushing a desktop-v* (or v* if CLI + desktop release together) tag. It's the gate between "code is QA-clean on every platform" (covered by desktop-qa-checklist.md) and "the release is published, signed, and announced".
A box left unticked is a release that ships broken. Resist the urge to bypass.
1. Code freeze
- [ ] All changes intended for the release are merged to
main. - [ ] CI is green on the head commit (lint, unit tests, e2e tests, Trivy).
- [ ] docs/desktop-qa-checklist.md — assignment grid filled, every cell signed off.
- [ ] No P0 or P1 bugs labelled
desktop-qaopen against the release branch.
2. Versioning
- [ ]
package.jsonversion bumped (orrelease-itran successfully and bumped it). - [ ]
charts/iterion/Chart.yamlappVersionmatchespackage.json(CI guard would block otherwise; verify locally withtask chart:sync-version). - [ ]
CHANGELOG.mdupdated — release-it writes it into the release commit itself; spot-check the new section for missing entries.
3. Signing prerequisites
These are hard prerequisites held outside the repo. Confirm each is current and accessible by the release operator before pushing the tag.
- [ ] Ed25519 updater key: GitHub secret
UPDATER_ED25519_PRIVATEis set, in PEM form, matches the public key embedded incmd/iterion-desktop/updater.go(updaterPublicKeyHexconstant). If the constant has changed since the last release, see "Key rotation" below. - [ ] macOS Apple Developer ID:
APPLE_DEVELOPER_ID_CERT(.p12) andAPPLE_DEVELOPER_ID_CERT_PASSWORDGitHub secrets present;APPLE_NOTARIZE_API_KEY(.p8) +APPLE_NOTARIZE_KEY_ID+APPLE_NOTARIZE_ISSUER_IDpresent. Cert validity > release date + 30 days. - [ ] Microsoft Authenticode:
WINDOWS_SIGNING_CERT(.pfx) andWINDOWS_SIGNING_CERT_PASSWORD(or SignPath / Azure Trusted Signing config) present. Cert validity > release date + 30 days. - [ ] GPG signing key for Linux:
GPG_PRIVATE_KEYandGPG_PASSPHRASEGitHub secrets present (for signing.deb+.AppImage). Public key published to the org's key server /KEYSfile in the release.
If any of these is missing or expired:
- For Ed25519: see "Key rotation".
- For Apple / Microsoft / GPG: pause the release until the operator with cert custody has refreshed the secret. Skipping signing on a public release is grounds to not ship.
4. Release-pipeline dry run (optional but recommended)
- [ ] On a feature branch, run
gh workflow run desktop-release.yml -f dry_run=true(if the workflow supports it) or use adesktop-vX.Y.Z-rc1pre-release tag. - [ ] Verify all 6 platform jobs succeed (macOS universal, windows/amd64, windows/arm64, linux/amd64, linux/arm64).
- [ ] Verify
generate-manifest.shproduced valid JSON (jq -e .against the artefact). - [ ] Verify the generated
.sigfiles are valid Ed25519 signatures of their corresponding artefacts (sample: download one binary + its.sig, runopenssl pkeyutl -verify -pubin -inkey updater_ed25519.pub -rawin -in <artefact> -sigfile <artefact>.sig).
5. Trigger the release
- [ ] Tag and push:
git tag v<X.Y.Z> && git push origin v<X.Y.Z>(or use therelease-itflow). - [ ] Watch
desktop-release.ymlsucceed end-to-end. - [ ] Watch
release.yml(CLI) succeed end-to-end (parallel job on the same tag). - [ ] Watch
brew-update.yml(workflow_runon the above) succeed and patch the brew tap's cask SHA.
6. Post-publish verification
- [ ]
gh release view v<X.Y.Z>shows all expected artefacts (6 binaries × {bundle, .sig} + manifest + manifest.sig + checksum + GPG sigs for Linux). - [ ] Download and run a binary on each platform that wasn't covered by CI:
- Open the .zip on a real Apple Silicon Mac →
/Applications/Iterion.appopens cleanly via Gatekeeper. - Run the .exe-installer on a Windows host → SmartScreen accepts (post Authenticode warmup).
chmod +xand run the AppImage on Ubuntu → opens.
- Open the .zip on a real Apple Silicon Mac →
- [ ] Auto-update test: install vN-1 on a real machine, run
Help → Check for updates, watch the upgrade complete. - [ ] Brew tap:
brew update && brew install iterion-desktop(orbrew upgrade iterion-desktop) → installs vN.
7. Announcement (optional but expected for v1.0)
- [ ] Release notes drafted from
CHANGELOG.mdand the manifesto's "what's new" framing. - [ ] GitHub Release body populated with the announcement.
- [ ] Blog post / changelog entry / tweet drafted.
- [ ] Update README.md "latest release" badges (if any).
- [ ] Update why-iterion.md "How to start" if the install URL or scaffolding differs.
8. Rollback contingency
If a release artefact ships a critical bug after publication:
- [ ] Yank the manifest: edit the GitHub Release to remove or replace
iterion-desktop-manifest.jsonso existing users don't auto-update to the broken version. New users land on a stale version, which is preferred. - [ ] Re-tag a
vX.Y.Z+1patch release with the fix and publish; auto-update will lift users off the broken version. - [ ] Revert the brew cask to the previous good version manually (the cask edits live in the iterion-brew tap repo).
- [ ] Communicate: pin a notice on the GitHub Release describing the issue, recommended action, and patch ETA.
- [ ] Post-mortem: track the regression that escaped CI/QA; add a scenario to desktop-qa-checklist.md so it can't recur.
Key rotation (Ed25519 updater key)
The Ed25519 keypair signing the manifest + artefacts is the trust root for auto-update. Rotate it when:
- The private key is exposed (anywhere outside the GitHub secret store).
- The release operator with custody changes (transfer is itself an exposure window).
- It's been > 2 years since last rotation (defence-in-depth; algorithm is fine, custody isn't).
Rotation procedure:
- Generate a new keypair:
./scripts/desktop/ed25519-keygen.sh ./new-keys. - Update
cmd/iterion-desktop/updater.goupdaterPublicKeyHexto the new public key (hex-encoded). - Cut a release with both the old and new public keys recognised — temporarily widen
verifyManifestto accept either signature, ship that release, wait until > 95% of installs have updated. - Cut a follow-up release that drops the old public key.
- Update the GitHub secret
UPDATER_ED25519_PRIVATEto the new key. - Securely destroy the old private key.
Without the dual-key bridge, users on the old version can't update past the rotation point because their embedded public key won't verify the new manifest.
What's not here
- CLI-only release process — covered by
release.ymland the conventional-commits / release-it flow. The desktop release rides the same tag. - Detailed cert provisioning (how to request an Apple Developer ID, etc.) — out of scope; once you have the cert, this checklist tells you how to use it.
- Marketing / press kit — that's a product call, not a release-engineering call.
