When you tag a version, you usually want the same things to happen every time: build the artifacts, attach them, and publish notes. This generator builds a GitHub Actions workflow that fires on a version tag, runs your build, auto-generates release notes from commit history, and uploads your assets to a GitHub Release.
How it works
The workflow listens on a push event filtered to tags matching your pattern. On a match it:
- Checks out the full history so the changelog action can diff against the previous tag.
- Runs your build command to produce the release artifacts.
- Calls
softprops/action-gh-release, which creates the release for the pushed tag, setsgenerate_release_notes: true, and uploads every file matching your asset globs.
It needs only the built-in GITHUB_TOKEN with contents: write permission — no personal access token.
Full workflow skeleton
name: Release
on:
push:
tags:
- "v*" # fires on v1.0.0, v2.3.1-rc1, etc.
permissions:
contents: write # needed to create releases and upload assets
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so release notes diff against the previous tag
- name: Build artifacts
run: make dist # replace with your actual build command
- name: Publish release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true # GitHub builds notes from merged PRs since the last tag
prerelease: false
files: |
dist/*.tar.gz
dist/*.zip
How auto-generated release notes work
When generate_release_notes: true is set, GitHub queries the merged pull requests between the previous tag and the current one and formats them into a changelog. The result groups PRs by label (features, bug fixes, and so on) if you have configured a .github/release.yml categorisation file.
The quality of auto-generated notes depends directly on your PR titles. A PR titled “fix login bug” produces a vague changelog entry; a PR titled fix: handle expired session token on refresh produces a useful one. If your team uses Conventional Commits, the titles translate naturally.
Choosing your tag pattern
Use v* to match all semver-style tags (v1.0.0, v2.1.0-beta.1). For projects releasing multiple artifacts from one repo, consider a prefix like api/v* or cli/v* and separate workflows per prefix. Avoid tagging the default branch directly for releases — always push the tag explicitly after finalising the commit.
Pre-releases and release candidates
Enable the pre-release toggle and the workflow sets prerelease: true on the GitHub Release, which marks it clearly as non-stable and excludes it from the “latest release” pointer. This is the correct approach for tags like v2.0.0-rc1 or v3.0.0-beta.2 — package registries and tools that watch the latest release tag will not pick these up accidentally.
Tips and notes
- Use a tag pattern like
v*so only version tags publish releases, not every tag. - Generated notes summarize merged pull requests since the last tag; write clear PR titles for clean changelogs.
- Provide multiple asset globs (one per line) to attach binaries for several platforms in a single release.
- For signed or checksummed assets, add a step before the release that produces the
.sha256files and include them in the globs. fetch-depth: 0is essential — without full history, the notes generator cannot find the previous tag to diff against.