Developing release-tools¶
just build # uv sync: pytest, ruff, ty, prek, git-cliff, shellcheck
just lint # every hook: ruff, ty, actionlint (+ shellcheck), workflow and action schemas
just test # the release package, cliff.toml, the actions, and that the examples match
tests/test_release.pycovers each command of thereleasepackage (tests/test_cli.pyits entry points and help);tests/test_release_e2e.pydrives whole release flows (two series; alphas, betas, candidates and two release lines with the changelog onmain) the wayrelease.ymlandbackport.ymldo, against a scratch repository with a local bareoriginand a stand-in forgh;tests/test_release_pr.pyruns itsrelease-prcommand;tests/test_workflows.pychecks that the workflows only read outputs the package writes.tests/test_cliff.pyruns git-cliff 2.14.2 on scratch histories: gitmoji stripping, migration notes, blank lines, ignored pre-releases, two release lines,--current,--prepend.tests/test_actions.pyshellchecks the composite actions and runs them with stand-ins forpipxandgh.tests/test_examples.pychecks that docs/adopting.md, theexamples/and the dogfooding stubs agree, that the stubs pass what the reusable workflows declare, and that every reference uses the same release-tools tag and git-cliff version.
Requires Python 3.12 or later: the release package runs on the runner's
system Python (python3 path/to/release <command>) and only uses the standard
library. python3 release --help lists its commands.
How release-tools releases itself¶
release-tools follows the same process with its own workflows (dogfooding):
self-release.yml,
self-backport.yml and
self-pr-checks.yml are the
consumer stubs with uses: ./.github/workflows/<file> instead of a pinned tag, and
self-publish.yml publishes the GitHub release with
./actions/*. A local reference runs the workflow from the same commit as the event, so a
change is exercised by release-tools itself (release candidates included) before any
consumer pins it. Nothing is built or uploaded: the release is the tag and its notes.
It has no version files (version-files: ""). Set it up like any other repository
(Per-repository setup, without PyPI), tag v0.0.0 on the first
commit, and start the first release with major to get v1.0.0rc1 and then v1.0.0.
The documentation site¶
The pages in docs/ are the source of https://algorithmiq.github.io/release-tools/,
built with Zensical (zensical.toml). just docs previews it
with live reload; just docs-build builds it the way CI does (--strict: broken links
fail). Links between pages are relative .md links, so they work on GitHub too.
Each release deploys its version with Zensical's fork of mike
(the docs job of .github/workflows/self-publish.yml), which commits to the
gh-pages branch:
| Tag | Deployed as |
|---|---|
vX.Y.Z, newest final line |
X.Y, and latest moves to it |
vX.Y.Z, an older line |
X.Y (latest stays) |
vX.Y.0aN, bN, rcN |
X.Y, titled "X.Y (pre-release)", until its final replaces it |
The site root redirects to latest after the first final; until then, it redirects to
the first pre-release's line. If a docs deploy is skipped because several tags were
pushed close together, re-run that tag's docs job (the deploy logic doesn't depend on
order, so it's safe in any order). mike is transitional: when Zensical ships native
versioning, only the deploy step changes.
One-time setup, by a repository admin: Settings → Pages → Source: Deploy from a
branch, branch gh-pages, folder / (root). The branch appears with the first
deploy; set the source after it. No ruleset may block pushes of the Actions token to
gh-pages.