| name | release |
| description | Prepare a release by bumping the version in pubspec.yaml, generating a changelog entry from commits, creating a git tag, and pushing. Validates everything before tagging. |
When this skill is invoked with optional $ARGUMENTS:
Steps
-
Parse user input — extract from $ARGUMENTS:
- Explicit version (e.g.,
/release 0.3.0) — use this exact version
- Bump keyword (
major, minor, or patch) — apply this bump to the current version
- Empty — auto-determine the bump type from commit analysis (step 4)
-
Pre-flight checks — run these before doing anything else. If any fail, abort immediately with a clear error message:
- Clean working tree: Run
git status --porcelain. If there is any output, abort — tell the user to commit or stash their changes first.
- On main branch: Run
git branch --show-current. If the result is not main, abort — tell the user to switch to main.
- In sync with remote: Run
git fetch origin main then compare git rev-parse HEAD with git rev-parse origin/main. If they differ, abort — tell the user to pull or push first.
- No duplicate tag: No existing git tag
v<new_version> (skip if version not yet determined).
-
Quality gates — ensure the package is releasable. If any fail, abort and ask the user to fix the issues first:
dart analyze — must produce zero issues (errors, warnings, or infos)
dart test — all tests must pass
-
Analyze commits & determine version:
- Get the latest git tag:
git describe --tags --abbrev=0
- Get current version from
pubspec.yaml (the version: field)
- List all commits since the latest tag:
git log <latest_tag>..HEAD --oneline
- Parse each commit using Conventional Commits format (
type(scope): description):
- Extract the type (e.g.,
feat, fix, refactor)
- Extract the scope if present
- Extract the description
- Check for breaking changes:
BREAKING CHANGE: in body/footer or ! after type (e.g., feat!:)
- Determine version bump (unless user provided explicit version or keyword):
- Any breaking change → major bump
- Any
feat commit → minor bump
- Only
fix, refactor, style, perf, docs → patch bump
- No user-facing commits (only
chore, test, ci, build) → ask whether to proceed with a patch release or abort
- If user provided a bump keyword, apply it to the current version
- If user provided an explicit version, validate it is higher than the current version
- Verify no existing git tag
v<new_version> (if not already checked in step 2)
-
Generate changelog entry — map commits to Keep a Changelog categories:
| Commit type | Changelog category | Include? |
|---|
feat | Added | Yes |
fix | Fixed | Yes |
refactor | Changed | Yes |
style | Changed | Yes |
perf | Changed | Yes |
docs | — | Skip |
chore | — | Skip |
test | — | Skip |
ci | — | Skip |
build | — | Skip |
Rules:
- Only include categories that have actual entries. Do NOT add empty categories.
- Write human-friendly descriptions, not raw commit messages.
- Group related commits when appropriate (e.g., multiple fixes for the same feature).
-
Review & confirm — present a summary before making any file changes:
Release Summary
───────────────
Current version: A.B.C
New version: X.Y.Z (BUMP_TYPE bump)
Commits since last release: N total (M user-facing, K skipped)
Changelog preview:
──────────────────
## X.Y.Z - YYYY-MM-DD
### Added
- ...
### Fixed
- ...
Ask: "Does this release summary look correct? Should I proceed?"
Allow the user to request edits to the changelog content before proceeding.
-
Update files:
pubspec.yaml: Replace version: <old> with version: <new>
CHANGELOG.md: Replace ## Unreleased with ## Unreleased\n\n## <new_version> - <YYYY-MM-DD> followed by the generated changelog entry. This leaves an empty Unreleased section and adds the new version below it.
-
Commit & tag:
git add pubspec.yaml CHANGELOG.md
git commit -m "release: v<new_version>"
git tag -a v<new_version> -m "Release v<new_version>"
-
Push — pushing the tag triggers the release.yaml CI workflow, which publishes to pub.dev. This is irreversible.
-
Report:
- Print the new version, tag name, and changelog URL