Release Process¶
rgpot uses a lockstep monorepo version: the same SemVer appears in
meson.build, CMakeLists.txt (project(VERSION ...)), rgpot-core/ Cargo.toml, towncrier.toml, and pixi.toml (workspace key only — not
dependency pins such as nickel).
Git tags are vX.Y.Z (see cog.toml tag_prefix).
Pre-release tags such as v1.2.0-rc.1 are allowed; release.yml marks the
GitHub Release as prerelease and skips cargo publish (stable crates.io
only).
Requires cocogitto 7+ locally and in CI
(release-prepare.yml installs 7.0.0), plus a normal Rust toolchain so potctl
(potctl/ workspace crate; cargo run -p potctl -- …) can run lockstep
commands.
CI builds target/release/potctl in release.yml / release-prepare.yml.
Do not hand-edit a ## [X.Y.Z] section above the towncrier marker; fragments
under docs/newsfragments/ are the only input for the next release notes block.
Canonical changelog: repository-root CHANGELOG.md (towncrier).
docs/orgmode/changelog.org only includes that file for Sphinx; do not maintain
a second prose changelog.
Tooling:
Tool |
Role |
|---|---|
cocogitto ( |
Conventional-commit aware bump, version commit, annotated tag |
Curated |
|
|
Project CLI: |
|
Build |
|
Later jobs/runners: download |
|
Staged on |
|
Staged: |
|
|
|
Feature-gated C++ backends (xtb+tblite, metatomic/vesin) on PRs |
|
Supported versions + private report path |
|
Release-surface review hints (enable on branch protection) |
Secrets / protection (maintainer, once per repo):
Repository secret
CARGO_REGISTRY_TOKENforrelease.ymlcargo publish.Optional GitHub Environment named
releasewith required reviewers (workflow
references environment: release; create under Settings > Environments).
Prefer signed tags when cutting locally:
git tag -s vX.Y.Z(or ensurecog
produces signed tags if configured). GHA does not replace maintainer GPG.
C++ distribution note: tag/source is the C++ contract; release.yml runs
a minimal meson install smoke. Optional backends (xtb/tblite/metatomic) are
validated on PRs via orchestrator potentials jobs, not re-run on every tag.
conda-forge / Spack / system packages are out of band (separate feedstock/PR
track), not part of release.yml.
Changelog fragments¶
Each user-facing PR should add a fragment under docs/newsfragments/ (one
fragment per user-visible change; see docs/newsfragments/README.md):
uvx towncrier create --content "Short user-facing note." 42.added.md
# or interactive:
uvx towncrier create
Types (see towncrier.toml): security, removed, deprecated, added,
dev, changed, fixed, misc.
Preview with uvx towncrier build --draft or pixi r towncrier-draft if
defined.
CI runs towncrier check on pull requests when shipped paths change
(orchestrator towncrier runs on all PRs; fragments under CppCore/, rgpot- core/, meson, CMakeLists.txt, pixi.toml, release scripts, etc.).
Pure docs / ci / chore commits may omit fragments if they avoid those
paths.
Preparing a release (maintainer) — run as soon as this lands on main¶
Ensure
mainis green (orchestratorCI gate, potentials if
relevant).
Confirm fragments exist for everything since the last tag (=uvx towncrier build
–draft=).
Local sanity:
cargo run -q -p potctl -- release assert cargo publish --manifest-path rgpot-core/Cargo.toml --locked --dry-run
Dry-run bump (optional; also GHA
workflow_dispatchonrelease-prepare.yml):cog bump --auto --dry-run # or: --patch / --minor / --major / --version 1.2.0
Cut the release locally (needs push rights; does not publish to crates.io by
itself — the tag workflow does):
# Stable 1.2.0 example (first cut after lockstep PR merges with versions at 1.2.0):
cog bump --version 1.2.0
# or let cog compute from conventional commits since last tag:
# cog bump --auto
git push origin HEAD --follow-tags
Hooks (cog.toml pre_bump_hooks):
cargo run -q -p potctl -- release sync {{version}}— lockstep write (meson,
CMake, towncrier, Cargo, pixi workspace)
uvx towncrier build --yes --version {{version}}— updateCHANGELOG.md, clear
fragments
cargo run -q -p potctl -- release assert --require-changelog {{version}}
— gate
Tag push triggers
release.yml(staged, not one fat job):toolsjob:setup-ci-toolsbuildspotctl(rust-cacheshared-key=potctl-
ci-tools=) and uploads artifact ci-tools-<sha>
gatejob:restore-ci-toolsonly — =potctl release assert –require-
changelog=, release notes → artifact release-notes-<sha> (fail fast before
matrix work)
cpp-smoke∥rust-test(parallel; only need greengate)publish(stable tags only) thengh-release(body from gate artifact; RC
prerelease)
Within a single job, steps share the runner FS (no reinstall per step).
Across jobs, binaries travel via artifacts; cargo=/deps hit =Swatinem/rust- cache on tool and rgpot-core runners so the next tag cut is cheap when
sources are unchanged.
Do not run cargo publish by hand unless CI is unavailable; the workflow is
the source of truth.
Do not use cargo publish without --locked (lockfile drift must fail the
release).
Version policy¶
Lockstep: C++ (meson + CMake), Rust crate (
rgpot-core), docs towncrier
stamp, and pixi workspace version share one semver (optionally with -[a-z0- 9.]+ suffix for RCs).
One global tag:
vX.Y.ZorvX.Y.Z-rc.N(notrgpot-core-v…).Crate publish ships
rgpot-coreonly on stable tags; C++ consumers track
the git tag / source tarball, not crates.io.
Emergency / hotfixes¶
cog bump --patch
git push origin HEAD --follow-tags
For a named version:
cog bump --version 1.1.1
Local checks before bump¶
pixi r rust-test-all
pixi r prek
uvx towncrier build --draft
cargo run -q -p potctl -- release assert
cargo run -q -p potctl -- release sync 9.9.9 # ok semver; use real target in dry tests
# refuse garbage:
cargo run -q -p potctl -- release sync not-a-version # must error
# restore if you ran a fake version: git checkout -- meson.build CMakeLists.txt ...
cargo publish --manifest-path rgpot-core/Cargo.toml --locked --dry-run
pixi r lychee-check # optional link hygiene
Post-merge checklist (first 1.2.0 cut)¶
Merge the lockstep/release-machinery PR to
main(versions may already read
1.2.0).
Ensure
rustc/cargowork (same as buildingrgpot-core).On
main:cog bump --version 1.2.0(or--autoif you want cog to decide).
This runs potctl release sync, towncrier build (so CHANGELOG.md gains
## [1.2.0] and fragments are cleared), then potctl release assert --require- changelog.
git push origin main --follow-tags(or push commit thenv1.2.0explicitly).Confirm
Releaseworkflow: lockstep gate, smoke install, rust tests, crates.io,
GH Release body.
Optional: announce; open conda-forge/Spack bumps out of band if applicable.