Skip to content

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:bumpci:version:precheckci:version:write-configci: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.

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.

  1. Terminal window
    git switch main
    git pull --ff-only
  2. Terminal window
    task release:prepare BUMP=stable

    The task:

    • Validates BUMP against the seven allowed values.
    • Calls task ci:version:bump BUMP_LEVEL=patch BUMP_PRERELEASE=stable DRY_RUN=true to preview the next version without mutating pyproject.toml.
    • Scaffolds .github/releases/<computed_version>.md if it does not exist.

    It works on the current branch (main) — it does not write version files and does not create a releases/<bump> branch. The release version is derived entirely by the workflow via uv version --bump from the latest tag.

  3. Open .github/releases/<version>.md (the path was printed by release:prepare). Add Highlights, breaking changes, and migration notes.

  4. Add a ## [<version>] - YYYY-MM-DD section to CHANGELOG.md and update the compare links at the bottom, then commit:

    Terminal window
    git add .github/releases/<version>.md CHANGELOG.md
    git commit -m "🔧 chore(release): release <version>"
    git push origin main
  5. Terminal window
    task release:publish BUMP=stable

    This runs gh workflow run release.yml -f bump=stable, dispatching release.yml against the pushed main commit. The workflow derives the version, commits the version files to main, and tags that synced commit.

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) → precheckwrite-configpostcheck; 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.

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.