Release
Releases happen on their own when a pull request merges into main. No
one tags or uploads by hand.
What a merge does
- The CI workflow runs every check on the merged commit. The
commitscheck belongs to a pull request and has its own workflow, so it does not run here. - If
fmt,clippy,test,doc,licensesanddocspass, thereleasejob runscog bump --auto. It reads the commit subjects since the last tag:- a
featcommit bumps the minor version; - a
fixcommit bumps the patch version; - any other type alone bumps nothing. The job ends green and the change ships with the next release;
- a breaking change (
!after the type or scope) bumps nothing more while the project is below 1.0:feat!bumps the minor version,fix!the patch version, andchore!nothing. From 1.0 on, a commit of any type with!, or with a body line such asBREAKING CHANGE: the flag is goneorBREAKING-CHANGE: ..., bumps the major version.
- a
- A bump runs
cargo xtask set-versionas its pre-bump hook, which writes the version intoCargo.toml,Cargo.lockandfuzz/Cargo.lock. Cog then updatesCHANGELOG.mdand creates the commitchore(version): vX.Y.Zwith the tagvX.Y.Z. - The job pushes the commit and the tag in one atomic push with the
release deploy key. The main ruleset lets only that key push to
maindirectly. The private key is a secret of thereleaseenvironment, which onlymainmay deploy to, so a workflow on another branch cannot read it. - The tag starts the publish workflow. It stops unless the tag is
vX.Y.Zand its commit is onmain. It builds the macOS arm64 binary, the universal plug-in host, the man pages, the shell completions andTHIRD-PARTY-LICENSES.html. It checks that the host holds both slices and that both binaries print the tag’s version. The host’s x86_64 slice runs only where the runner has Rosetta; without it, the workflow warns and checks the arm64 slice alone. The notices cover the workspace: both binaries, which share only the core crate, and the three crates that only xtask uses. The workflow checks that they namevst3-host. The job packs each folder inplugins/as its own zip archive and publishes a release with the changelog section as its notes. The notes end with a line that names both binaries.
The version commit starts the CI workflow again. The release job skips a
commit whose subject starts with chore(version), so the loop stops there.
The test job runs the xtask test
the_fuzz_lock_names_the_workspace_version, which fails when Cargo.lock
and fuzz/Cargo.lock name different versions of the library or its core.
cargo xtask check-fuzz-lock runs the same check locally.
The release archive
sound-to-patch-vX.Y.Z-aarch64-apple-darwin.tar.gz holds:
sound-to-patch, the binary, for Apple silicon;sound-to-patch-host, the plug-in host thatrenderstarts, a universal binary for Apple silicon and Intel: Vital 1.0.7 holds Intel code only, so the host runs as Intel under Rosetta for it;man/, one page per command:sound-to-patch.1andsound-to-patch-<subcommand>.1for each subcommand, such assound-to-patch-analyze.1andsound-to-patch-preset-apply.1;completions/for bash, zsh and fish;THIRD-PARTY-LICENSES.html;LICENSE.
THIRD-PARTY-LICENSES.html is also a release asset of its own. Each agent
plugin ships as <plugin>-vX.Y.Z.zip, its folder under plugins/.
Releases are immutable
Once a release is published, its tag and assets cannot change. The title and notes stay editable. A deleted release’s tag can never be reused. The tags ruleset covers every tag: only the release deploy key creates one, and no one deletes or moves one, including a tag whose release failed.
When something fails
- A check fails on
main. Thereleasejob does not run. Fix the problem in a new pull request; its merge releases everything since the last tag. - The publish workflow fails. The tag exists and no later merge bumps
it again. Fix the cause on
mainif needed, then re-run the failed publish run, or start the publish workflow by hand with the tag name. It skips a release that already exists. Never delete and re-create a tag. - Two merges land close together. The
releasejob first checks thatmainstill points at the commit its run tested. When another merge, or the version commit of its release, landed in between, the job ends green with a notice, and the run of the newer commit releases both. The same notice ends the job when its push fails becausemainmoved during the job. A push that fails whilemainis unchanged stays red: re-run the job. When the newer run fails a check, nothing is released until a later merge passes or its failed jobs are re-run.