Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Release

Releases happen on their own when a pull request merges into main. No one tags or uploads by hand.

What a merge does

  1. The CI workflow runs every check on the merged commit. The commits check belongs to a pull request and has its own workflow, so it does not run here.
  2. If fmt, clippy, test, doc, licenses and docs pass, the release job runs cog bump --auto. It reads the commit subjects since the last tag:
    • a feat commit bumps the minor version;
    • a fix commit 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, and chore! nothing. From 1.0 on, a commit of any type with !, or with a body line such as BREAKING CHANGE: the flag is gone or BREAKING-CHANGE: ..., bumps the major version.
  3. A bump runs cargo xtask set-version as its pre-bump hook, which writes the version into Cargo.toml, Cargo.lock and fuzz/Cargo.lock. Cog then updates CHANGELOG.md and creates the commit chore(version): vX.Y.Z with the tag vX.Y.Z.
  4. 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 main directly. The private key is a secret of the release environment, which only main may deploy to, so a workflow on another branch cannot read it.
  5. The tag starts the publish workflow. It stops unless the tag is vX.Y.Z and its commit is on main. It builds the macOS arm64 binary, the universal plug-in host, the man pages, the shell completions and THIRD-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 name vst3-host. The job packs each folder in plugins/ 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 that render starts, 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.1 and sound-to-patch-<subcommand>.1 for each subcommand, such as sound-to-patch-analyze.1 and sound-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. The release job 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 main if 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 release job first checks that main still 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 because main moved during the job. A push that fails while main is 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.