This document provides comprehensive examples for all use cases and scenarios of the GitHub Release action.
- Basic Examples
- Package Manager Examples
- Version Increment Examples
- Prerelease Examples
- Custom Branch Examples
- Dependency Group Examples
- Draft Release Examples
- Complete Workflow Examples
- Monorepo Examples
- Edge Cases and Special Scenarios
The simplest possible release workflow:
name: Release
on:
workflow_dispatch:
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'Behavior:
- Uses default package manager (uv)
- Creates patch version bump (e.g., 1.0.0 → 1.0.1)
- Releases from
mainbranch - Publishes release immediately (not draft)
Prerequisites: Ensure your pyproject.toml has:
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.1.0"
version_files = ["pyproject.toml:version"]
tag_format = "$version"
update_changelog_on_bump = true # Recommended for automatic changelog updatesAllow choosing version increment type:
name: Manual Release
on:
workflow_dispatch:
inputs:
increment:
description: 'Version increment'
required: true
type: choice
options:
- patch
- minor
- major
default: 'patch'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: ${{ inputs.increment }}- name: Release with pip
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
package-manager: 'pip'
python-version: '3.11'
install-groups: 'groups: dev'Project setup (pyproject.toml):
[dependency-groups]
dev = [
"commitizen>=3.0.0",
"pytest>=7.0.0",
]- name: Release with uv
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
package-manager: 'uv'
python-version: '3.12'
install-groups: 'groups: dev docs'Project setup (pyproject.toml):
[dependency-groups]
dev = [
"commitizen>=3.0.0",
"pytest>=7.0.0",
]
docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.0.0",
]With uv.lock:
Ensure your repository has a uv.lock file:
uv lock
git add uv.lock
git commit -m "chore: add uv.lock"- name: Release with pixi
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
package-manager: 'pixi'
install-groups: 'default'Project setup (pixi.toml):
[project]
name = "my-project"
version = "0.1.0"
channels = ["conda-forge"]
[dependencies]
python = ">=3.10"
commitizen = ">=3.0.0"
[tasks]
release = "cz bump"- name: Patch Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'patch'Example:
- Current:
1.2.3 - New:
1.2.4
Commit types that trigger patch:
git commit -m "fix: resolve authentication bug"
git commit -m "fix: patch memory leak"- name: Minor Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'minor'Example:
- Current:
1.2.4 - New:
1.3.0
Commit types that trigger minor:
git commit -m "feat: add user profile feature"
git commit -m "feat: implement OAuth login"- name: Major Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'major'Example:
- Current:
1.3.0 - New:
2.0.0
Commit types that trigger major:
git commit -m "feat!: redesign API endpoints"
git commit -m "feat: remove deprecated methods
BREAKING CHANGE: The old auth methods are no longer supported"- name: Alpha Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'patch'
prerelease-type: 'alpha'Example:
- Current:
1.0.0 - New:
1.0.1a0(first alpha) - Next:
1.0.1a1(second alpha)
Use case: Early development, internal testing
- name: Beta Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'minor'
prerelease-type: 'beta'Example:
- Current:
1.0.0 - New:
1.1.0b0(first beta) - Next:
1.1.0b1(second beta)
Use case: Feature complete, external testing
- name: Release Candidate
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'major'
prerelease-type: 'rc'Example:
- Current:
1.5.0 - New:
2.0.0rc0(first RC) - Next:
2.0.0rc1(second RC)
Use case: Final testing before production release
Complete workflow with multiple prerelease stages:
name: Prerelease Workflow
on:
workflow_dispatch:
inputs:
stage:
description: 'Release stage'
required: true
type: choice
options:
- alpha
- beta
- rc
- final
permissions:
contents: write
jobs:
prerelease:
if: ${{ inputs.stage != 'final' }}
runs-on: ubuntu-latest
steps:
- name: Create Prerelease
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'minor'
prerelease-type: ${{ inputs.stage }}
draft: 'false'
final-release:
if: ${{ inputs.stage == 'final' }}
runs-on: ubuntu-latest
steps:
- name: Create Final Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'minor'
prerelease-type: 'none'- name: Release from Develop
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
release-branch: 'develop'
increment: 'patch'- name: Release v2.x
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
release-branch: 'release/v2.0'
increment: 'patch'name: Multi-Branch Releases
on:
workflow_dispatch:
inputs:
branch:
description: 'Release branch'
required: true
type: choice
options:
- main
- develop
- release/v2.0
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
release-branch: ${{ inputs.branch }}
increment: 'patch'- name: Release with Dev and Docs Groups
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev docs'Project setup:
[dependency-groups]
dev = [
"commitizen>=3.0.0",
"pytest>=7.0.0",
"mypy>=1.0.0",
]
docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.0.0",
]- name: Release with Extras
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'extras: aws viz'Project setup:
[project.optional-dependencies]
aws = [
"boto3>=1.26.0",
"botocore>=1.29.0",
]
viz = [
"matplotlib>=3.5.0",
"plotly>=5.0.0",
]- name: Release with Groups and Extras
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev docs, extras: aws'- name: Release with Core Only
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: ''Note: Ensure Commitizen is in core dependencies:
[project]
dependencies = [
"commitizen>=3.0.0",
"requests>=2.28.0",
]- name: Create Draft Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'minor'
draft: 'true'Use case:
- Review release notes before publishing
- Wait for additional checks/approvals
- Manual testing before announcement
name: Draft Release
on:
push:
branches: [main]
permissions:
contents: write
jobs:
draft:
runs-on: ubuntu-latest
steps:
- name: Create Draft
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
draft: 'true'
- name: Notify Team
run: |
echo "Draft release created. Review at:"
echo "${{ github.server_url }}/${{ github.repository }}/releases"Manual publish:
- Go to GitHub Releases page
- Find the draft release
- Click "Edit"
- Review release notes
- Click "Publish release"
name: Production Release
on:
workflow_dispatch:
inputs:
increment:
description: 'Version increment'
required: true
type: choice
options:
- patch
- minor
- major
confirm:
description: 'Type "yes" to confirm'
required: true
permissions:
contents: write
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Validate Confirmation
if: ${{ inputs.confirm != 'yes' }}
run: |
echo "::error::Release cancelled - confirmation required"
exit 1
test:
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run Tests
run: |
pip install -e ".[dev]"
pytest
release:
needs: test
runs-on: ubuntu-latest
steps:
- name: Create GitHub Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: ${{ inputs.increment }}
package-manager: 'uv'
python-version: '3.12'
- name: Notify Success
run: |
echo "✅ Release ${{ steps.release.outputs.NEW_VERSION }} created"name: Weekly Beta Release
on:
schedule:
- cron: '0 10 * * 1' # Every Monday at 10 AM UTC
workflow_dispatch:
permissions:
contents: write
jobs:
beta:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Check for New Commits
id: check
run: |
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
CHANGES=$(git log $LAST_TAG..HEAD --oneline)
if [ -n "$CHANGES" ]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi
fi
- name: Create Beta Release
if: steps.check.outputs.has_changes == 'true'
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'patch'
prerelease-type: 'beta'
- name: Skip Message
if: steps.check.outputs.has_changes == 'false'
run: echo "No changes since last release, skipping"name: Multi-Python Release
on:
workflow_dispatch:
permissions:
contents: write
jobs:
test:
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Run Tests
run: |
pip install -e ".[dev]"
pytest
release:
needs: test
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
python-version: '3.12' # Use latest for release
increment: 'patch'name: GitFlow Release
on:
push:
branches:
- main
- develop
- 'release/**'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Determine Release Type
id: type
run: |
BRANCH="${{ github.ref_name }}"
if [[ "$BRANCH" == "main" ]]; then
echo "increment=patch" >> $GITHUB_OUTPUT
echo "prerelease=none" >> $GITHUB_OUTPUT
echo "draft=false" >> $GITHUB_OUTPUT
elif [[ "$BRANCH" == "develop" ]]; then
echo "increment=patch" >> $GITHUB_OUTPUT
echo "prerelease=beta" >> $GITHUB_OUTPUT
echo "draft=false" >> $GITHUB_OUTPUT
else
echo "increment=patch" >> $GITHUB_OUTPUT
echo "prerelease=rc" >> $GITHUB_OUTPUT
echo "draft=true" >> $GITHUB_OUTPUT
fi
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
release-branch: ${{ github.ref_name }}
increment: ${{ steps.type.outputs.increment }}
prerelease-type: ${{ steps.type.outputs.prerelease }}
draft: ${{ steps.type.outputs.draft }}For monorepos where each package manages its own version and changelog:
- name: Release sub-package
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
increment: 'minor'
package-manager: 'uv'
install-groups: 'groups: dev'
config-file: 'libs/my-package/pyproject.toml'Sub-package commitizen config (libs/my-package/pyproject.toml):
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.1.0"
# All paths are relative to libs/my-package/, not the repo root
version_files = ["pyproject.toml:version"]
tag_format = "my-package-$version"
update_changelog_on_bump = true
changelog_file = "docs/CHANGELOG.md"Important: Because the action changes into libs/my-package/ before running Commitizen, every path in that section must be relative to libs/my-package/. Using the full repo-relative path (e.g. libs/my-package/pyproject.toml:version) would fail.
Release multiple independent packages in one workflow:
name: Monorepo Release
on:
workflow_dispatch:
inputs:
package:
description: 'Package to release'
required: true
type: choice
options:
- libs/pkg-a
- libs/pkg-b
- libs/pkg-c
increment:
description: 'Version increment'
required: true
type: choice
options:
- patch
- minor
- major
default: 'patch'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: ${{ inputs.increment }}
config-file: '${{ inputs.package }}/pyproject.toml'Scenario: Creating the very first release of a project
- name: First Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
increment: 'patch'Requirements:
- CHANGELOG.md must exist (can be empty)
- At least one conventional commit
- Commitizen configured in pyproject.toml
Behavior:
- Generates full changelog from all commits
- Creates first tag (e.g., 0.1.0)
- Warning shown (not an error)
Setup:
# Create CHANGELOG.md
cat > CHANGELOG.md << 'EOF'
# Changelog
All notable changes to this project will be documented in this file.
EOF
# Commit with conventional format
git add CHANGELOG.md
git commit -m "docs: add changelog"
# Make some changes
git commit -m "feat: initial implementation"
git commit -m "fix: resolve setup issue"Scenario: Minimal project with only core dependencies
- name: Release Minimal Project
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: ''Project setup:
[project]
name = "minimal-project"
version = "0.1.0"
dependencies = [
"commitizen>=3.0.0", # Required!
"requests>=2.28.0",
]
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.1.0"
version_files = ["pyproject.toml:version"]
tag_format = "$version"Scenario: Previous release attempt failed, need to retry
# Check current state
git status
git log --oneline -5
# If version was bumped but not pushed
git reset --soft HEAD~1 # Undo commit
git restore --staged . # Unstage changes
# If tag was created locally
git tag -d 1.2.3 # Delete local tag
# Clean state, retry releasePrevention: Use draft releases for testing:
- name: Safe Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
draft: 'true' # Safe to retryScenario: Ensure release works on all platforms
name: Cross-Platform Release
on:
workflow_dispatch:
permissions:
contents: write
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- name: Test on ${{ matrix.os }}
run: |
pip install -e ".[dev]"
pytest
release:
needs: test
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'Scenario: Emergency fix on production
name: Hotfix Release
on:
push:
branches:
- 'hotfix/**'
permissions:
contents: write
jobs:
hotfix:
runs-on: ubuntu-latest
steps:
- name: Create Hotfix Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
release-branch: ${{ github.ref_name }}
increment: 'patch'
draft: 'false'
- name: Cherry-pick to Main
run: |
git checkout main
git cherry-pick ${{ github.sha }}
git push origin mainScenario: Attach build artifacts to release
name: Release with Artifacts
on:
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Build Distribution
run: |
pip install build
python -m build
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'
- name: Upload Release Assets
uses: softprops/action-gh-release@v2
with:
files: dist/*
tag_name: ${{ steps.release.outputs.NEW_VERSION }}Scenario: Ensure changelog follows format
name: Validated Release
on:
workflow_dispatch:
permissions:
contents: write
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Validate Commits
run: |
pip install commitizen
cz check --rev-range $(git describe --tags --abbrev=0)..HEAD
release:
needs: validate
runs-on: ubuntu-latest
steps:
- name: Create Release
uses: serapeum-org/github-actions/actions/release/github@github-release/v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
install-groups: 'groups: dev'Start with draft releases for important deployments:
draft: 'true'Run tests and checks before creating releases:
jobs:
test:
# ... run tests
release:
needs: test
# ... create releaseEnsure all commits follow the convention:
feat: add new feature
fix: resolve bug
docs: update documentation
chore: update dependenciesKeep a changelog file in your repository (required).
Use alpha/beta/rc for testing before final release:
prerelease-type: 'beta'Reference specific action versions:
uses: serapeum-org/github-actions/actions/release/github@github-release/v1.0.0Always include required permissions:
permissions:
contents: writeSee the main README.md for common issues and solutions.