Use when preparing a release, tagging a version, or when user says "release", "tag", "ship it", "push to production" - ensures all release artifacts are verified before tagging to avoid the...
Never tag until CI passes. Every retag erodes trust and wastes time.
This skill prevents the "tag, watch CI fail, retag, repeat" anti-pattern by establishing a pre-flight checklist that catches issues BEFORE creating the tag.
NO TAG WITHOUT GREEN CI
Run the full verification locally. Fix everything. THEN tag. Not before.
MANDATORY: Use TodoWrite to create todos for EACH item.
Check ALL places that reference your main package:
goreleaser.yml - main: field (common: ./cmd/app vs .).github/workflows/*.yml - any go build commandsMakefile - build targetsDockerfile - build commands# Find all references to cmd/ or main package paths
grep -r "cmd/" . --include="*.yml" --include="*.yaml" --include="Makefile" --include="Dockerfile"
grep -r "go build" . --include="*.yml" --include="*.yaml" --include="Makefile"
Go 1.23+ coverage tool fails on packages without tests:
# Check for test files in each package
find . -name "*_test.go" | wc -l
# If zero, add placeholder tests to EVERY package
Every package needs at least one test file or CI coverage step fails with no such tool "covdata".
# Run what CI runs
make test # or go test ./...
make lint # or golangci-lint run
make build # verify it compiles
# If using coverage
make test-coverage
.gitignore includes build artifacts, coverage filesgit status # Nothing unexpected staged
git diff --stat # Review all changes
git log --oneline -5 # Verify recent history
Only after ALL checks pass:
# 1. Commit all changes
git add -A && git commit -m "release: prepare v0.0.X"
# 2. Wait for pre-commit hooks to pass
# If hooks fail, fix and re-commit
# 3. Push and wait for CI
git push origin main
# 4. WAIT FOR CI TO PASS - check status
gh run list --limit 2
# OR watch in browser
# 5. Only after CI is green, create tag
git tag -a v0.0.X -m "v0.0.X"
git push origin v0.0.X
# 6. Verify release workflow completes
gh run list --limit 2
If you catch yourself doing any of these, STOP:
All of these mean: Wait for CI. Fix issues. Then tag.
| Symptom | Cause | Fix |
|---|---|---|
couldn't find main file |
Wrong path in goreleaser | Set main: . if main.go at root |
no such tool "covdata" |
Package without tests | Add placeholder test to each package |
| Release succeeds but brew fails | Wrong description/homepage | Update goreleaser brews section |
| Had to retag | Tagged before CI passed | WAIT FOR GREEN CI |
| 504 errors in CI | GitHub infra issue | Retry workflow, not a code problem |
When incrementing version:
Search codebase for version references:
grep -r "version" . --include="*.go" --include="*.yml" --include="*.json" | grep -v test | grep -v vendor
After tag is pushed:
# Watch release workflow
gh run watch
# Verify release assets
gh release view v0.0.X
# Test installation (if applicable)
go install github.com/user/repo@v0.0.X
Retagging is a symptom of rushing.
The 5 minutes spent on pre-flight checks saves 30 minutes of retag cycles and preserves your release history integrity.
Every tag should be final. If you're deleting tags, you skipped the checklist.