ADR-0007: Automated release on every merge to main¶
Status: Accepted, with known risks
Context¶
Sevak has one maintainer and no release manager. Manual releases drift: fixes
sit on main for weeks, installed copies stay vulnerable, and version numbers
and changelogs are done late or wrongly. Users also get fixes only if the
update path is trivial.
Decision¶
Every push to main ships a release, unless it touches only documentation or
the head commit contains [skip release]
(.github/workflows/release.yml).
- Plan. The next version is computed from the commit subjects since the
last
vX.Y.Ztag (scripts/release-version.mjs):feat:raises the minor version, a breaking change (feat!:or aBREAKING CHANGE:footer) the major one (the minor one while on 0.x), anything else the patch version. A draft GitHub release is opened for the commit. - Build. Installers are built on Windows (NSIS, MSI), macOS (universal
app and dmg) and Linux (deb, rpm, AppImage) and signed for the updater with
a minisign key held in repository secrets (
TAURI_SIGNING_PRIVATE_KEY). - Publish.
latest.json(the manifest installed copies poll) andSHA256SUMS.txtare attached and the draft is published, which creates the tag. A failed build leaves only a draft and no tag. - Distribute. winget, Scoop, Homebrew and the AUR are updated when their secrets are configured.
The workflow relies on main being protected and on CI having passed on the
pull request that was merged (its header says so; the repository settings are
not part of this repository), so the release is of reviewed, tested code. The
workflow does not re-run the tests. Conventional Commit
subjects are therefore a release mechanism: a wrongly typed commit changes the
version number.
Consequences¶
Benefits:
- Fixes reach users in hours, with no release ceremony; security fixes use the same path as any other change.
- Version numbers are derived, so they cannot be forgotten.
Risks, accepted knowingly:
- A bad merge is a bad release. There is no soak period, staged rollout or
channel: whatever lands on
mainis offered to every installed copy at its next update check (every six hours, and when the launcher opens after an hour). The mitigations are required CI, the user's own consent before an update installs, and the speed of shipping a fix. Rolling back means releasing a higher version. - The pipeline is the crown jewel. Anyone who can merge to
main, or who can change the workflow or read the signing secrets, can ship code to every user, signed with the one key the updater trusts. Protecting the account, branch protection, secrets and the actions the workflow uses is part of Sevak's security, not only of its hygiene (see the threat model). - No second factor on integrity.
SHA256SUMS.txtis published beside the files it covers, so it detects corruption but not a compromised release. Windows and macOS builds are not yet code-signed or notarized, so the OS warnings users see cannot distinguish a genuine from a tampered build either. - Frequent releases are noisy for package-manager maintainers and for
users who keep every update prompt;
[general] check_for_updatescan be turned off, and package-manager installs update through the manager.