This document describes how to cut a release of orcapod to PyPI.
- All development happens on feature branches off
main. - There are no long-lived branches (the historical
devbranch has been retired). - No back-merges are needed.
Releases are triggered from the GitHub Actions UI — no manual git tag step required.
-
Merge your branch into
main— open a PR, get it reviewed, merge it. -
Trigger the release workflow — go to Actions → Release → Run workflow in the GitHub UI, enter the version (e.g.
0.1.0), optionally enter a branch name (defaults tomain), and click Run workflow.A leading
vis stripped automatically —v0.1.0and0.1.0both work. -
CI takes over — the workflow runs the following jobs automatically:
validate-branch ─┬─ test ──────────┐ └─ license-check ──┤─ build ─┬─ publish-testpypi ─ publish-pypi ─┐ └─ linear-sync ──────────────────────┴─ linear-complete- Pre-flight: branch validation, then tests on Python 3.11 and 3.12 and license check (parallel after validation)
- Build: normalises version, creates local tag, builds wheel + sdist, pushes tag to origin
- TestPyPI: publishes to test.pypi.org first as a staging step
- PyPI: publishes to pypi.org and creates a GitHub Release with generated release notes
- Linear:
linear-syncstarts immediately after build (parallel to publish);linear-completeruns after both PyPI publish and linear-sync succeed
Release candidates (e.g. 0.1.0rc1) follow exactly the same path — enter the version in the
workflow input. PyPI handles the stable vs pre-release distinction natively:
pip install orcapod— installs the latest stable release onlypip install --pre orcapod— installs the latest release including pre-releases
To release from a branch other than main — for example, a maintenance branch carrying
a critical patch — enter the branch name in the Branch field when triggering the
workflow.
Example: cutting v0.1.1 from hotfix/0.1.x:
- Trigger the release workflow — go to Actions → Release → Run workflow
- In the Use workflow from dropdown, keep
mainselected (so the workflow version includes theBranchfield — do not selecthotfix/0.1.xhere) - Set Version to
0.1.1 - Set Branch to
hotfix/0.1.x - Click Run workflow
The workflow will confirm the branch exists, run tests against it, create the v0.1.1
tag at its tip, and publish to PyPI — identical to a normal release.
| Release type | Tag format | Example |
|---|---|---|
| Stable | vMAJOR.MINOR.PATCH |
v0.1.0 |
| Release candidate | vMAJOR.MINOR.PATCHrcN |
v0.1.0rc1 |
| Alpha | vMAJOR.MINOR.PATCHaN |
v0.1.0a1 |
| Beta | vMAJOR.MINOR.PATCHbN |
v0.1.0b1 |
The workflow input accepts any of the above (with or without a leading v). The version is
derived from the git tag by hatch-vcs (dynamic = ["version"] in pyproject.toml) — no
manual version bump is needed.
When a release is triggered, the CI automatically transitions all Linear issues in
"Merged" status (whose PRs were included in the release) to "Done". This is
handled by two jobs in release.yml that call linear/linear-release-action, plus a
separate release-sync.yml that runs on every push to main.
| Trigger | Workflow / Job | Action | Effect |
|---|---|---|---|
Push to main |
release-sync.yml / sync |
sync (no version) |
Associates the merged PR with the open Linear release draft |
Release workflow build succeeds |
release.yml / linear-sync |
sync --version <tag> |
Finalises the commit set for this release version in Linear |
After publish-pypi succeeds |
release.yml / linear-complete |
complete --version <tag> |
Marks the release done in Linear; triggers Merged → Done |
Before cutting the first release with this system active, a workspace admin must:
-
Set the
LINEAR_ACCESS_KEYrepo secret innauticalab/orcapod-pythonGitHub settings (Settings → Secrets and variables → Actions → New repository secret). Use the same Linear API key asmetamorphic-brain/axon. -
Configure a Linear release in the workspace for orcapod-python via the Linear UI: set the release name, which statuses count as "included" (at minimum: Merged), and the target state for the transition (Done).
-
Update PyPI/TestPyPI Trusted Publisher configs — if the Trusted Publisher on pypi.org or test.pypi.org still references
publish.ymlas the workflow file, update it torelease.ymlbefore triggering the first release.
If LINEAR_ACCESS_KEY is not set: the release-sync workflow runs but the Linear action
may fail; the linear-sync and linear-complete jobs in release.yml fail but do not
block the PyPI publish (they have no dependents in the publish chain).
- Copy
.github/workflows/release-sync.ymlverbatim. - Add
linear-syncandlinear-completejobs to the repo's release workflow, adjustingneeds:inlinear-completeto point at whichever job creates the GitHub Release. - Set the
LINEAR_ACCESS_KEYrepo secret. - Configure a Linear release in the workspace for the new repo.