Release process
bwa-mem3 follows semantic versioning. Releases are automated with release-please: every push to main updates a standing “release PR” that bumps the version and regenerates the changelog from the Conventional Commits history; merging that PR tags the release and publishes a GitHub Release. The version string is derived from version.txt and embedded in every binary at compile time.
Version stamping
version.txt at the repo root is the single source of truth for the version. release-please rewrites it (and .release-please-manifest.json) in the release PR; nothing else should edit it by hand.
The Makefile computes the build’s version string from it at parse time:
# version.txt is the single source of truth; scripts/version.sh reads it
# and appends an informational git-describe-style dev suffix.
VERSION_STRING := $(shell scripts/version.sh)
scripts/version.sh reads the base version from version.txt and, when git is available, appends a dev suffix that surfaces how far the working tree is from the matching tag:
| Working-tree state | Example string |
|---|---|
| Source tarball / shallow clone (no git) | 0.4.0 |
Clean and exactly at tag v0.4.0 | 0.4.0 |
| Clean, not at the tag | 0.4.0-3f7ab2e |
| Uncommitted changes at the tag | 0.4.0-dirty |
| Uncommitted changes, not at the tag | 0.4.0-3f7ab2e-dirty |
“At the tag” means HEAD is precisely the commit pointed to by tag v<base> (or <base>). Manifest drift — HEAD at a tag that disagrees with version.txt — is treated as “not at tag”, so the -<sha> suffix surfaces the drift visibly rather than silently printing a wrong bare version.
The string is written into src/version.h by the src/version.h: FORCE rule, which runs on every make invocation but only touches the file when the string changes. This minimises unnecessary recompilation of src/main.o.
PACKAGE_VERSION from src/version.h appears in:
bwa-mem3 versionoutput (stdout).- The
@PG VN:field in every SAM/BAM file produced bybwa-mem3 mem.
Note the version string has no leading v (it mirrors version.txt, e.g. 0.4.0), even though the git tags do (v0.4.0).
Verifying the version
./bwa-mem3 version
# Example output on a release tag:
# 0.4.0
# mimalloc 3.3.0 ← if USE_MIMALLOC=1
On a commit past the tag the string carries the short SHA suffix:
0.4.0-3f7ab2e
Semver policy
bwa-mem3 follows semver, interpreted for an alignment tool as follows.
MAJOR (X.0.0) — bump when the change would break a downstream
consumer that pinned the previous version without checking release
notes. Concretely:
- An on-disk index file format change (a re-index is required to use the new version).
- Removal or rename of a CLI flag or subcommand.
- A SAM/BAM tag is removed, renamed, or its type/value space changes incompatibly (a column-fixed downstream parser would break). Adding a new tag is not a major change.
- A change to the resolved primary alignment that is intentional and affects more than a negligible fraction of reads (e.g. a MAPQ recalibration applied unconditionally). Concordance regressions attributable to bug fixes are not major changes — call them out in the release notes under “Correctness” instead.
- Dropping support for a previously supported host class
(e.g. raising the build’s compiled-in
BASELINE_ARCHfloor in a way that excludes hosts the previous release ran on).
MINOR (0.X.0) — bump for any user-visible new functionality that
does not break consumers pinned to the previous minor. Examples:
- A new CLI flag or subcommand.
- A new SAM aux tag emitted on output (e.g.
HN:iin 0.1.0, the BismarkXR:Z/XG:Z/XM:Zset in 0.2.0). - A new operational feature (e.g.
bwa-mem3 shm, in-process SIMD dispatch). - A user-facing default change that is documented in release notes but
does not require any consumer action (e.g.
BASELINE_ARCH=avx2as the build default). - New performance characteristics that change wall-time meaningfully.
PATCH (0.0.X) — bump for bug fixes, doc-only changes, build
fixes, and internal refactors that have no user-visible behavioral
delta. Pre-existing-bug fixes that incidentally shift output for a
small fraction of reads are patch-level when called out in the
release notes; widespread output shifts (>0.1% of reads on a typical
WGS bench cell) deserve MINOR or MAJOR depending on the source.
While the project is pre-1.0, the leading 0. is treated literally —
0.2.0 may make breaking changes vs 0.1.0 if called out clearly in
the release notes. After 1.0, MAJOR bumps are reserved for genuinely
breaking changes.
Release-readiness checklist
Run through this list on the candidate main commit before merging the
release PR (merging it is what tags and publishes the release — see
Cutting a release). Every item must pass.
Build and test
-
make clean && makesucceeds at the defaultBASELINE_ARCH(avx2) on a Linux x86_64 host. -
make clean && make BASELINE_ARCH=sse41succeeds on the same host — confirms the portability floor still compiles. -
make clean && makesucceeds on an arm64 host (Apple Silicon or aarch64 Linux). -
make testpasses on both x86_64 and arm64. -
test/regression/all_tiers_parity.shproduces byte-identical SAM acrossBWAMEM3_FORCE_TIER=sse41 → sse42 → avx → avx2 → avx512bwon an AVX-512BW host. Failures here indicate a per-tier kernel or dispatcher-wiring regression — fix before tagging.
Bench
- bwa-mem3-bench run
submitted on the candidate SHA via
bwa_mem3_bench.cli submit --fg-labs-sha <sha>(or the local smoke path for a fast sanity check). -
bench regression --prev <previous-tag-sha>reports gatePASS— concordance ≥ 99.999% on everyvs-baseline.jsoncell except methylation (which is expected to drift vs the bwameth baseline; see the methylation carve-out below) and no cell labeledREGRESSION. - Methylation cells reviewed for expected-drift consistency: the
meth-twist-emseq-5Mconcordance vs the bwameth baseline should sit at ~98.9% post-PR-#90, with the per-class breakdown matching the entry inbwa-mem3-bench/docs/expected-divergences.yaml(or the entry added in this release — the file is in the bench repo, not in this repo).
Docs
-
make docsbuilds cleanly with no mdbook warnings. - The release notes are generated automatically by release-please
from the conventional-commit history, so the real check is
upstream: every user-visible PR in the release window has a
correct conventional-commit type, and any breaking change carries
a
!/BREAKING CHANGE:marker so it lands in the⚠ BREAKING CHANGESsection (see Flagging breaking changes).NEWS.mdis not updated — it is frozen at 0.2.0; 0.3.0 and later live only inCHANGELOG.mdand the GitHub Releases page. -
docs/src/reference/pr-catalog.mdFG-MAIN-TABLEblock has a row for every fork-carried PR landed since the previous tag, with its upstream disposition (see Contributing). -
docs/src/reference/changelog.mdanddocs/src/cli/version.mdexamples reference the new release string. - Spot-check the bwa-mem3-bench reference numbers in
docs/src/performance/overview.mdagainst the bench’sregression.mdfor the tagging SHA.
Cutting a release
Releases are not tagged by hand. The .github/workflows/release.yml workflow runs release-please on every push to main and a tarball job on each published release.
-
release-please maintains a standing release PR. After PRs land on
main, release-please opens (or updates) a PR titledchore(main): release X.Y.Z. It computes the next version from the conventional-commit history since the last tag, bumpsversion.txtand.release-please-manifest.json, and prepends the generated section toCHANGELOG.md. The bump level is driven entirely by the commit types:feat:→ minor,fix:/perf:/etc. → patch, and a!/BREAKING CHANGE:marker forces the breaking bump (a minor pre-1.0, sincebump-minor-pre-majoris set). If the proposed version is wrong, the fix is upstream — correct the offending commit’s type or add a breaking marker (see Flagging breaking changes), not the release PR. -
Review the release PR. Confirm the proposed version matches the change set per the semver policy, and that the generated
CHANGELOG.mdreads correctly — in particular that any breaking change appears under⚠ BREAKING CHANGES. Run the release-readiness checklist against the PR’s base commit. -
Merge the release PR. This is the action that ships the release. release-please creates the
vX.Y.Ztag and a GitHub Release whose body is the generated changelog section. Read the Docs activates a versioned build at/vX.Y.Z/automatically once the tag appears. -
The tarball job runs automatically once the release is created. It checks out the tag with submodules, verifies
version.txtmatches the tag, builds the vendoredSource_code_including_submodules.tar.gz(all submodules bundled, no.git/), smoke-tests that it compiles and reports the right version, uploads the asset plus its.sha256, and appends a “For packagers” block (with the asset URL and sha256) to the release body. Bioconda recipes pin against this asset.
Note — Manual rebuild of a tarball asset
The tarball job can be re-run for an existing tag via the workflow’s
workflow_dispatchinput (e.g. to repair a missing asset), butv0.2.0is rejected — its asset is pinned by sha256 in an open bioconda PR and must not change.
Note — Tarball builds and the version string
A source tarball has no git history, so
scripts/version.shcannot append a dev suffix — but it still reads the git-trackedversion.txt, so amakefrom the tarball prints the bare base version (e.g.0.4.0) with no further action needed.
Post-release verification
After the release PR is merged and the GitHub release is published:
-
Wait ~5 minutes for Read the Docs to build the new version, then open
https://bwa-mem3.readthedocs.io/en/v0.X.Y/and confirm:- The version selector lists
v0.X.Y. - The home page renders with no missing-page errors.
developer-guide/launcher.md,performance/overview.md, andmethylation/tags.mdall render with their mermaid diagrams and tables intact (these are the most diagram-heavy pages).
- The version selector lists
-
Pull the tag in a clean clone and verify
bwa-mem3 versionreports the bare version string (no-<sha>dev suffix):git clone -b v0.X.Y --depth 1 https://github.com/fg-labs/bwa-mem3.git cd bwa-mem3 && make ./bwa-mem3 version | head -1 # expect: 0.X.Y (no leading 'v'; mirrors version.txt) -
If the docs build failed on RTD or the version string is wrong, do not delete or move the tag. Tags are immutable in practice — let release-please open the next release PR with the fix (a follow-up
0.X.(Y+1)patch) instead.
Branch and tag conventions
- All release tags are on the
mainbranch, which carries both upstream bwa-mem2 commits and fork-carried changes. See Branch and worktree conventions for the full branching model. - Tags are prefixed with
v:v0.1.0,v0.2.0, etc. - Pre-release tags use a
-presuffix:v0.1.0-pre. - Patch releases increment the third component:
v0.1.1.
What’s Different table update
When a release bundles new fork-carried commits that were not previously documented, update the FG-MAIN-TABLE in docs/src/reference/pr-catalog.md in the same PR before tagging. See Contributing for the rule.
See also: Branch and worktree conventions · What’s Different → Overview · Reference → Changelog · Building from source