name: git-release version: 1.0.0 description: Automate semver releases — bump version, generate changelog, tag, and publish GitHub Release. author: ZeptoClaw license: MIT tags:
- git
- release
- devops
- changelog
- semver env_needed:
- name: GITHUB_TOKEN description: Personal access token with repo scope (for creating GitHub Releases) required: true
- name: GH_REPO description: "Repository in owner/repo format (e.g. myorg/myapp)" required: true metadata: {"zeptoclaw":{"emoji":"🚀","requires":{"anyBins":["git","gh","jq"]}}}
Git Release Skill
Automate the full release workflow: semver bump → changelog → git tag → GitHub Release.
Setup
export GITHUB_TOKEN="ghp_xxx..."
export GH_REPO="myorg/myapp"
Or if already logged in with gh auth login, skip GITHUB_TOKEN — the gh CLI uses its own token.
Check What Changed Since Last Release
# Show last tag
git describe --tags --abbrev=0
# Commits since last tag
git log $(git describe --tags --abbrev=0)..HEAD --oneline
# Count breaking / feat / fix
git log $(git describe --tags --abbrev=0)..HEAD --oneline | grep -c "^.*feat"
git log $(git describe --tags --abbrev=0)..HEAD --oneline | grep -c "^.*fix"
Determine Next Version (Semver)
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
MAJOR=$(echo $LAST_TAG | sed 's/v//' | cut -d. -f1)
MINOR=$(echo $LAST_TAG | sed 's/v//' | cut -d. -f2)
PATCH=$(echo $LAST_TAG | sed 's/v//' | cut -d. -f3)
# Bump patch (bug fixes only)
NEXT="v${MAJOR}.${MINOR}.$((PATCH + 1))"
# Bump minor (new features, no breaking changes)
NEXT="v${MAJOR}.$((MINOR + 1)).0"
# Bump major (breaking changes)
NEXT="v$((MAJOR + 1)).0.0"
echo "Last: $LAST_TAG → Next: $NEXT"
Generate Changelog from Commits
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
RANGE="${LAST_TAG:+${LAST_TAG}..}HEAD"
# Categorized changelog
BREAKING=$(git log $RANGE --oneline | grep -i "BREAKING\|!:" || true)
FEATURES=$(git log $RANGE --oneline | grep -i "^[a-f0-9]* feat" || true)
FIXES=$(git log $RANGE --oneline | grep -i "^[a-f0-9]* fix" || true)
OTHERS=$(git log $RANGE --oneline | grep -iv "^[a-f0-9]* \(feat\|fix\|chore\|docs\)" || true)
cat << EOF
## What's Changed
${BREAKING:+### Breaking Changes
$BREAKING
}${FEATURES:+### Features
$FEATURES
}${FIXES:+### Bug Fixes
$FIXES
}${OTHERS:+### Other Changes
$OTHERS
}
**Full Changelog**: https://github.com/$GH_REPO/compare/${LAST_TAG}...${NEXT}
EOF
Create Tag and Push
NEXT="v1.2.0" # set your version
# Create annotated tag
git tag -a "$NEXT" -m "Release $NEXT"
# Push tag
git push origin "$NEXT"
echo "Tag $NEXT pushed"
Create GitHub Release
# Generate notes and create release
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | head -1)
NOTES=$(git log ${LAST_TAG:+${LAST_TAG}..}HEAD --oneline \
| sed 's/^[a-f0-9]* /- /' \
| head -30)
gh release create "$NEXT" \
--title "Release $NEXT" \
--notes "## What's Changed
$NOTES
**Full Changelog**: https://github.com/$GH_REPO/compare/${LAST_TAG}...${NEXT}" \
--verify-tag
Attach Build Artifacts to Release
# Build first (adjust for your stack)
# cargo build --release
# npm run build
# Upload artifacts
gh release upload "$NEXT" \
./target/release/myapp \
./target/release/myapp.tar.gz \
--clobber
Full Release Workflow (One-liner)
# Set version
NEXT="v1.2.0"
LAST=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
# Tag
git tag -a "$NEXT" -m "Release $NEXT" && git push origin "$NEXT"
# Release
gh release create "$NEXT" \
--generate-notes \
--title "Release $NEXT"
echo "Released: https://github.com/$GH_REPO/releases/tag/$NEXT"
Tips
- Use
--generate-noteswithgh release create— GitHub auto-generates changelog from PRs - Protect your main branch; require PRs so release notes are PR-title based (cleaner than raw commits)
- For Rust: bump
Cargo.tomlversion before tagging:sed -i "s/^version = .*/version = \"1.2.0\"/" Cargo.toml - For Node:
npm version patch/minor/majorauto-bumpspackage.jsonand creates a commit + tag - Tag format: always use
vprefix (v1.2.0) — most tools expect it - Draft releases first with
--draft, review, thengh release edit $NEXT --draft=false