Release workflow¶
eOn releases use cocogitto (cog) to derive the
next semver tag from the conventional-commit log, run the mechanical bump
steps, create an atomic signed tag, and emit the source tarball. The
cog.toml at the repo root wires this up; the hand checklist below documents
what it automates and the manual steps that precede and follow it.
1. Pre-release checklist¶
Before invoking cog bump, verify:
[ ] Every PR intended for the release is merged into
main.[ ]
CHANGELOG.mdis up to date through the previous release only – towncrier will prepend the new section fromdocs/newsfragments/*. If fragments are missing for user-facing changes, add them first.[ ]
docs/source/releases/v<X.Y.Z>/release-notes.mdandindex.mdexist and are linked fromdocs/source/releases/index.md(cog cannot generate these – they are curated).[ ] CI is green on
main.[ ]
pixi install --lockedsucceeds cleanly (so the lockfile regeneration hook has something stable to work from).[ ] Downstream integration test passes. The lab-cosmo/atomistic-cookbook example
eon-pet-nebexercises eOn + PET-MAD on the oxadiazole NEB and is the canonical smoke gate for metatomic consumers. Point a cookbook checkout at the prospective release commit of eOn (edit itsenvironment.ymlto override theeondependency, orpip install -ethe eOn source tree into the nox-managed env) and run:nox -e eon-pet-nebA pass means the nox session exits 0, the generated gallery artefacts regenerate, and
client_traceback.loginside the example directory is empty. A regression here blocks the release.
2. Running cog bump¶
The one-command happy path on main:
cog bump --auto --annotated 'Release v<X.Y.Z>
<one-paragraph body listing headline features, e.g.:
ARTn saddle search (pARTn), OCINEB hybrid CI-NEB + min-mode,
IRA structure comparison, ...>
See CHANGELOG.md.'
Override cog’s commit-log inference with --minor, --major, or
--version X.Y.Z when needed (e.g. the only feat: commits since the
last tag are feat(docs) and a patch bump is incorrect).
What cog bump does¶
Defined in cog.toml:
Picks the next version (semver increment inferred from conventional commit types since the last tag, or taken from the flag).
Runs
pre_bump_hooks:sedthe new version intopyproject.tomlandpixi.toml. All other consumers (docs/source/conf.py,client/get_version.py, the meson and CMake builds) read frompyproject.toml.uvx pixi-to-conda-lock pixi.lock --output condaEnvsregenerates everycondaEnvs/*.conda-lock.yml.pixi r -e dev towncrier build --version {{version}} --date $(date +%Y-%m-%d) --yesconsumes every file indocs/newsfragments/and prepends the new section toCHANGELOG.md.
Stages the resulting diff and writes the atomic release commit (
chore(version): <X.Y.Z>by default; override via the--annotatedbody if you want custom wording).Creates the signed annotated tag
v<X.Y.Z>.Runs
post_bump_hooks:git archive --format=tar v<X.Y.Z> | xz -9 > eon-v<X.Y.Z>.tar.xzproduces the source tarball. Automatic GitHub tag archives are avoided because their contents have a documented stability caveat.Prints a reminder for the remaining manual steps.
cog.toml sets disable_changelog = true so cog stays out of
CHANGELOG.md (towncrier owns it) and branch_whitelist = ["main"]
so cog bump refuses to run on a PR branch.
3. Post-bump actions¶
Inspect the release commit:
git show HEADThe diff should look like
1edaf4d8from v2.12.0 – version bumps inpyproject.toml/pixi.toml, regeneratedcondaEnvs/*.conda-lock.yml, an appended block inCHANGELOG.md, everydocs/newsfragments/*file deleted, and the new release-notes page.Push the commit and tag together:
git push origin main --follow-tagsCreate the GitHub release with the tarball attached:
gh release create v<X.Y.Z> eon-v<X.Y.Z>.tar.xz \ --title v<X.Y.Z> \ --notes-file docs/source/releases/v<X.Y.Z>/release-notes.md
The feedstock URL assumes this exact tarball filename; do not rename the asset.
4. conda-forge feedstock bump¶
Once the GitHub release is published (so the asset URL resolves), update the feedstock at conda-forge/eon-feedstock:
Branch
release-<X.Y.Z>offmain.In
recipe/recipe.yaml, bumpcontext.versionto"<X.Y.Z>".Compute the tarball sha256 and replace the first
source[].sha256:curl -sSL "https://github.com/TheochemUI/eOn/releases/download/v<X.Y.Z>/eon-v<X.Y.Z>.tar.xz" \ | sha256sum
Reset
build.number: 0.Verify
fix_vesin_const.patchandfix_capnpc.patchstill apply cleanly; if not, regenerate them against the new source tree.Commit, push,
gh pr createagainstconda-forge/eon-feedstock.Watch the Azure Pipelines matrix (linux-64, osx-64, osx-arm64, win-64) via
cf-ci watch conda-forge/eon-feedstock#<N>.
5. Manual fallback¶
When cog bump fails mid-run (hook script error, unexpected prompt, etc.)
the state is recoverable: no commit has been written yet. Fix the root
cause and re-run. If you must cut by hand, this is the equivalent
sequence; 1edaf4d8 chore: release v2.12.0 is the canonical reference.
# Version
sed -i 's/^version = "[^"]*"/version = "<X.Y.Z>"/' pyproject.toml pixi.toml
# Lockfiles
uvx pixi-to-conda-lock pixi.lock --output condaEnvs
# Changelog
pixi r -e dev towncrier build --version <X.Y.Z> \
--date "$(date +%Y-%m-%d)" --yes
# Release notes page (manual)
# Create docs/source/releases/v<X.Y.Z>/{index.md,release-notes.md} and
# add to docs/source/releases/index.md toctree.
# Atomic commit + signed tag
git add -A
git commit -m "chore: release v<X.Y.Z>"
git tag -s -a v<X.Y.Z> -m "Release v<X.Y.Z>
<body>"
# Tarball
git archive --format=tar v<X.Y.Z> | xz -9 > eon-v<X.Y.Z>.tar.xz
Then continue from §3 post-bump actions.