Release process (CalVer via release-it)
Release process (CalVer via release-it)
Release process (CalVer via release-it)
All workspace packages share one lockstep version yyyy.ww.patch (ISO week, e.g.
2026.34.0). Releases are cut with release-it + @csmith/release-it-calver-plugin
@release-it/bumper, configured in.release-it.json. Nothing is published to
npm; versioning exists for git tags, GitHub Releases, CHANGELOG.md, and tag-driven
deploys.
Procedure
- Run
pnpm run release:dryfirst — verify the computed ISO week number and that
all 26package.jsonfiles appear in the bumper’s out list. - Cut stable from
main:pnpm run release→ commitschore(release): vX,
tagvX, GitHub Release, CHANGELOG entry, lockstep version bump. - Beta: from a
betabranch (or main between stable cuts),pnpm run release:beta
→yyyy.ww.patch-beta.Ntags (the calver plugin ignores release-it’s
--preRelease, soscripts/release-beta.tscomputes the suffix explicitly).
Mergebeta→mainbefore the next stable cut. - All deploys go through
.github/workflows/deploy-pyinfra.yml— the
single deploy path (pyinfra artifact + activate, Infisical env render,
report-only drift gate, post-deploy smoke + config-audit). It fires on:- push to
beta(BRI-435 converge-always: merging to beta IS the
beta deploy — docs-only paths are ignored), - CalVer tags:
vX.Y.Z-> production,vX.Y.Z-beta.N-> beta, workflow_dispatch: rollback/redeploy only (ref+ optional
artifact_sha256redeploy an existing artifact). It replaces whatever
is live for that env.
Every trigger is guarded: theresolve-envjob refuses any sha that is
not already on the env’s branch (betafor beta,mainfor prod), so a
feature-branch commit can never be deployed. To test on beta, merge to
beta.
Every run builds the artifact in-run viabuild-artifact.yml
(workflow_call), so deploy never races a separate builder.
The drift gate no longer blocks: host drift warns in the run summary
and the deploy converges the host (PYINFRA_ENV_MODE=write lets it
reconcile the env file too).
- push to
- Cut a beta tag after each merge to
beta. The push already deployed;
the tag is a stable point-in-time marker: it ties a deploy run’s
head_shato a named release onbeta.usebrioso.com, so “what was on
staging when X shipped?” stays answerable when the branch tip has
moved on.git fetch origin betaand inspect the tag’sgit log -1
(or the GitHub Release) instead of guessing from commit SHAs.
Fail-first PR checks (BRI-434)
Deploy problems surface on the PR, not on deploy night:
build-artifact.ymlruns build + boot-smoke + smoke-test-artifact on
PRs touching deployable paths (apps/**,packages/**,deploy/**,
scripts/**,config/**,.github/**, toolchain manifests). PR builds
resolve no GitHub Environment — they compile against the checked-in
fixture envdeploy/artifact-env/smoke.env.example(audit-build-env.ts
still enforces required key NAMES) and skip the Release publish (the
smoke jobs consume the run-scoped artifact upload).deploy-pr-checks.yml(pull_request_target, base-branch code only,
PRs into beta/main):secrets-checkhard-fails when a GitHub secret
NAME inconfig/deploy-secrets.yamlis missing from the target
environment, audits the Infisical render, and asserts the Modal worker
secret’s required keys;drift-reportposts the live
pyinfra --dry --jsonreport as a warning + job summary (informational).mise run deploy:rehearselocally remains the pre-merge dry run.
Retired deploy surfaces (BRI-435)
Deleted: deploy-beta.yml (bash beta deploy; its deploy-beta.sh was
already gone), pyinfra-deploy-beta.yml (Phase-3 soak, superseded by
deploy-pyinfra.yml), modal-deploy.yml, deploy-modal-audiocpp.yml,
beam-deploy.yml (dispatch-only deploys of retired runtimes),
build-runpod.yml (retired image build). Still live: deploy.yml
(frozen manual audit trail — do not dispatch), deploy-modal-worker.yml,
deploy-secrets-sync.yml, pyinfra-drift.yml (daily drift schedule).