GitHub Actions Release Automation
A release marks a stable version of your software that users can download. Creating releases by hand invites mistakes: forgotten files, missing notes, wrong version labels. A workflow handles the same job in seconds and repeats it perfectly every time.
Release Automation in Simple Words
Think of a bakery that stamps each loaf with a batch number and ships it in a labeled box. The baker only decides when a batch is ready. The packaging line does the rest. A tag is the baker's decision, and the workflow is the packaging line.
Version Tags
A Git tag is a permanent label on a specific commit. Teams usually follow semantic versioning, which uses three numbers.
v 2 . 5 . 1
| | |
| | +-- Patch: bug fixes only
| +------ Minor: new features, nothing breaks
+---------- Major: changes that may break old usageThe Release Pipeline
+------------+ +-------------+ +-----------+ +----------------+
| Push tag | --> | Build and | --> | Package | --> | Create GitHub |
| v1.2.0 | | test code | | files | | Release + notes|
+------------+ +-------------+ +-----------+ +----------------+Trigger on Tag Push
A tag filter starts the workflow only for version tags.
on:
push:
tags:
- "v*"The pattern v* matches v1.0.0, v2.3.4, and any other tag that starts with the letter v.
Complete Workflow
name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build project
run: |
mkdir dist
echo "Build for ${{ github.ref_name }}" > dist/info.txt
zip -r app-${{ github.ref_name }}.zip dist
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
app-${{ github.ref_name }}.zip \
--title "Version ${{ github.ref_name }}" \
--generate-notesKey Details Explained
Permission
The contents: write scope allows the token to create releases. Read access fails with a permission error.
The ref_name Value
For a tag push, github.ref_name holds the tag text, such as v1.2.0. The workflow uses it in file names and titles.
Generated Notes
The --generate-notes flag collects merged pull requests since the previous release and writes a summary. Contributors receive credit automatically.
Attached Files
Each file path after the tag becomes a downloadable asset on the release page.
Publish a Tag
Run these two commands on your computer to start the pipeline.
git tag v1.2.0
git push origin v1.2.0Open the Actions tab to watch the run. The Releases section on the repository home page shows the new version when the job completes.
Pre-Releases and Drafts
| Flag | Effect |
|---|---|
| --prerelease | Marks the release as not production-ready |
| --draft | Saves the release for review before the public sees it |
| --latest | Pins the release as the latest stable version |
A draft step works well with environments: the workflow creates a draft, a reviewer reads the notes, and publishing happens manually.
Running Tests First
Add a test job and make the release job wait for it with needs. A failing test blocks the release, so broken code never reaches users.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
release:
needs: test
runs-on: ubuntu-latest
steps:
- run: echo "Safe to release"Good Habits
- Use tags that start with v and follow semantic versioning.
- Protect the main branch so only reviewed code gets tagged.
- Store checksums next to downloads so users can verify files.
- Keep release notes readable with clear pull request titles.
Consistent tags and clear titles turn the automatic notes into a useful changelog that users can trust.
