Auto-generate changelogs from Conventional Commits and create GitHub Releases using a single GitHub Action.
requarks/changelog-action is a GitHub Action that analyzes commits between git tags and generates a Markdown changelog. It automatically handles PR links, author attribution, and BREAKING CHANGE highlights.
BREAKING CHANGE notes to the top of version entriesv* (e.g., v0.2.3)type(scope): description
[optional body]
[optional footer(s)]
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
refactor |
Code refactoring (no behavior change) |
docs |
Documentation changes |
test |
Adding/modifying tests |
chore |
Build, config, and other maintenance |
ci |
CI/CD configuration changes |
perf |
Performance improvements |
build |
Build system changes |
style |
Code formatting changes |
| Parameter | Required | Default | Description |
|---|---|---|---|
token |
Yes | — | GitHub API token (${{ github.token }}) |
tag |
Yes* | — | Current tag (single-tag mode) |
fromTag |
Yes* | — | Start tag for range-based changelog |
toTag |
Yes* | — | End tag for range-based changelog |
excludeTypes |
No | build,docs,other,style |
Comma-separated commit types to exclude |
excludeScopes |
No | — | Comma-separated scopes to exclude |
restrictToTypes |
No | — | Include only specific types (overrides excludeTypes) |
writeToFile |
No | true |
Auto-generate CHANGELOG.md |
changelogFilePath |
No | CHANGELOG.md |
Changelog file path |
includeInvalidCommits |
No | false |
Include non-conventional commits |
useGitmojis |
No | true |
Prepend emoji to type headers |
reverseOrder |
No | false |
List commits newest-to-oldest |
Use either
tagOR bothfromTag/toTag. In single-tag mode, the previous tag is detected automatically.
| Output | Description |
|---|---|
changes |
Generated changelog content (without version/date header) |
Adding changelog generation to an npm auto-publish workflow.
name: Publish to npm
on:
push:
tags:
- 'v*'
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm run check
- run: npm run build
- run: npm test
publish:
needs: ci
runs-on: ubuntu-latest
permissions:
contents: write # Required for GitHub Release creation
id-token: write # npm Trusted Publishing
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history needed for tag comparison
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: https://registry.npmjs.org
cache: npm
- run: npm ci
- run: npm run build
- name: Verify tag matches package.json version
run: |
PKG_VERSION="v$(node -p "require('./package.json').version")"
GIT_TAG="${GITHUB_REF#refs/tags/}"
if [ "$PKG_VERSION" != "$GIT_TAG" ]; then
echo "::error::Tag $GIT_TAG does not match package.json version $PKG_VERSION"
exit 1
fi
- name: Generate changelog
id: changelog
uses: requarks/changelog-action@v1
with:
token: ${{ github.token }}
tag: ${{ github.ref_name }}
writeToFile: false
excludeTypes: build,docs,other,style,ci,test,chore
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
allowUpdates: true
body: ${{ steps.changelog.outputs.changes }}
tag: ${{ github.ref_name }}
- run: npm publish --provenance --access public
fetch-depth: 0- uses: actions/checkout@v4
with:
fetch-depth: 0 # Default is 1 — change to full history
Without
fetch-depth: 0, the action cannot find the previous tag and will fail. This is mandatory.
contents: write Permissionpermissions:
contents: write # Changed from read to write
contents: write is required for creating GitHub Releases. The same permission is needed if you commit CHANGELOG.md back to the repository.
excludeTypes# User-facing changes only (feat, fix, refactor)
excludeTypes: build,docs,other,style,ci,test,chore
# Include all commit types
excludeTypes: ''
# Use default (excludes build, docs, other, style)
# Omit excludeTypes entirely
Choose based on project size and purpose. Small projects may benefit from including all types, while user-facing release notes are cleaner with only feat, fix, and refactor.
If you want to keep a CHANGELOG.md file in the repository alongside GitHub Releases:
- name: Generate changelog
id: changelog
uses: requarks/changelog-action@v1
with:
token: ${{ github.token }}
tag: ${{ github.ref_name }}
writeToFile: true # Auto-generate CHANGELOG.md
excludeTypes: build,docs,other,style,ci,test,chore
- name: Commit CHANGELOG.md
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'docs: update CHANGELOG.md for ${{ github.ref_name }}'
file_pattern: CHANGELOG.md
branch: develop
With
writeToFile: true, new version entries are appended to CHANGELOG.md. Duplicate entries for the same version are automatically prevented.
Example output from changelog-action:
### ✨ Features
- [`a1b2c3d`](https://github.com/owner/repo/commit/a1b2c3d) - Add client-side fallback for PAGES mode *(by @username)*
### 🐛 Bug Fixes
- [`d4e5f6g`](https://github.com/owner/repo/commit/d4e5f6g) - Fix query builder compatibility issue *(by @username)*
### ♻️ Refactoring
- [`h7i8j9k`](https://github.com/owner/repo/commit/h7i8j9k) - Extract fetchTree helper function *(by @username)*
v0.0.0) beforehand.release:) — Can be included with includeInvalidCommits: true, but using standard Conventional Commit types (e.g., chore(release):) is recommended.excludeScopes) to generate separate changelogs per package.