gh-release
Skill2 starsChanged 42 days agoMITView on GitHub
Create an annotated git tag and GitHub prerelease from the latest versioned CHANGELOG entry
- Commits and pushes
1 other project uses a version of this.
Adopted by
Most recently taken up by
- TracecatHQ/tracecattheir own version, first seen Oct 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- TracecatHQ/tracecat★ 3.9ksame name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository22 other files it gives its agents.
- AGENTS.mdAGENTS.md
- changelog-bump-verSkill
- gh-copilot-review-readSkill
- gh-copilot-review-resolveSkill
- gh-copilot-reviewSkill
- gh-cr-submitSkill
- gh-issue-fixSkill
- gh-issueSkill
- gh-pr-mergeSkill
- gh-protect-default-branchSkill
- gh-pr-reviewSkill
- gh-prSkill
- git-branchSkill
- git-commitSkill
- git-pushSkill
- make-changelogSkill
- mir-skills-installSkill
- mir-skills-updateSkill
- python-venvSkill
- save-planSkill
- session-noteSkill
- work-reportSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
53 rules. About 0 are common, 25 are distinctive, and 28 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈25
Distinctive · estimate
This author's own choices. Worth a look.
28
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
Create an annotated git tag for the newest versioned release in CHANGELOG.md
- Distinctive: line 14
Create a GitHub prerelease with notes copied from that same changelog entry
- Very specific: line 15
Treat the first versioned section below ## [Unreleased] as the release to publish
- Distinctive: line 23
Use this skill when:
- Distinctive: line 28
Do not use this skill when:
- Distinctive: line 36
Must be a git repository
- Very specific: line 46
Run changelog-bump-ver first so the newest release already exists as a versioned changelog section
- Very specific: line 74
Not on default branch -> Error: Releases must be created from the default branch tip.
- Distinctive: line 85
If you need to confirm compare-link or release-note behavior during execution, use the WebFetch tool for those URLs.
- Very specific: line 94
If this fails -> error: Error: This skill requires a git repository.
- Very specific: line 99
If missing -> error: Error: CHANGELOG.md not found.
- Very specific: line 130
Prefer gh repo view so repositories with non-main default branches are handled correctly
- Very specific: line 131
If GitHub metadata is unavailable, fall back to origin/HEAD
- Very specific: line 132
If origin/HEAD is unavailable, fall back to local main, then local master
- Very specific: line 134
If empty -> error: Error: Could not determine the default branch.
- Very specific: line 141
If current_branch is not equal to default_branch -> error: Error: Releases must be created from the default branch tip.
- Very specific: line 147
If this prints any output -> error: Error: Working tree is not clean.
- Very specific: line 151
Ensure CHANGELOG.md has exactly one unreleased section:
- Very specific: line 172
Treat v1.2.3 and 1.2.3 as the same version internally
- Very specific: line 173
Always publish the git tag and GitHub release as v1.2.3
- Very specific: line 179
If no such heading exists -> error: Error: No versioned release entry found below ## [Unreleased].
- Very specific: line 183
Read the selected release section from its heading line until the next ## heading or end of file.
- Distinctive: line 188
Keep blank lines and subsection order intact
- Very specific: line 189
Do not invent missing Added, Changed, Fixed, or other subsections
- Distinctive: line 215
If there is another versioned release heading after the selected one, that next heading is the previous release version
- Distinctive: line 216
If there is no older versioned heading, this is the first release
- Distinctive: line 220
Verify that tag exists locally or on origin
- Very specific: line 221
If the previous changelog version exists but the tag does not -> error: Error: Previous changelog version exists but matching git tag was …
- Distinctive: line 224
Use the first commit on the default branch as the start of the full changelog range
- Distinctive: line 232
Use that commit SHA as the start of the compare range.
- Very specific: line 243
If either check finds the tag -> error: Error: Tag vX.Y.Z already exists locally or on origin.
- Very specific: line 275
Use gh repo view --json url --jq '.url' to get the canonical GitHub repository URL
- Very specific: line 279
Do not repeat the release heading line from CHANGELOG.md
- Distinctive: line 280
Do not add extra summary prose above the changelog notes
- Distinctive: line 281
Keep the exact subsection content from the changelog
- Very specific: line 282
Always include the ## Full Changelog section at the end
- Distinctive: line 286
Write the assembled prerelease body from Step 6 into a temporary file before creating the release:
- Very specific: line 305
Do not pass an empty temp file to gh release create --notes-file
- Distinctive: line 306
Remove the temp file after the release command succeeds or fails
- Very specific: line 310
Create the release tag at the current HEAD commit:
- Distinctive: line 317
Use an annotated tag, not a lightweight tag
- Distinctive: line 319
Do not retag an existing version
- Distinctive: line 332
Ensure the prerelease is published from the annotated tag you created in Step 8
- Distinctive: line 333
If the tag push fails, stop and report the error instead of creating the release
- Distinctive: line 337
Create a temporary notes file, then publish the prerelease:
- Distinctive: line 350
Use the already-pushed annotated tag from Step 9 rather than relying on GitHub to create a new ref
- Very specific: line 352
If gh release create fails after the local tag was created:
- Distinctive: line 355
Remove the temp notes file before exiting
- Distinctive: line 356
Do not claim release success
- Distinctive: line 358
After the release command finishes, clean up the temp file:
- Distinctive: line 401
When scanning for the release to publish:
- Very specific: line 402
Start at the ## [Unreleased] heading
- Very specific: line 404
Use document order, not highest-version sorting, because changelog-bump-ver writes the newest release directly below Unreleased
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
What I do
- Create an annotated git tag for the newest versioned release in
CHANGELOG.md - Create a GitHub prerelease with notes copied from that same changelog entry
- Treat the first versioned section below
## [Unreleased]as the release to publish - Preserve the release section subsections and bullets exactly as written in the changelog
- Preserve the repo's
### Miscsubsection at the end of release notes when present - Append a
## Full Changelogsection that compares the previous release to the new tag - Handle first-release repositories by comparing the default branch's first commit to the new release tag
When to use me
Use this skill when:
- You already ran
changelog-bump-verand now want to publish that version as a git tag and GitHub prerelease - The repository uses
CHANGELOG.mdwith Keep a Changelog style version headings - You want prerelease notes to come directly from the latest versioned changelog section
Do not use this skill when:
CHANGELOG.mdstill only has unreleased notes and no new versioned section yet; runchangelog-bump-verfirst- You want this workflow to rewrite
CHANGELOG.md - You want to publish a full GitHub release instead of a prerelease
Prerequisites
Required:
- Must be a git repository
CHANGELOG.mdexists at the repository rootghis installed and authenticatedoriginremote exists- The working tree is clean
HEADis on the default branchCHANGELOG.mdcontains exactly one## [Unreleased]sectionCHANGELOG.mdcontains at least one versioned release heading below## [Unreleased]
Expected workflow:
- Run
changelog-bump-verfirst so the newest release already exists as a versioned changelog section - Then run
gh-releaseto publish that version as a prerelease
Validation checks:
# Check git repository
git rev-parse --git-dir
# Check changelog exists
[ -f CHANGELOG.md ]
# Check GitHub CLI auth
gh auth status
# Check origin remote exists
git remote get-url origin
# Check working tree is clean
git status --short
# Detect default branch from GitHub metadata
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'Error messages:
- Missing changelog ->
Error: CHANGELOG.md not found. Run changelog-bump-ver first. - Missing versioned release ->
Error: No versioned release entry found below ## [Unreleased]. Run changelog-bump-ver first. - Dirty working tree ->
Error: Working tree is not clean. Commit or stash changes before creating a release. - Not on default branch ->
Error: Releases must be created from the default branch tip. - Tag already exists ->
Error: Tag vX.Y.Z already exists locally or on origin. - Missing previous tag for non-first release ->
Error: Previous changelog version exists but matching git tag was not found.
References
This skill follows:
- Keep a Changelog: https://keepachangelog.com/en/1.1.0/
- Semantic Versioning: https://semver.org/spec/v2.0.0.html
- GitHub CLI release create: https://cli.github.com/manual/gh_release_create
If you need to confirm compare-link or release-note behavior during execution, use the WebFetch tool for those URLs.
Workflow
Step 1: Validate Repository State
git rev-parse --git-dir 2>/dev/nullIf this fails -> error: Error: This skill requires a git repository.
[ -f CHANGELOG.md ] && echo "found" || echo "missing"If missing -> error: Error: CHANGELOG.md not found. Run changelog-bump-ver first.
gh auth statusIf this fails -> error: Error: GitHub CLI not authenticated. Run: gh auth login
git remote get-url origin >/dev/nullIf this fails -> error: Error: Git remote 'origin' not found.
default_branch="$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null)"
if [ -z "$default_branch" ]; then
default_branch="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')"
if [ -z "$default_branch" ]; then
if git show-ref --verify --quiet refs/heads/main; then
default_branch="main"
elif git show-ref --verify --quiet refs/heads/master; then
default_branch="master"
fi
fi
fi
printf '%s\n' "$default_branch"Rules:
- Prefer
gh repo viewso repositories with non-maindefault branches are handled correctly - If GitHub metadata is unavailable, fall back to
origin/HEAD - If
origin/HEADis unavailable, fall back to localmain, then localmaster
If empty -> error: Error: Could not determine the default branch.
current_branch="$(git branch --show-current)"
printf '%s\n' "$current_branch"If current_branch is not equal to default_branch -> error: Error: Releases must be created from the default branch tip.
git status --shortIf this prints any output -> error: Error: Working tree is not clean. Commit or stash changes before creating a release.
Step 2: Validate Changelog Shape
Ensure CHANGELOG.md has exactly one unreleased section:
unreleased_count="$(grep -c '^## \[Unreleased\]$' CHANGELOG.md)"
printf '%s\n' "$unreleased_count"Rules:
0-> error:Error: CHANGELOG.md does not contain a ## [Unreleased] section.1-> continue>1-> error:Error: Multiple ## [Unreleased] sections found. Normalize the changelog before releasing.
Then identify the first versioned release heading after ## [Unreleased].
Accepted heading formats:
## [v1.2.3]## [v1.2.3] - 2026-03-20## [1.2.3]## [1.2.3] - 2026-03-20
Normalization rules:
- Treat
v1.2.3and1.2.3as the same version internally - Always publish the git tag and GitHub release as
v1.2.3 - Ignore comparison-link lines such as
[Unreleased]: ...
Selection rule:
- Starting from
## [Unreleased], the first versioned## [...]heading encountered is the release to publish
If no such heading exists -> error: Error: No versioned release entry found below ## [Unreleased]. Run changelog-bump-ver first.
Step 3: Extract Release Version and Notes
Read the selected release section from its heading line until the next ## heading or end of file.
Rules:
- Exclude the selected heading line from the notes body
- Preserve all subsection headings and bullets exactly as written
- Keep blank lines and subsection order intact
- Do not invent missing
Added,Changed,Fixed, or other subsections - Allow nonstandard subsections and keep them unchanged
- Preserve
### Miscexactly as written as the final subsection when the changelog uses the repo's extended template
Example release body extracted from CHANGELOG.md:
### Added
- Support release digests
### Fixed
- Correct changelog parsing for empty sections
### Misc
- Refactor changelog parsing for prerelease note generationNormalize the release version to a tag value:
1.2.3->v1.2.3v1.2.3->v1.2.3
Step 4: Resolve Previous Release Context
Determine whether this is the first release.
Rules:
- If there is another versioned release heading after the selected one, that next heading is the previous release version
- If there is no older versioned heading, this is the first release
For non-first releases:
- Normalize the previous version to
vX.Y.Z - Verify that tag exists locally or on origin
- If the previous changelog version exists but the tag does not -> error:
Error: Previous changelog version exists but matching git tag was not found.
For first releases:
- Use the first commit on the default branch as the start of the full changelog range
Commands:
git rev-list --max-parents=0 "$default_branch" | tail -n 1Use that commit SHA as the start of the compare range.
Step 5: Verify the New Tag Does Not Already Exist
tag="vX.Y.Z"
git rev-parse -q --verify "refs/tags/$tag" >/dev/null && echo "local-exists"
git ls-remote --tags origin "refs/tags/$tag" | grep -q . && echo "remote-exists"If either check finds the tag -> error: Error: Tag vX.Y.Z already exists locally or on origin.
Step 6: Build the GitHub Prerelease Notes
The prerelease title must be exactly the normalized tag:
vX.Y.ZThe prerelease body must be:
- The extracted changelog body for the selected release
- A blank line
## Full Changelog- A compare line in one of these forms
Non-first release:
## Full Changelog
https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0First release:
## Full Changelog
First release: https://github.com/OWNER/REPO/compare/<first-commit-sha>...v0.1.0Repository URL guidance:
- Use
gh repo view --json url --jq '.url'to get the canonical GitHub repository URL - Build the compare link from that URL
Body construction rules:
- Do not repeat the release heading line from
CHANGELOG.md - Do not add extra summary prose above the changelog notes
- Keep the exact subsection content from the changelog
- Always include the
## Full Changelogsection at the end
Step 7: Write the Prerelease Notes File
Write the assembled prerelease body from Step 6 into a temporary file before creating the release:
notes_file="$(mktemp)"
cat > "$notes_file" <<'EOF'
### Added
- Example release note
### Misc
- Example internal refactor note
## Full Changelog
https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0
EOFRules:
- The file content must be the exact assembled release body from Step 6
- Do not pass an empty temp file to
gh release create --notes-file - Remove the temp file after the release command succeeds or fails
Step 8: Create the Annotated Tag
Create the release tag at the current HEAD commit:
git tag -a "vX.Y.Z" -m "Release vX.Y.Z"Rules:
- Use an annotated tag, not a lightweight tag
- Tag the current
HEADonly after all validation passes - Do not retag an existing version
Step 9: Push and Verify the Annotated Tag
Push the annotated tag to origin before creating the GitHub prerelease:
git push origin "vX.Y.Z"
git ls-remote --tags origin "refs/tags/vX.Y.Z"Rules:
- Push the tag before running
gh release create - Ensure the prerelease is published from the annotated tag you created in Step 8
- If the tag push fails, stop and report the error instead of creating the release
Step 10: Create the GitHub Prerelease
Create a temporary notes file, then publish the prerelease:
gh release create "vX.Y.Z" \
--prerelease \
--title "vX.Y.Z" \
--notes-file "$notes_file"Behavior rules:
- The release must be marked with
--prerelease - The release title must match the tag exactly
- The release notes must come from the generated body written in Step 7
- Use the already-pushed annotated tag from Step 9 rather than relying on GitHub to create a new ref
If gh release create fails after the local tag was created:
- Report the failure clearly
- Tell the user the local and remote tag now exist and may need cleanup or retry
- Remove the temp notes file before exiting
- Do not claim release success
After the release command finishes, clean up the temp file:
rm -f "$notes_file"Step 11: Report the Result
Report:
- Published tag
- Whether the release was first release or had a previous release
- Compare range used in
Full Changelog - GitHub prerelease URL
Standard success message:
✓ Created prerelease v0.5.0
- Tag: v0.5.0
- Previous release: v0.4.0
- Full Changelog: https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0
- GitHub prerelease: https://github.com/OWNER/REPO/releases/tag/v0.5.0First release success message:
✓ Created prerelease v0.1.0
- Tag: v0.1.0
- Previous release: none (first release)
- Full Changelog: https://github.com/OWNER/REPO/compare/<first-commit-sha>...v0.1.0
- GitHub prerelease: https://github.com/OWNER/REPO/releases/tag/v0.1.0Version Parsing Rules
Accept these heading patterns when scanning CHANGELOG.md:
^## \[(v)?([0-9]+\.[0-9]+\.[0-9]+)\]$^## \[(v)?([0-9]+\.[0-9]+\.[0-9]+)\] - [0-9]{4}-[0-9]{2}-[0-9]{2}$
Ignore:
- Comparison links such as
[Unreleased]: ... - Headings with non-SemVer values like
vNext,1.0, orrelease-1 - Inline code or prose mentions of versions
When scanning for the release to publish:
- Start at the
## [Unreleased]heading - Select the first later heading that matches the accepted version formats
- Use document order, not highest-version sorting, because
changelog-bump-verwrites the newest release directly belowUnreleased
Release Body Example
Given this changelog excerpt:
## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
### Misc
## [v0.5.0] - 2026-03-20
### Added
- Add `gh-release` skill for annotated tags and GitHub prereleases
### Fixed
- Preserve changelog subsection order in generated release notes
### Misc
- Refactor release note assembly for changelog subsection passthrough
## [v0.4.0] - 2026-03-10
### Added
- Add changelog version bump workflowPublish v0.5.0 with notes body:
### Added
- Add `gh-release` skill for annotated tags and GitHub prereleases
### Fixed
- Preserve changelog subsection order in generated release notes
### Misc
- Refactor release note assembly for changelog subsection passthrough
## Full Changelog
https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0Edge Cases
| Scenario | Behavior |
CHANGELOG.md missing | Error: CHANGELOG.md not found. Run changelog-bump-ver first. |
No ## [Unreleased] section | Error: CHANGELOG.md does not contain a ## [Unreleased] section. |
Multiple ## [Unreleased] sections | Error: Multiple ## [Unreleased] sections found. Normalize the changelog before releasing. |
No versioned release below Unreleased | Error: No versioned release entry found below ## [Unreleased]. Run changelog-bump-ver first. |
| Release version heading is malformed | Ignore it unless it matches the accepted SemVer patterns |
| Current branch is not the default branch | Error: Releases must be created from the default branch tip. |
| Working tree is dirty | Error: Working tree is not clean. Commit or stash changes before creating a release. |
| Tag already exists locally or remotely | Error: Tag vX.Y.Z already exists locally or on origin. |
| Could not determine default branch from GitHub metadata | Fall back to origin/HEAD, then local main, then local master |
| Previous changelog version exists but tag is missing | Error: Previous changelog version exists but matching git tag was not found. |
| Temp notes file was created but not populated | Error: stop before gh release create; do not publish empty notes |
| Annotated tag was created locally but not pushed | Push and verify the tag on origin before creating the release |
| First release with no older version heading | Compare first commit on default branch to new tag |
| First release with a single commit | Compare that same first commit to the new tag |
Release section contains ### Misc | Preserve it unchanged in the generated notes body |
gh release create fails after tag creation | Report partial failure and note that the local tag now exists |
Complete Workflow Example
Scenario: changelog-bump-ver already created ## [v0.5.0] - 2026-03-20 above v0.4.0
- Validate repository state:
git rev-parse --git-dir gh auth status git remote get-url origin git status --short git branch --show-current - Detect default branch:
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' # main - Identify the release heading below
Unreleased:- Selected heading:
## [v0.5.0] - 2026-03-20 - Previous heading:
## [v0.4.0] - 2026-03-10
- Selected heading:
- Verify tags:
git rev-parse -q --verify refs/tags/v0.5.0 git rev-parse -q --verify refs/tags/v0.4.0 - Build notes body:
### Added - Add `gh-release` skill for annotated tags and GitHub prereleases ### Fixed - Preserve changelog subsection order in generated release notes ### Misc - Refactor release note assembly for changelog subsection passthrough ## Full Changelog https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0 - Write notes, push tag, and create prerelease:
notes_file="$(mktemp)" cat > "$notes_file" <<'EOF' ### Added - Add `gh-release` skill for annotated tags and GitHub prereleases ### Fixed - Preserve changelog subsection order in generated release notes ### Misc - Refactor release note assembly for changelog subsection passthrough ## Full Changelog https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0 EOF git tag -a "v0.5.0" -m "Release v0.5.0" git push origin "v0.5.0" gh release create "v0.5.0" \ --prerelease \ --title "v0.5.0" \ --notes-file "$notes_file" rm -f "$notes_file" - Notify the user:
✓ Created prerelease v0.5.0 - Tag: v0.5.0 - Previous release: v0.4.0 - Full Changelog: https://github.com/OWNER/REPO/compare/v0.4.0...v0.5.0 - GitHub prerelease: https://github.com/OWNER/REPO/releases/tag/v0.5.0
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

