| name | release-management |
| description | Manage GitHub releases - create releases, upload assets, manage tags, and generate release notes using gh CLI |
GitHub Release Management Skill
This skill provides operations for managing GitHub releases, including creating releases, uploading assets, managing tags, and distributing software versions.
Available Operations
1. Create Release
Create a new release with tag, title, and release notes.
2. List Releases
View all releases in a repository.
3. View Release
Get details about a specific release.
4. Edit Release
Update release information.
5. Delete Release
Remove a release (keeps the tag).
6. Upload Assets
Add files to a release.
7. Download Assets
Download release assets.
8. Delete Assets
Remove assets from a release.
9. Manage Tags
Create and manage Git tags for releases.
Usage Examples
Create Release
Create release from tag:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes "Initial release with core features"
Create with auto-generated notes:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--generate-notes
Create from notes file:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes-file CHANGELOG.md
Create pre-release:
gh release create v2.0.0-beta.1 --repo owner/repo-name \
--title "Version 2.0.0 Beta 1" \
--notes "Beta release for testing" \
--prerelease
Create draft release:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes "Release draft" \
--draft
Create with assets:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes "Release with binaries" \
dist/app-linux-x64.tar.gz \
dist/app-macos-x64.tar.gz \
dist/app-windows-x64.zip
Create on specific branch/commit:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes "Release notes" \
--target main
Latest release:
gh release create v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0" \
--notes "Latest stable release" \
--latest
List Releases
List all releases:
gh release list --repo owner/repo-name
Limit results:
gh release list --repo owner/repo-name --limit 10
Exclude drafts:
gh release list --repo owner/repo-name --exclude-drafts
Exclude pre-releases:
gh release list --repo owner/repo-name --exclude-pre-releases
JSON output:
gh release list --repo owner/repo-name --json tagName,name,publishedAt,isPrerelease,isDraft
Using API:
gh api repos/owner/repo-name/releases --jq '.[] | {tag: .tag_name, name: .name, published: .published_at}'
View Release
View latest release:
gh release view --repo owner/repo-name
View specific release:
gh release view v1.0.0 --repo owner/repo-name
View in browser:
gh release view v1.0.0 --repo owner/repo-name --web
JSON output:
gh release view v1.0.0 --repo owner/repo-name --json tagName,name,body,assets,publishedAt
View assets:
gh release view v1.0.0 --repo owner/repo-name --json assets --jq '.assets[] | {name, size, download_count}'
Edit Release
Update title and notes:
gh release edit v1.0.0 --repo owner/repo-name \
--title "Version 1.0.0 - Updated" \
--notes "Updated release notes"
Update from file:
gh release edit v1.0.0 --repo owner/repo-name \
--notes-file RELEASE_NOTES.md
Mark as latest:
gh release edit v1.0.0 --repo owner/repo-name --latest
Mark as pre-release:
gh release edit v1.0.0 --repo owner/repo-name --prerelease
Publish draft:
gh release edit v1.0.0 --repo owner/repo-name --draft=false
Change to draft:
gh release edit v1.0.0 --repo owner/repo-name --draft
Update discussion category:
gh release edit v1.0.0 --repo owner/repo-name --discussion-category announcements
Delete Release
Delete release (keeps tag):
gh release delete v1.0.0 --repo owner/repo-name
Delete with confirmation:
gh release delete v1.0.0 --repo owner/repo-name --yes
Delete and cleanup tag:
gh release delete v1.0.0 --repo owner/repo-name --yes
git push --delete origin v1.0.0 # Delete remote tag
Upload Assets
Upload single file:
gh release upload v1.0.0 dist/app.tar.gz --repo owner/repo-name
Upload multiple files:
gh release upload v1.0.0 --repo owner/repo-name \
dist/app-linux.tar.gz \
dist/app-macos.tar.gz \
dist/app-windows.zip
Upload with glob pattern:
gh release upload v1.0.0 dist/*.tar.gz --repo owner/repo-name
Overwrite existing asset:
gh release upload v1.0.0 dist/app.tar.gz --repo owner/repo-name --clobber
Using API:
# Get upload URL
UPLOAD_URL=$(gh api repos/owner/repo-name/releases/tags/v1.0.0 --jq '.upload_url' | sed 's/{?name,label}//')
# Upload asset
gh api "$UPLOAD_URL?name=app.tar.gz" \
-X POST \
-H "Content-Type: application/gzip" \
--input dist/app.tar.gz
Download Assets
Download all assets:
gh release download v1.0.0 --repo owner/repo-name
Download specific asset:
gh release download v1.0.0 --repo owner/repo-name --pattern "*.tar.gz"
Download to directory:
gh release download v1.0.0 --repo owner/repo-name --dir downloads/
Download latest release:
gh release download --repo owner/repo-name
Download with pattern matching:
gh release download v1.0.0 --repo owner/repo-name --pattern "*linux*"
Using API to get download URL:
# Get asset URL
gh api repos/owner/repo-name/releases/tags/v1.0.0 --jq '.assets[] | {name, browser_download_url}'
# Download with curl
ASSET_URL=$(gh api repos/owner/repo-name/releases/tags/v1.0.0 --jq '.assets[0].browser_download_url')
curl -L -o app.tar.gz "$ASSET_URL"
Delete Assets
Using API to delete asset:
# Get asset ID
ASSET_ID=$(gh api repos/owner/repo-name/releases/tags/v1.0.0 --jq '.assets[] | select(.name=="app.tar.gz") | .id')
# Delete asset
gh api repos/owner/repo-name/releases/assets/$ASSET_ID -X DELETE
Delete and re-upload:
# Delete old asset
ASSET_ID=$(gh api repos/owner/repo-name/releases/tags/v1.0.0 --jq '.assets[] | select(.name=="app.tar.gz") | .id')
gh api repos/owner/repo-name/releases/assets/$ASSET_ID -X DELETE
# Upload new version
gh release upload v1.0.0 dist/app.tar.gz --repo owner/repo-name
Manage Tags
Create tag:
cd repo-name
git tag -a v1.0.0 -m "Version 1.0.0"
git push origin v1.0.0
List tags:
cd repo-name
git tag -l
View tag details:
cd repo-name
git show v1.0.0
Delete tag:
cd repo-name
git tag -d v1.0.0 # Delete local
git push --delete origin v1.0.0 # Delete remote
Create tag from specific commit:
cd repo-name
git tag -a v1.0.0 abc123def -m "Version 1.0.0"
git push origin v1.0.0
Common Patterns
Standard Release Workflow
# 1. Prepare release
VERSION="v1.2.0"
cd repo-name
# 2. Update version files
echo "1.2.0" > VERSION
git add VERSION
git commit -m "Bump version to 1.2.0"
git push
# 3. Create and push tag
git tag -a $VERSION -m "Release $VERSION"
git push origin $VERSION
# 4. Build release artifacts
npm run build # or your build command
mkdir -p dist
# 5. Create release with artifacts
gh release create $VERSION \
--title "Release $VERSION" \
--generate-notes \
dist/*.tar.gz \
dist/*.zip
Pre-release to Stable
# 1. Create pre-release
gh release create v2.0.0-rc.1 --repo owner/repo-name \
--title "Release Candidate 1" \
--notes "Testing release" \
--prerelease \
dist/*
# 2. After testing, promote to stable
gh release edit v2.0.0-rc.1 --repo owner/repo-name \
--prerelease=false \
--latest
# 3. Or create new stable release
gh release create v2.0.0 --repo owner/repo-name \
--title "Version 2.0.0" \
--notes "Stable release" \
dist/*
Draft Release for Review
# 1. Create draft
gh release create v1.5.0 --repo owner/repo-name \
--title "Version 1.5.0" \
--notes-file CHANGELOG.md \
--draft \
dist/*
# 2. Review in browser
gh release view v1.5.0 --repo owner/repo-name --web
# 3. Publish when ready
gh release edit v1.5.0 --repo owner/repo-name --draft=false
Multi-Platform Release
VERSION="v1.0.0"
# Build for all platforms
./build-linux.sh
./build-macos.sh
./build-windows.sh
# Create release with all platform binaries
gh release create $VERSION --repo owner/repo-name \
--title "Version 1.0.0 - Multi-platform" \
--notes "Available for Linux, macOS, and Windows" \
dist/app-linux-amd64.tar.gz \
dist/app-linux-arm64.tar.gz \
dist/app-darwin-amd64.tar.gz \
dist/app-darwin-arm64.tar.gz \
dist/app-windows-amd64.zip \
dist/app-windows-arm64.zip
Automated Release with GitHub Actions
# Trigger release workflow (example)
gh workflow run release.yml --repo owner/repo-name \
-f version=1.2.0 \
-f prerelease=false
# Monitor release workflow
gh run watch $(gh run list --workflow release.yml --limit 1 --json databaseId --jq '.[0].databaseId')
Rollback Release
# 1. Delete problematic release
gh release delete v1.2.0 --repo owner/repo-name --yes
# 2. Delete tag
git push --delete origin v1.2.0
# 3. Mark previous version as latest
gh release edit v1.1.0 --repo owner/repo-name --latest
Generate Release Notes from Commits
VERSION="v1.3.0"
PREV_VERSION="v1.2.0"
# Get commits since last release
git log $PREV_VERSION..HEAD --pretty=format:"- %s (%h)" > release_notes.txt
# Create release
gh release create $VERSION --repo owner/repo-name \
--title "Release $VERSION" \
--notes-file release_notes.txt \
dist/*
Download Latest Release for Installation
# Script to download and install latest release
REPO="owner/repo-name"
# Get latest release tag
LATEST=$(gh release view --repo $REPO --json tagName --jq '.tagName')
# Download release assets
gh release download $LATEST --repo $REPO --pattern "*linux*"
# Extract and install
tar -xzf app-linux-*.tar.gz
sudo mv app /usr/local/bin/
Advanced Usage
Release Statistics
View download counts:
gh api repos/owner/repo-name/releases --jq '.[] | {
tag: .tag_name,
downloads: [.assets[].download_count] | add
}'
Most popular release:
gh api repos/owner/repo-name/releases --jq 'map({
tag: .tag_name,
downloads: [.assets[].download_count] | add
}) | sort_by(.downloads) | reverse | .[0]'
Asset-level statistics:
gh release view v1.0.0 --repo owner/repo-name --json assets --jq '.assets[] | {
name,
size,
downloads: .download_count
} | sort_by(.downloads) | reverse'
Bulk Release Management
List all tags without releases:
# Get all tags
ALL_TAGS=$(git tag)
# Get tags with releases
RELEASE_TAGS=$(gh release list --repo owner/repo-name --limit 1000 --json tagName --jq '.[].tagName')
# Find difference
comm -23 <(echo "$ALL_TAGS" | sort) <(echo "$RELEASE_TAGS" | sort)
Delete old pre-releases:
gh api repos/owner/repo-name/releases --jq '.[] | select(.prerelease==true) | select(.created_at < "2024-01-01") | .tag_name' | \
while read tag; do
echo "Deleting $tag"
gh release delete $tag --repo owner/repo-name --yes
done
Custom Release Notes Template
# Create release notes from template
cat > release_notes.md << EOF
## What's Changed
$(git log v1.0.0..v1.1.0 --pretty=format:"- %s by @%an" | grep -v "Merge pull request")
## New Contributors
$(git log v1.0.0..v1.1.0 --pretty=format:"%an" | sort -u | sed 's/^/* @/')
**Full Changelog**: https://github.com/owner/repo-name/compare/v1.0.0...v1.1.0
EOF
gh release create v1.1.0 --notes-file release_notes.md
Error Handling
Tag Already Exists
# Check if tag exists
git tag -l v1.0.0
# Delete and recreate if needed
git tag -d v1.0.0
git push --delete origin v1.0.0
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
Release Already Exists
# Check if release exists
gh release view v1.0.0 --repo owner/repo-name 2>&1 | grep -q "release not found" || echo "Release exists"
# Delete and recreate
gh release delete v1.0.0 --repo owner/repo-name --yes
gh release create v1.0.0 --title "Version 1.0.0" --notes "Release notes"
Asset Upload Failures
# Verify asset exists locally
[ -f dist/app.tar.gz ] && echo "File exists" || echo "File not found"
# Check file size (GitHub limit is 2GB per asset)
ls -lh dist/app.tar.gz
# Retry upload
gh release upload v1.0.0 dist/app.tar.gz --repo owner/repo-name --clobber
Best Practices
- Use semantic versioning: Follow vX.Y.Z format (e.g., v1.2.3)
- Write meaningful notes: Include what changed, breaking changes, and upgrade instructions
- Use draft releases: Review before publishing
- Tag commits properly: Create annotated tags with messages
- Include checksums: Provide SHA256 checksums for assets
- Test pre-releases: Use beta/rc releases for testing
- Clean naming: Use consistent asset naming conventions
- Keep releases focused: One release per version
- Link to documentation: Include links to docs in release notes
- Archive old releases: Delete very old pre-releases to reduce clutter
Semantic Versioning
- Major (X.0.0): Breaking changes
- Minor (1.X.0): New features, backwards compatible
- Patch (1.2.X): Bug fixes, backwards compatible
- Pre-release: v1.2.0-alpha.1, v1.2.0-beta.1, v1.2.0-rc.1
Integration with Other Skills
- Use
workflow-managementto automate releases with GitHub Actions - Use
issue-managementto reference issues fixed in release - Use
pull-request-managementto include PR links in notes - Use
commit-operationsto generate changelog from commits