release
Load this skill when shipping a version: bump, changelog, land it, tag, publish the GitHub release. Trigger on "cut a release", "bump the version", "tag a release", "hotfix", or a version field changi
SKILL.mdplugins/standalone/ceh-git-workflow/skills/release/SKILL.md
GitHubRelease
Ships vX.Y.Z: the bump lands on main through a reviewed PR, and the tag and GitHub release
happen only after the merge, pointing at the merge commit, never at the feature branch.
Procedure
Pick the path, then run it top to bottom. Each step gates the next.
| Situation | Path |
|---|---|
| Ship a version (default) | Full release |
The bump already merged to main, only tag + notes |
Tag and publish |
| P1/P2 production issue that cannot wait | Hotfix |
Full release
- Decide the bump per the bump table. Never below the current version.
- Branch
chore/release-vX.Y.Zfrom up-to-datemain. - Bump the version in every manifest the project ships. All must read the same vX.Y.Z.
- Changelog: invoke the Skill tool with skill="ceh-git-workflow:update-changelog" to write the vX.Y.Z section. Gate: section written and semver-validated.
- Docs: refresh the README per
ceh-git-workflow:update-readmeif the release is user-facing, and CLAUDE.md if project facts changed. Otherwise record "no update needed". - Commit with the release commit message. Tree clean.
- Land the branch: open the PR and merge it per
ceh-git-workflow:pull-request. Gate: CI green, approvals met, merged tomain. - Tag and publish per Tag and publish.
Tag and publish
On main, after the merge:
git checkout main && git pull origin main # the merge commit is now HEAD
git tag -a vX.Y.Z -m "vX.Y.Z — <summary>" # annotated: some repos reject lightweight tags
git push origin vX.Y.Z
gh release create vX.Y.Z --title "vX.Y.Z" --notes-file notes.md && rm notes.md
notes.md is the vX.Y.Z changelog section plus the attribution footer (see
Attribution).
Hotfix
The Full release with these differences:
- Branch
fix/critical-<description>frommain, and commit the fix itself asfix(<scope>): <description>. Minimal scope: nothing unrelated rides along. - The bump is PATCH. It may commit on the same branch after the fix.
- Review is fast-tracked to 1 approval, but CI must pass. A broken hotfix is worse than a delayed one.
- The PR body links the incident and names the symptom, so the merge commit explains itself.
- After publishing, deploy staging then production (both, however abbreviated), because a rushed fix that skips staging can ship a second failure straight to production. Confirm the symptom is gone and error rates are back to baseline before declaring the incident resolved, and be ready to roll back. A P1/P2 gets a post-mortem within 48 hours.
Rules
Versioning
Tags are v<major>.<minor>.<patch>.
| Change | Bump |
|---|---|
Breaking change (BREAKING CHANGE: footer or ! type) |
MAJOR |
| New backward-compatible feature | MINOR |
| Fixes, chores, docs, refactors | PATCH |
When in doubt, PATCH. Versions only increase. Pre-releases take a suffix (v1.4.0-rc.1,
v1.4.0-beta.1) and sort below the final v1.4.0.
Gates
- One version everywhere: every manifest reads the same vX.Y.Z before the commit.
- Tag the merge commit on
main, never the feature branch, because the tag must name the tree that passed the gate onmain:git pull origin mainfirst. - Never tag or release on a red gate. Surface it and wait.
Attribution
| Artifact | Setting | Where the footer goes |
|---|---|---|
| Release commit | attribution.commit |
Last line of the commit message |
| GitHub release notes | attribution.pr |
Last line of the notes file |
Reproduce the line the session's Git instructions supply, verbatim. Never substitute a literal from this skill or from memory. If the setting is empty, omit it. The tag message takes none.
Output
Release commit message
The release commit is where the diff explains least: it shows version strings and changelog prose,
not what shipped or why the bump is that level. Always multi-line, written to a temp file and
committed with git commit -F, never -m:
chore: release vX.Y.Z
<1-3 sentences: what this release ships, in the changelog's terms>
- Bump: <PATCH|MINOR|MAJOR>: <the change that forces this level>
- Manifests: <which moved, old -> new>
- Docs: <changelog / README / CLAUDE.md updated, or "no update needed" and why>
<attribution footer>
Stop conditions
- Bump level unclear between MINOR and MAJOR → state the breaking candidate and ask. With no human to answer, take MAJOR and say why, because an unflagged break costs users more than an extra major version.
- CI red or approvals missing at step 7 → surface it and wait. Never tag around it.
- No human present and no standing authorization to publish → prepare everything up to the tag, then stop and report. Tagging and publishing are outward-facing and cannot be taken back.
Hands off to
- Invoke the Skill tool with skill="ceh-git-workflow:update-changelog" to write the vX.Y.Z section at step 4 of Full release.