Release process¶
Audience: anyone (human or AI agent) committing to vibe-qc, plus users who want to pin a calculation to an exact build. If you only want to install and run, see
installation.md.
Branch model¶
vibe-qc has two long-lived branches with strict roles. All development chats and contributors must respect this split — it’s the mechanism that lets us match a calculation log to the exact code that produced it, and it’s how we keep public users on a stable surface while we iterate.
Branch |
Purpose |
Push policy |
|---|---|---|
|
Active development. Every feature, bugfix, refactor lands here first. CI must pass. Daily commits expected. |
Maintainers + agents, after CI green. |
|
Public-facing snapshot. Advertised install instructions and any binary distribution we ever publish pull from |
Fast-forward only, and only from a tagged commit on |
Any other branch is a topic branch — short-lived, owned by a single
contributor or chat session, gets squashed or rebased into main once
its work lands.
Note
Pre-v0.4.0 deviation. Until the first public tag (planned for
v0.4.0), the docs site at vibe-qc.com tracks main directly, not
release. The reasoning: holding the public docs at v0.1.0 while
v0.2.0 / v0.3.0 / v0.4.0-dev features land on main would mislead
new readers into a months-stale install matrix and tutorial set. The
site banner reads dev 0.4.0.dev0 (main @ <sha>) during this
window so it’s still unambiguous which build a calculation log came
from. Starting with the v0.4.0 tag, the site switches to the
release-branch model described above and the banner reads
Release v0.4.0.
What’s the user-visible difference?¶
Every vibe-qc run prints a banner that identifies the build:
╔════════════════════════════════════════════════════════════════════════╗
║ Release v0.1.0 — Quantum chemistry for molecules and solids ║
║ © Michael F. Peintinger · MPL 2.0 · https://vibe-qc.com ║
║ linked: libint 2.13.1 · libxc 7.0.0 · spglib 2.7.0 ║
╚════════════════════════════════════════════════════════════════════════╝
vs. a development build:
╔════════════════════════════════════════════════════════════════════════╗
║ dev 0.1.0 (main @ abc1234) — Quantum chemistry for molecules and … ║
║ © Michael F. Peintinger · MPL 2.0 · https://vibe-qc.com ║
║ linked: libint 2.13.1 · libxc 7.0.0 · spglib 2.7.0 ║
╚════════════════════════════════════════════════════════════════════════╝
The first form appears only when:
The current commit is exactly tagged (e.g.
v0.1.0).The working tree is clean (no uncommitted changes).
Any other state — branch, dirty tree, detached HEAD, untagged commit —
shows the dev form, including branch name, short SHA, and a dirty
flag if there are uncommitted changes.
Cutting a release — checklist¶
Maintainers only. Run from a clean checkout of main with everything
committed and pushed.
Pre-flight
git fetch origin git checkout main git pull --ff-only .venv/bin/python -m pytest tests/ # 100 % pass .venv/bin/python -c "from vibeqc.banner import build_info; print(build_info())"
The
build_info()output should showdirty: False. If anything else is wrong, fix it onmainfirst.Bump the version
Edit
versioninpyproject.toml(and only that — the banner reads this). Commit:git commit -am "release: vX.Y.Z" git push origin main
Tag the release commit on
maingit tag -a vX.Y.Z -m "vibe-qc X.Y.Z" git push origin vX.Y.Z
Fast-forward
releaseto that taggit checkout release # or git checkout -b release if first time git merge --ff-only vX.Y.Z git push origin release
If git refuses the fast-forward, stop.
releasehas somehow diverged frommain’s tag. Investigate before doing anything destructive.Verify on a clean checkout
cd /tmp && rm -rf vibeqc-rel-check git clone -b release https://gitlab.peintinger.com/mpei/vibeqc.git vibeqc-rel-check cd vibeqc-rel-check ./scripts/setup_native_deps.sh python3 -m venv .venv && .venv/bin/pip install -e '.[test]' .venv/bin/python -c "from vibeqc.banner import print_banner; print_banner()"
Banner should read
Release vX.Y.Z.Post-release
Update the changelog with the release notes (sourced from the project-root
CHANGELOG.md).Bump the next
0.X.Y+1.dev0version onmainso subsequent dev builds are visibly post-release.The vibe-qc.com docs site auto-deploys via GitLab CI on every push to
mainorrelease. The push ofreleasein step 4 already triggered a deploy; the next pipeline at https://gitlab.peintinger.com/mpei/vibeqc/-/pipelines should show green within ~3 minutes and the live site banner should readRelease vX.Y.Z. For the v0.4.0 cutover specifically, edit.gitlab-ci.ymlto tighten theonly: [main, release]filters toonly: [release]— this stops dev pushes tomainfrom overwriting the publicly-advertised tagged content. Until that edit, both branches publish on push; the most-recent push wins.
Running calculations against a specific build¶
Common case: testing a fix from a topic branch, comparing accuracy across builds, or reproducing an old result. The banner is the source of truth, so:
# 1. Clone or check out the exact ref you want to test.
git fetch origin
git checkout release # or v0.1.0, or some-topic-branch
# 2. Rebuild the native deps and the python package against that tree.
./scripts/setup_native_deps.sh
.venv/bin/pip install -e '.[test]' --force-reinstall --no-deps
# 3. Confirm the banner shows what you expect.
.venv/bin/python -c "from vibeqc.banner import print_banner; print_banner()"
# 4. Run your calculation. Every persisted SCF log carries the same
# banner at the top, so the result is unambiguously paired to the build.
If a calculation gives a wrong answer, always include the banner in the bug report. The branch+SHA pinpoint the exact source state; the linked-library line pinpoints the native ABI.
CI hooks¶
What’s wired today (.gitlab-ci.yml at repo root):
Docs build + deploy runs on every push to
mainorrelease. Container:python:3.13-slimfor build,alpine:latestfor deploy. Runner:erzherzog-docker(gitlab/gitlab-runner in Docker on the same host as the GitLab CE instance, tagsdocker/sphinx). Deploy uses an rsync-over-SSH push toweb18@vibe-qc.com:/web/, with the ed25519 deploy key stored as the masked, protected$DEPLOY_SSH_KEY_B64CI variable. Build logs surface in GitLab’s pipeline UI.
What’s planned, not yet wired:
releaseis a protected branch on the GitLab project: only fast-forward from a tag is allowed (push rule). Apply this in the GitLab UI before the v0.4.0 tag.A nightly job re-runs the test suite against
releaseto catch silent breakage from environment drift (e.g. a newer compiler rejecting our C++). Add as a scheduled pipeline once the test suite runs cleanly inside the CI container (currently needs the C++ toolchain image, which the docs pipeline doesn’t exercise).A manual job tags + pushes the release branch given a tag name. Useful for one-click cutting of a release; today the workflow is the manual step-1-through-6 checklist above.
Why not just use main for everything?¶
We’re a single-developer project today, so the temptation is real.
The reason release exists anyway is that we’re going public soon
and the docs site at https://vibe-qc.com pulls from a fixed branch
(currently main, soon release). Keeping release separate means
casual visitors see stable docs and stable install instructions even
as we tear apart main for a refactor.