Automated release creation, changelog maintenance, version syncing, tagging, and GitHub Releases using Clean Commit or Conventional Commit messages.
- Why Use This Action?
- How It Works
- Features
- Commit Type Mapping
- Quick Start
- Inputs
- Monorepo Support
- Outputs
- Examples
- Conventional Commit Examples
- Generated CHANGELOG.md Example
- Development
- Troubleshooting
- License
- Contributing
- Acknowledgments
This action turns commit history into releases with minimal workflow code. It can:
- detect semantic version bumps from commit types and breaking changes
- generate Keep a Changelog entries
- update supported manifest versions
- commit changelog and version-file updates
- create release tags and floating major tags like
v1 - publish GitHub Releases
- support per-package and unified monorepo flows
graph LR
A[Commits] --> B[Detect version bump]
B --> C[Parse commits]
C --> D[Generate changelog]
D --> E[Sync version files]
E --> F[Commit changelog]
F --> G[Create tags]
G --> H[Create GitHub Release]
Versioning is deterministic. When no tags exist, the action first checks package.json, Cargo.toml, pyproject.toml, or pubspec.yaml, then falls back to initial-version.
- semantic versioning from commit history
- Clean Commit and Conventional Commit support
- Keep a Changelog generation
- Clean Commit maintenance types flow into
[Unreleased]until the next release - monorepo
[Unreleased]updates respectroot-changelogandper-package-changelog - optional changelog commit back to the repository
- automatic manifest version syncing for
package.json,Cargo.toml,pyproject.toml, andpubspec.yaml - GitHub Release creation with generated notes
- floating major tag updates such as
v1 - monorepo package detection, per-package bumps, and unified version mode
- structured outputs for downstream workflows
Default changelog mapping:
| Commit Type | Section |
|---|---|
feat, new, add |
Added |
fix, bugfix, revert |
Fixed |
security |
Security |
perf, refactor, update, change, chore, setup, docs, test, release |
Changed |
deprecate |
Deprecated |
remove, delete |
Removed |
Rules:
BREAKING CHANGE,BREAKING-CHANGE,breaking, or!trigger a major bump- clean-commit defaults use
feat,new,addfor minor andfix,bugfix,security,perf,update,removefor patch - conventional defaults use
featfor minor andfix,perf,revertfor patch - default excluded types are
docs,style,test,ci,build,release
name: Release
on:
push:
branches: [main]
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
changelog-path: ./CHANGELOG.md
sync-version-files: true
update-major-tag: true
release-name-template: '{tag}'- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
prerelease-prefix: beta
release-prerelease: true- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
tag-only: true| Input | Description | Default |
|---|---|---|
github-token |
Token used for tags, releases, and pushes | ${{ github.token }} |
| Input | Description | Default |
|---|---|---|
main-branch |
Production branch name. The action fails when the current branch does not match. | main |
| Input | Description | Default |
|---|---|---|
version-prefix |
Prefix for release tags | v |
initial-version |
Fallback version when no tags or manifest version exist. Uses plain X.Y.Z. |
0.1.0 |
planned-version |
Immutable release version to use instead of recalculating it. Requires planned-version-tag and planned-version-bump-type, and accepts valid SemVer including prerelease and build suffixes. |
`` |
planned-version-tag |
Immutable release tag to use instead of recalculating it. Must equal ${version-prefix}${planned-version}. |
`` |
planned-version-bump-type |
Immutable release bump type to use instead of recalculating it. Must be major, minor, or patch. |
`` |
planned-previous-version |
Previous release version paired with the plan. Leave empty for an initial release; otherwise it must be valid SemVer and its tag must exist. | `` |
prerelease-prefix |
Prefix for prerelease versions | `` |
major-keywords |
Comma-separated keywords that trigger major bumps | BREAKING CHANGE,BREAKING-CHANGE,breaking |
minor-keywords |
Comma-separated keywords that trigger minor bumps, empty uses convention-aware defaults | `` |
patch-keywords |
Comma-separated keywords that trigger patch bumps, empty uses convention-aware defaults | `` |
fetch-depth |
Number of commits fetched for changelog generation, 0 for all |
0 |
include-all-commits |
Include all commits instead of only commits since the last tag | false |
| Input | Description | Default |
|---|---|---|
changelog-path |
Path to the root changelog | ./CHANGELOG.md |
changelog-enabled |
Generate changelog entries | true |
commit-changelog |
Commit changelog and version-file updates | true |
commit-type-mapping |
JSON map from commit types to changelog sections, empty uses convention-aware defaults | `` |
exclude-types |
Comma-separated commit types to skip, empty uses convention-aware defaults | `` |
exclude-scopes |
Comma-separated scopes to skip | `` |
| Input | Description | Default |
|---|---|---|
create-release |
Create a GitHub Release | true |
release-draft |
Publish release as draft | false |
release-prerelease |
Mark release as prerelease | false |
release-name-template |
Template using {tag}, {version}, and {date} |
{tag} |
tag-only |
Create tags but skip GitHub Release | false |
dry-run |
Skip pushes and release creation | false |
update-major-tag |
Update major tag such as v1 to the release commit |
false |
| Input | Description | Default |
|---|---|---|
git-user-name |
Git identity used for generated commits | WG Tech Labs |
git-user-email |
Git email used for generated commits | 262751631+wgtechlabs-automation@users.noreply.github.com |
commit-convention |
Convention for generated commits and smart defaults | clean-commit |
| Input | Description | Default |
|---|---|---|
sync-version-files |
Update manifest versions automatically | true |
version-file-paths |
Comma-separated manifest paths, auto-detected when omitted | `` |
Supported files: package.json, Cargo.toml, pyproject.toml, pubspec.yaml.
| Input | Description | Default |
|---|---|---|
monorepo |
Enable monorepo mode | false |
workspace-detection |
Auto-detect workspaces | true |
change-detection |
Route package changes by scope, path, or both |
both |
scope-package-mapping |
Explicit JSON map of commit scopes to package paths | `` |
per-package-changelog |
Write package-level changelogs | true |
root-changelog |
Write aggregated root changelog | true |
monorepo-root-release |
Create root tag and GitHub Release alongside package releases | true |
unified-version |
Use one shared version for all packages | false |
cascade-bumps |
Reserved for future use | false |
package-manager |
npm, bun, pnpm, or yarn; auto-detected when omitted |
`` |
When monorepo: true is enabled, the action can:
- discover packages from supported workspace files
- route commits by scope, changed paths, or both
- calculate per-package or unified bumps
- generate package changelogs and a root changelog
- create package tags such as
@scope/pkg@1.2.0 - optionally create a root release tag such as
v1.2.0
name: Monorepo Release
on:
push:
branches: [main]
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: release
uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
monorepo: true
change-detection: both
per-package-changelog: true
monorepo-root-release: true- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
monorepo: true
unified-version: true- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
monorepo: true
scope-package-mapping: |
{
"core": "packages/core",
"cli": "packages/cli"
}| Output | Description |
|---|---|
version |
Generated version number |
version-tag |
Full tag with prefix |
previous-version |
Previous version number |
version-bump-type |
major, minor, patch, or none |
| Output | Description |
|---|---|
release-created |
Whether a GitHub Release was created |
release-id |
GitHub Release ID |
release-url |
GitHub Release URL |
release-upload-url |
Upload URL for release assets |
| Output | Description |
|---|---|
major-tag |
Updated floating major tag, or empty when disabled |
| Output | Description |
|---|---|
changelog-updated |
Whether the changelog changed |
changelog-entry |
Generated changelog entry |
commit-count |
Number of commits in the release |
| Output | Description |
|---|---|
added-count |
Number of Added items |
changed-count |
Number of Changed items |
deprecated-count |
Number of Deprecated items |
removed-count |
Number of Removed items |
fixed-count |
Number of Fixed items |
security-count |
Number of Security items |
| Output | Description |
|---|---|
packages-updated |
Compact JSON array of updated packages |
packages-count |
Number of updated packages |
name: Release
on:
push:
branches: [main]
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: release
uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- run: |
echo "Version: ${{ steps.release.outputs.version }}"
echo "Tag: ${{ steps.release.outputs.version-tag }}"
echo "URL: ${{ steps.release.outputs.release-url }}"- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
exclude-scopes: frontend,docs
commit-type-mapping: |
{
"feat": "Added",
"fix": "Fixed",
"security": "Security",
"perf": "Changed",
"remove": "Removed"
}- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
release-draft: true- id: release
uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- if: steps.release.outputs.release-created == 'true'
run: |
echo "Released ${{ steps.release.outputs.version-tag }}"
echo "Fixed: ${{ steps.release.outputs.fixed-count }}"Releases created with the default GITHUB_TOKEN do not trigger other workflows listening for release events in the same repository. Use a PAT or GitHub App token if you need downstream release workflows.
- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GH_PAT }}# minor
feat: add user authentication
new: support themes
# patch
fix: resolve worker leak
bugfix(auth): correct token validation
security: patch XSS issue
# major
feat(api)!: change response format
# changed
perf: improve query performance
refactor: simplify auth module
setup: update release workflow
# deprecated
deprecate: mark legacy API as deprecated
# removed
remove: delete deprecated v1 endpoints
# excluded by default
docs: update README
test: add unit tests
ci: update workflow# Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
## [Unreleased]
## [1.2.0] - 2026-03-09
### Added
- User authentication with OAuth2
### Changed
- Improved query performance
### Fixed
- Corrected token validation
### Security
- Patched XSS vulnerabilitybash run-tests.sh- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
dry-run: trueUse a dry run first to capture the computed release plan from the action outputs, then pass the approved values back on the final run so the root release remains immutable even if new commits land before finalization. planned-version, planned-version-tag, and planned-version-bump-type are required together; planned-previous-version may be empty for a first release. Planned versions support valid SemVer, including prerelease and build suffixes. When a previous version is supplied, finalization verifies its tag still exists after fetching tags. Note that automatic tag discovery only recognizes plain X.Y.Z tags as previous releases, so if you release a prerelease or build-metadata tag (e.g., v0.1.0-beta.1+build.7), later runs will not treat it as the latest tag and will plan versions from the most recent plain X.Y.Z tag instead. This applies to single-package repositories and both unified and per-package monorepos; per-package processing continues with its normal package calculations.
- id: plan
uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
dry-run: true
- uses: wgtechlabs/release-build-flow-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
planned-version: ${{ steps.plan.outputs.version }}
planned-version-tag: ${{ steps.plan.outputs.version-tag }}
planned-version-bump-type: ${{ steps.plan.outputs.version-bump-type }}
planned-previous-version: ${{ steps.plan.outputs.previous-version }}Use outputs such as version-tag, release-url, packages-updated, and major-tag to chain builds, notifications, or artifact publishing.
Use version-bumping commit types such as feat, new, add, fix, bugfix, security, perf, update, or remove.
The action enforces main-branch as a production-branch guard. Run it on the configured branch or change main-branch to match your production branch.
Check changelog-enabled, exclude-types, and exclude-scopes.
Ensure:
permissions.contents: writeis set in the workflowcreate-releaseistruedry-runisfalse
Grant:
permissions:
contents: writeCheck workspace files, package manifests, and workspace-detection.
Use scoped commits, verify package paths, or provide scope-package-mapping.
Use a PAT or GitHub App token instead of the default GITHUB_TOKEN when another workflow depends on release events.
MIT. See LICENSE.
Contributions are welcome. See CONTRIBUTING.md.