release
Automate project releases by deriving semver from changelogs and triggering GoReleaser workflows.
Install
mkdir -p .claude/skills/release-andrewdryga && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19274" && unzip -o skill.zip -d .claude/skills/release-andrewdryga && rm skill.zipInstalls to .claude/skills/release-andrewdryga
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Cut a versioned release of coop — derive the semver bump from the `## Unreleased` changelog, finalize + annotated-tag it, then (only on explicit confirmation) push the `v*` tag that triggers the public GoReleaser build. Refuses a docs-only no-op release. Use when asked to "cut / ship / tag a release", "publish a release", or "bump the version".Key capabilities
- →Derive semver bumps from Unreleased changelog entries
- →Finalize changelog sections for new versions
- →Create annotated git tags for release points
- →Regenerate help documentation casts at specific versions
- →Trigger public GoReleaser build pipelines
How it works
It validates the repository state, updates the changelog, tags the commit, and pushes to trigger an automated CI pipeline that builds and signs public artifacts.
Inputs & outputs
When to use release
- →Ship a new version of the codebase
- →Bump version and tag the repository
- →Automate public binary release generation
About this skill
/release — cut one clean, signed release
Releases are tag-driven: the version comes from git describe --tags, and pushing a v*
tag fires .github/workflows/release.yml → GoReleaser builds every OS/arch and publishes a
public, cosign-signed GitHub Release (binaries + checksums.txt + build provenance) that
install.sh serves. The tag push is the point of no return — everything before it is
local and reversible; after it, the artifacts are public. Don't poke at the Makefile/workflow
each time — this is the contract; follow it.
1. Pre-flight — is there anything real to ship?
- On
main, clean tree, not behindorigin/main(the only ahead commits should be your own release prep). Broad free gate green for the executable candidate:make check. A later changelog-only finalization/reopening uses the actual notes/docs checks; do not repeat unchanged local broad proof. The exact-tag release workflow still runs all free CI checks. - The gate is free and deterministic. Live-provider suites run on demand and are not release permission; do not request a waiver or run paid models to finalize a version.
- Identify the latest published, non-draft, non-prerelease version with
gh release list --limit 100 --json tagName,isDraft,isPrerelease,publishedAtbefore comparing changes. A local or failed tag is not a published release. - Refuse a no-op.
git diff --stat <latest-published-tag>..main— if it touches onlyCHANGELOG.md/docs (no code), STOP: the binary would be byte-identical to the last release. The fix is almost always changelog attribution, not a new version — move the entry under the release where the code actually shipped (git tag --contains <commit>shows which one already has it). Cutting a version for unchanged code misdates the feature. - The
## Unreleasedentries ARE the release. Empty ⇒ nothing to cut; say so and stop. - Write the GitHub release body in
.github/release-notes.md, under## <version>: a short summary of the most important changes in plain English, not every changelog item. Explain user benefits, keep essential upgrade warnings, and end with the full-changelog compare link against the previous published release. The release workflow publishes that section as is, so the page is never edited by hand afterwards. Preserve every detailed entry since 10.1.2 in CHANGELOG.md; older releases are kept at the v11.3.0 tag, which its last line links. - Public notes describe product changes, compatibility and user actions. Operator approvals,
waivers, test/review diaries, spend details and CI troubleshooting belong in gitignored task
records, never the public changelog or release body. Keep real functional limits accurate;
removing process narration must not invent validation or capabilities. Follow
.agent/kb/rules/public-release-notes-are-product-focused.md. - Optional dry-run:
make snapshot(GoReleaser--snapshot --clean --skip=sign, no publish; signing is CI-only keyless OIDC) to catch config breakage before any tag exists.
2. Pick the version (semver — or take the user's)
- Latest: the published version established in pre-flight, not the highest local Git tag.
- Bump by what's in Unreleased: new functionality → minor
x.Y.0; fixes/hardening only → patchx.y.Z; a breaking change → major. A version the user named wins. - Guard: the tag must not already exist and must sort after the latest.
- Move all unpublished attempt entries into Unreleased before finalizing; preserve their change descriptions, correcting only behavior superseded before publication. Only the version that actually ships gets a numbered release entry. Release notes and full-changelog links compare against the previous published release; do not let GitHub choose an unpublished tag as baseline.
3. Finalize + tag (all local, still reversible)
- Rename
## Unreleased→## <version>(NO date — house format is a bare## X.Y.Z) and delete the placeholder comment under it; it lives only under## Unreleased. Keep entries as- **Bold headline.** explanation. - Replace
.github/release-notes.md's section with the new## <version>summary (keep the comment at its top). - Commit only those two files:
changelog: finalize <version> (<one-line summary>). - Annotated tag on THAT finalize commit:
git tag -a "v<version>" -m "v<version>"(tags are annotated and point at the finalize commit, never the re-open commit). - Still on that commit, run the release workflow's own check:
go run ./tools/releasenotes notes "v<version>"prints the summary it will publish, or refuses as the workflow would (tag not at HEAD; the changelog section or the summary unfinalized, for another version, empty or malformed). Fix and re-tag locally rather than push a tag that fails publication. - Re-open: add a fresh
## Unreleased+ the placeholder comment back; commitchangelog: open an Unreleased section after v<version>.
4. Push — public, irreversible: CONFIRM FIRST
- Show the user the version, the one-line summary, and that this publishes a public signed release. Get an explicit go-ahead — this is the one outward-facing, hard-to-undo step.
- Then:
git push origin main && git push origin "v<version>". - Watch it land:
gh run watch(orgh run list --workflow=release.yml), thengh release view "v<version>"to confirm the assets +checksums.txtuploaded.
5. If it breaks
- Failed before publishing? Delete the tag both sides (
git tag -d "v<version>",git push origin ":v<version>"), restore its changes under Unreleased, fix, retry. Verify no public release/assets exist first and retain the exact tag identity in task artifacts. - Already published? Never rewrite a public tag — roll forward with a follow-up patch.
When not to use it
- →Cutting a release for documentation-only changes
- →Releasing when the changelog has no Unreleased entries
- →Rewriting public tags after a release
Prerequisites
Limitations
- →Refuses to cut a release if only documentation files are changed
- →Requires a clean git tree before execution
How it compares
This workflow enforces a strict contract that prevents byte-identical releases and ensures all artifacts are signed and provenance-tracked.
Compared to similar skills
release side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| release (this skill) | 0 | 3mo | No flags | Advanced |
| turborepo | 61 | 4mo | Review | Intermediate |
| bazel-build-optimization | 14 | 5mo | No flags | Advanced |
| ml-pipeline-workflow | 9 | 7mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by AndrewDryga
View all by AndrewDryga →You might also like
turborepo
vercel
Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries. Use when user: configures tasks/workflows/pipelines, creates packages, sets up monorepo, shares code between apps, runs changed/affected packages, debugs cache, or has apps/packages directories.
bazel-build-optimization
wshobson
Optimize Bazel builds for large-scale monorepos. Use when configuring Bazel, implementing remote execution, or optimizing build performance for enterprise codebases.
ml-pipeline-workflow
wshobson
Build end-to-end MLOps pipelines from data preparation through model training, validation, and production deployment. Use when creating ML pipelines, implementing MLOps practices, or automating model training and deployment workflows.
linkerd-patterns
wshobson
Implement Linkerd service mesh patterns for lightweight, security-focused service mesh deployments. Use when setting up Linkerd, configuring traffic policies, or implementing zero-trust networking with minimal overhead.
deployment-pipeline-design
wshobson
Design multi-stage CI/CD pipelines with approval gates, security checks, and deployment orchestration. Use when architecting deployment workflows, setting up continuous delivery, or implementing GitOps practices.
glab
NikiforovAll
Expert guidance for using the GitLab CLI (glab) to manage GitLab issues, merge requests, CI/CD pipelines, repositories, and other GitLab operations from the command line. Use this skill when the user needs to interact with GitLab resources or perform GitLab workflows.