Skip to content

Create Release

ContributorsMyles Henaghan

When to use: The driver has asked for a release in this session. A release is usually a release PR that regenerates CHANGELOG.md, followed by a v* tag on the merged commit. Tag pushes often trigger staging and production deploys — treat tagging as a release action, not a casual git operation.

Agents: only run this when the driver has asked for a release. Let the driver make the version choice in step 2; do not pick it for them.

Follow the repository's own CONVENTIONS.md, CONTRIBUTING.md, or release docs for tool names (make changelog, tag-check scripts, host-specific permission tables). This skill is the decision order those documents assume.

1. See what would be in the release

git fetch origin --tags
git switch main && git pull origin main

If the repo provides a release-notes or changelog preview command, run it (for example make release-notes). That output should list major/minor/patch candidates from the highest numeric version tag, then unreleased changes as the changelog will show them. If nothing is listed, there is nothing to release.

Do not use Git's nearest-tag selection (git describe) as the version baseline when the repo documents a different rule — padded or out-of-order tags can make describe pick the wrong predecessor.

Two more views help with the version choice:

# Replace with the repo's tag helper if one exists, e.g. scripts/check_release_tag.py --latest
LAST=$(git tag -l 'v*' --sort=-v:refname | head -1)
git log --oneline "$LAST"..HEAD
git diff --stat "$LAST"..HEAD

Narrow the diff to paths that users or integrations touch (UI, public API, migrations, shared calculation modules) when the repo documents those paths.

An empty user-facing diff is a strong hint toward patch. A non-empty diff needs the questions in step 2.

Ask whether any open PR should be in this release. Merge those first: once the release PR merges, some teams freeze further merges until the tag is pushed.

2. Choose the bump deliberately

Automated suggestions often count commit types (feat → minor, fix → patch). The version describes impact on people and systems using the software, which commit types alone do not capture. Present the three candidates from the latest tag and ask the releaser to choose:

Bump Choose it when the release… Example from v1.0.4
Major Breaks something users or integrations rely on: removed or changed API contract, data change that needs manual steps, workflow people must relearn v2.0.0
Minor Adds or changes something users can see or do v1.1.0
Patch Fixes a defect, or changes nothing user-facing: diagnostics, performance, refactors, docs, tooling, infra wiring v1.0.5

Major usually answers itself: does anyone have to change something on their side (update a caller, run a manual data step, relearn a workflow) for things to keep working? If yes, it is major.

Minor or patch needs more thought. Work through these questions against the unreleased changes. Any yes points to minor; all no points to patch.

  1. Will someone using the product notice a difference: a new or changed screen, field, button, filter, export, or report?
  2. Can users do something they could not do before?
  3. For the same inputs, do any results change (calculations, totals, reports) other than by correcting a defect back to the intended behaviour?
  4. Can another system use something new: an endpoint, a field, or an option? (Additive is minor; removed or changed is major.)
  5. Would you tell users or stakeholders about this release, beyond "fixes and improvements"?

If it is still unclear, ask: if this release were rolled back, would a user notice? Yes points to minor.

Changes that affect only how the system is run, observed, or deployed are often patches even when their commits are feat: diagnostics, logging, performance, configuration defaults, infra wiring, dependency updates, tests, and docs.

Agents: answer each question from the commits and the diff, citing the commit behind each yes, then recommend a bump and let the driver decide.

Confirm the chosen version and a one-line reason; the reason becomes the tag message. Use no zero padding (v1.0.5, not v1.0.05).

3. Open the release PR

Use the repository's documented release branch flow. A typical shape:

git checkout -b chore/release-vX.Y.Z origin/main
make changelog VERSION=vX.Y.Z   # or the repo's equivalent
git add CHANGELOG.md
git commit -m "chore(release): vX.Y.Z"
git push -u origin chore/release-vX.Y.Z

Raise the PR on the hosting platform. Read the new CHANGELOG.md section: if an entry reads badly, the fix is usually the source commit message, not a hand edit of the generated file. Merge when build and required approvals pass.

4. Tag the release commit

Pull first. Rebase merges can change the commit hash on the default branch.

git switch main && git pull origin main
git log -1 --oneline   # expect: chore(release): vX.Y.Z
git tag -a vX.Y.Z -m "<the one-line reason from step 2>"
git push origin vX.Y.Z

If git log shows a different commit, something merged after the release PR. Stop and decide with the team whether to include it (new release PR) or wait.

If the push is refused

Permission errors on tag push (for example Azure DevOps TF401027, or GitHub "permission denied" on tags) mean nothing was released; a local tag may still exist. Stop and offer the driver:

  • Ask someone with tag-create permission to create the tag at the agreed commit with the agreed message, then delete the local tag copy if needed.
  • Request the permission from a project administrator using the repo's permission doc. After it is granted, confirm main has not moved, then push the same tag.

Agents: do not retry with other credentials, alternate remotes, or APIs to circumvent permission; stop and hand off.

5. Follow the deployment

When tags trigger pipelines, the run usually deploys to staging before production, often with manual approvals. Use the pipeline summary and environment health checks the repo documents (image tag, diagnostics endpoint, smoke tests) before approving production.


Troubleshooting

Symptom Likely cause Fix
Suggested patch/minor/major looks wrong Commit-type heuristics ignore user impact Run step 2 questions against the diff
git describe disagrees with release tooling Tag sort / padded tags Use the repo's --latest tag helper or git tag -l 'v*' --sort=-v:refname
Tag push denied Missing Create tag permission Section 4 — hand off; do not bypass
CHANGELOG entry is ugly Weak commit messages Fix messages on future commits; avoid hand-editing generated changelog