name: release description: Tend release workflow. Use when user asks to "do a release", "release a new version", "cut a release", or wants to publish a new version to PyPI. metadata: internal: true
Release Workflow
Steps
- Sync the release branch, then run tests and lints: The
releasebranch is long-lived and may sit behindmain(or carry leftover state) when a cycle starts. Basing the changelog on a stale branch silently drops any commit merged tomainafter the branch was last realigned —git log <last-version>..HEADwon't show it. Bring it current first:git fetch origin && git merge origin/main(resolve any conflicts; ifreleasehas no commits of its own,git reset --hard origin/maininstead). Thenwt testandpre-commit run --all-files. - Check current version: Read
versioningenerator/pyproject.toml - Review commits:
git log <last-version>..origin/main --onelineto understand scope — againstorigin/main(notHEAD), so the range is the full set of commits this release ships even if step 1 was skipped - Confirm version with user: Present changes summary and proposed version
- Bump version: Edit
versioningenerator/pyproject.toml, thencd generator && uv lock - Update CHANGELOG: Add a
## X.Y.Zsection at the top ofCHANGELOG.md(see "CHANGELOG" below). The release workflow publishes this section verbatim as the GitHub Release notes and fails the GitHub Release job if the section is missing (PyPI publish has already happened by then; recovery is a manualgh release create), so it must land in the release commit — before the tag. - Commit on the current branch:
chore: release X.Y.Z(version bump, lockfile, and CHANGELOG). Don't create a new branch — this worktree is already on the release branch, and the PR opens from it tomain. - Merge to main: Push, create PR via
gh pr create, wait for CI, merge withgh pr merge --squash - Tag and push:
git tag X.Y.Z && git push origin X.Y.Z— triggers.github/workflows/pypi-release.yaml, which publishes to PyPI and creates a GitHub Release from the version's CHANGELOG section. - Wait for the release workflow: Poll until
uvx tend@X.Y.Z --helpsucceeds and the release appears (gh release view X.Y.Z). - Regenerate tend's own workflows: Stay on the
releasebranch (don't create a new one — same as step 7). The squash-merge deletedorigin/release, sogit fetch && git reset --hard origin/mainto realign with the squashed history. Thenuvx tend@latest init, commit, push, and open a PR titledchore: regenerate workflows with tend X.Y.Z. Until this merges, tend's deployed workflows lag the just-released generator, so critical fixes (e.g. loop-prevention filters) remain unreachable on tend itself.
CHANGELOG
CHANGELOG.md holds one ## X.Y.Z section per release, newest first. The header must be exactly ## X.Y.Z — the release workflow matches it literally to extract the notes.
Draft the section from the commits since the last release (git log <last-version>..origin/main --oneline):
- Group by section, in order, omitting empty ones: Improved, Fixed, Documentation, Internal. Internal is for selected notable internals, not everything.
- Combine related PRs into one bullet; cite them all in a trailing
([#a](url), [#b](url))list. Use fullhttps://github.com/max-sixty/tend/pull/NURLs so links resolve from the GitHub Release page. - Be brief: 1–3 sentences per bullet; Internal bullets terser.
- No editorial framing: describe what changed, not what was wrong with the old approach.
- Verify against the diff, not the commit subject — subjects often undersell or misdescribe.
git show <sha>anything user-facing before trusting its bullet.
Version scheme
Tags are bare versions (0.0.9), not prefixed (v0.0.9).
Generated workflows pin the action to the generator's own version
(max-sixty/tend@X.Y.Z); there is no floating v1. Each X.Y.Z tag is the
immutable ref consumers run, enforced by a tag ruleset on max-sixty/tend
(update/deletion restricted). Never force-move or delete a published tag.
Step 9 (tag) must precede step 11 (regenerate via uvx tend@latest) so the
pinned ref resolves to an existing tag.
Commit message pattern
chore: release X.Y.Z
Bumps generator version to X.Y.Z and syncs lockfile.
N commits since A.B.C: <brief list of notable changes with PR numbers>.