Cut a release
Cut a Lingchu Bot release by committing release notes on main and triggering release.yml manually with a bump input. There are no releases/<bump> branches to push — task release:publish BUMP=... runs gh workflow run release.yml -f bump=... instead. The release version is derived entirely by the workflow via uv version --bump from the latest tag; the developer never writes version files. release.yml runs the same ci:version:bump → ci:version:precheck → ci:version:write-config → ci:version:postcheck chain that ci-builds.yml::versioned-build uses for the daily development build, so a single piece of PEP 440 logic governs every version transition.
Bump inputs
Section titled “Bump inputs”The bump input encodes the bump intent, not the literal version. The workflow derives the version from the latest git tag via uv version --bump:
bump |
BUMP_LEVEL |
BUMP_PRERELEASE |
Resulting version |
|---|---|---|---|
major |
major |
dev |
next major + .dev1 |
minor |
minor |
dev |
next minor + .dev1 |
patch |
patch |
dev |
next patch + .dev1 |
stable |
patch |
stable |
next patch (no pre-release) |
alpha |
patch |
alpha |
next patch + a1 |
beta |
patch |
beta |
next patch + b1 |
rc |
patch |
rc |
next patch + rc1 |
Literal version strings are never accepted as inputs. The workflow case rejects them with a clear error.
Local release flow
Section titled “Local release flow”-
Switch to a fresh main
Section titled “Switch to a fresh main”Terminal window git switch maingit pull --ff-only -
Run
Section titled “Run task release:prepare”task release:prepareTerminal window task release:prepare BUMP=stableThe task:
- Validates
BUMPagainst the seven allowed values. - Calls
task ci:version:bump BUMP_LEVEL=patch BUMP_PRERELEASE=stable DRY_RUN=trueto preview the next version without mutatingpyproject.toml. - Scaffolds
.github/releases/<computed_version>.mdif it does not exist.
It works on the current branch (
main) — it does not write version files and does not create areleases/<bump>branch. The release version is derived entirely by the workflow viauv version --bumpfrom the latest tag. - Validates
-
Edit the release notes
Section titled “Edit the release notes”Open
.github/releases/<version>.md(the path was printed byrelease:prepare). Add Highlights, breaking changes, and migration notes. -
Update the changelog and commit
Section titled “Update the changelog and commit”Add a
## [<version>] - YYYY-MM-DDsection toCHANGELOG.mdand update the compare links at the bottom, then commit:Terminal window git add .github/releases/<version>.md CHANGELOG.mdgit commit -m "🔧 chore(release): release <version>"git push origin main -
Trigger the release manually
Section titled “Trigger the release manually”Terminal window task release:publish BUMP=stableThis runs
gh workflow run release.yml -f bump=stable, dispatchingrelease.ymlagainst the pushedmaincommit. The workflow derives the version, commits the version files tomain, and tags that synced commit.
What the release workflow does
Section titled “What the release workflow does”release.yml runs five jobs in sequence:
| Job | Responsibility |
|---|---|
validate |
Derive BUMP_LEVEL / BUMP_PRERELEASE from the bump dispatch input; run ci:version:bump (uv, from latest tag) → precheck → write-config → postcheck; locate .github/releases/<version>.md; expose the computed version to downstream jobs. |
build |
Write the derived version files into the tree, commit + push them to the dispatch branch (main), then run task ci:build; upload the wheel + sdist. |
publish-pypi |
Attest SLSA Build L3 provenance; publish to PyPI via Trusted Publishing / OIDC. |
publish-image |
Build and push the Docker image to GHCR with the latest tag (stable only) plus ${version} and ${version%.*}. |
github-release |
Sync to the latest main tip (the version-sync commit), create the v<version> git tag there, and create the GitHub Release with the dist artifacts and the body from .github/releases/<version>.md. |
The validate and build jobs both invoke the same ci:version:bump task that versioned-build runs on the daily schedule, so the source-of-truth for the version lives in one place.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
Invalid release branch / input: <name> |
The bump input is not one of the seven bump names. |
Use major, minor, patch, stable, alpha, beta, or rc. |
Missing release notes: .github/releases/<version>.md |
The notes file was not committed before triggering. | Run task release:notes BUMP=<bump> to scaffold it, then commit and push before re-triggering. |
Tag v<version> already exists on origin |
The tag is already published; ci:version:tag-only skips recreation. |
Verify the tag matches the commit SHA; if a re-publish is needed, delete the tag on origin and re-run the workflow. |
| Version mismatch after a re-run | The workflow derived a version that differs from the last run. | The build job writes the CI-derived version files onto main; the github-release job tags that synced commit. Verify the resulting commit and tag. |