Release process
How Apollo Download Manager is versioned, how a version's changelog is written, how candidates and releases are tagged (#84), and how a release is made (#18). Who may tag, and the branch rules around releases, are in DEVELOPMENT_WORKFLOW.md. Building a candidate is RELEASE_CANDIDATES.md.
The version
Semantic Versioning:
MAJOR.MINOR.PATCH. While Apollo Download Manager is below 1.0.0, a minor version may break things, as SemVer allows for 0.y.z. The first release candidate isv0.1.0-rc.1(PO decision on #84).One value:
package.json'sversionis the source.Tauri reads it for the app and its packages:
src-tauri/tauri.conf.jsonsays"version": "../package.json"(Tauri'sversion).The browser extension's manifest is built from it (
scripts/build-extension.mjs).Cargo can't read another file, so
[workspace.package] versioninCargo.tomlrepeats it, and every crate takes it (version.workspace = true). The programs report it throughCARGO_PKG_VERSION: the app's About screen, the user agent and the torrent client's identity.
A test fails while they differ (
scripts/version-lib.test.mjs), and the release-candidate workflow refuses a tag whose version isn'tpackage.json's.Changing it:
pnpm version:set <MAJOR.MINOR.PATCH>setspackage.jsonandCargo.toml, then updates only Apollo Download Manager's own crates inCargo.lock(cargo update --workspace). The contract fixturetests/fixtures/contract/app-info.jsonholds the version too: regenerate it withVELOCITY_UPDATE_FIXTURES=1 cargo test -p velocity-core --lib contract(found on 0.1.1, #342). Commit the four files in one pull request with the changelog section, such aschore: version 0.2.0 (#N).A pre-release is a tag, not a version: the files say
0.2.0, and its candidates are the tagsv0.2.0-rc.1,v0.2.0-rc.2.
Choosing the next version
The PO decides each version, from what the release contains (PO decisions on #258, 2026-11-01).
The biggest change sets it:
The release contains From 0.1.0 it becomes Part raised Bug fixes only 0.1.1 PATCH At least one new feature, with or without fixes 0.2.0 MINOR. PATCH goes back to 0 A change that breaks something for users 0.2.0 below 1.0.0; from 1.0.0, the next MAJOR MINOR below 1.0.0, then MAJOR Releases are built from
main. Once a feature is merged, the next release can only be a MINOR one. So while a PATCH release is planned, only fixes are merged intomainuntil it's tagged, and features wait.Checking before a candidate:
pnpm changelog <last tag>groups the merged pull requests by their title's type. Afeat:pull request means a MINOR release at least. If every title isfix:,docs:,test:,ci:,build:orchore:, a PATCH is enough.Version milestones: each planned release has a GitHub milestone named after it, such as
v0.1.1, holding the issues it's planned to contain. The milestones R1 to R10 hold the rest of the roadmap (epic #1).The plan (PO decisions, 2026-11-01, revised 2026-11-05, 2026-11-07 and 2026-11-10):
Version What it contains Status 0.1.0 The first release, Windows and Linux Released 2026-10-31, as a pre-release 0.1.1 Fixes only: the download log (#251), connections (#221), the battle test (#77) and the bugs it and the PO's testing found Released 2026-11-04, as a pre-release 0.2.0 The new name, Apollo Download Manager, with its new window; the browser extension in the Chrome Web Store; the user guide in the app and the website; and features such as a local .metalinkfile (#222), the login window (#249) and plain error messages (#252). The Edge and Firefox store pages follow in a later version (#240, #241)This version 0.3.0 The load and long-run field test (#337), the ramp field test (#330), mirrors (#324), the extension finding the files on a page (#426), the guide audit (#425), research on other download managers (#427), release signing (#428, #429) and legal due diligence (#441) Next 1.0.0 The first production release, after the release-readiness review (RELEASE_READINESS.md, #78), with the PO's decision on each of its gaps Later Every release before 1.0.0 is published as a pre-release.
The changelog
CHANGELOG.md has one section a version, newest first, under an Unreleased section for what has merged since the last one.
Drafted from the pull requests: every pull request is squash-merged with a Conventional Commit title (DEVELOPMENT_WORKFLOW.md), so
main's first-parent history is the list of changes.pnpm changelog <from> [<to>] [--heading "<heading>"]prints a section for the commits after<from>(a tag, a commit, orstart) up to<to>(origin/mainby default).The groups, in order: Breaking changes (a
!after the type), Features (feat), Fixes (fix), Performance (perf), Security (security), Documentation (docs), Packaging and builds (build), Continuous integration (ci), Tests (test), and Other changes (chore,refactor,style,revert, and any other type). Each line is the title's description, its scope in bold, and its issue and pull request, such as- **ui:** the column chooser keeps Name (#59, PR #200).Titles that aren't Conventional Commits go under Other changes as they are, and the command lists them, so they can be reworded.
Edited by hand into release notes: the draft is a starting point. Before a release the PO, or an agent on the PO's request, rewrites the lines users need to read, drops what doesn't concern them, and adds upgrade notes, such as settings V1 had that Apollo Download Manager dropped. The rules are in
scripts/changelog-lib.mjs.
Tags
Only on verified
maincommits: a commit onmainwhose Main checks run passed.vX.Y.Z-rc.Nfor a release candidate. Pushing one starts the Release candidate workflow (RELEASE_CANDIDATES.md).vX.Y.Zfor a release, on the commit of the candidate the PO accepted (#18).Never moved or deleted. A failed candidate is followed by
-rc.N+1.Who: the PO only. The Release Tags ruleset lets only admins create, move or delete
v*tags (REPOSITORY_SETTINGS.md), so an agent prepares the exact command and the PO runs it.
Before a candidate
RELEASE_READINESS.md is brought up to date for the version, and the PO decides each of its open gaps.
The /release-candidate skill walks through these, and changes nothing without the PO's approval:
mainis green: the latest Main checks run on the commit passed.package.jsonhas the version to release, and the version test passes.CHANGELOG.md's section for it is written:pnpm changelog <last tag or start> --heading "<version> - <date>", edited.The PO tags
v<version>-rc.<N>on that commit, or starts the workflow by hand (RELEASE_CANDIDATES.md).The candidate's
build-info.jsonandSHA256SUMSmatch the commit, and the PO tests it beside V1.
Making the release
Once the PO accepts a candidate, its installers are the release: the release workflow publishes them as they are, rather than build again, so what was tested is what is released (#18). Tauri's builds aren't byte-for-byte reproducible, so a rebuild couldn't match the candidate's checksums.
The PO tags
vX.Y.Zon the accepted candidate's commit, within 14 days of its build, while its files are kept.The Release workflow (
release.yml) starts on the tag:verifyrefuses a tag that isn'tv<package.json version>, isn't onmain, has no green Main checks run, or isn't on a candidate's commit (av<version>-rc.Ntag; the highest N is the one released). It finds the candidate's run and artifact. Its files gone, it refuses: tag a new candidate.assembledownloads the candidate, checks every file against itsSHA256SUMS, and names themapollo-download-manager-<version>-<what>, such asapollo-download-manager-0.2.0-windows-x64-setup.exe(velocity-v2-…until 0.1.1), andbuild-info.jsonasapollo-download-manager-<version>-build-info.json(#452), with a newSHA256SUMS. It attests their build provenance with GitHub's artifact attestations, and takes the notes fromCHANGELOG.md's## <version>section; without one it refuses. The section's links into the repository, such asdocs/user/installing.md, become full links to that file at the version's tag, since a release page can't follow a relative one (#452).draftwaits in thereleaseenvironment for the PO's approval (below), then creates a draft GitHub release with the files and the notes, marked as a pre-release for a version below 1.0.0 (#452). It is the only job that may write.
The PO publishes the draft, on GitHub, after a last look. Nothing publishes it automatically.
The website's download page updates by itself: publishing the release starts the Website workflow, which rebuilds the site from
mainwith the new files (WEBSITE.md).
The release environment
The PO creates it once, in Settings, Environments: named release, with the PO as its required reviewer (self-review allowed, since the PO approves their own release), and deployments limited to tags v*. On GitHub Free, Pro and Team plans, required reviewers are only available for public repositories (deployments and environments), so it is set up once the repository is public. Without it, the draft job would run without waiting.
Anyone can check a downloaded file's provenance: gh attestation verify <file> --repo Singlbase-Technologies-Limited/apollo-download-manager. The rules are in scripts/release-lib.mjs.