Release-it — Automation for versioning and changelog
You've just merged the last feature of the sprint, eager to ship it to your app. Everything looks great, and you are ready to deploy, but now you're stuck manually bumping the version, tagging the commit, pushing to GitHub, and crafting a tidy CHANGELOG.md. It's boring, repetitive, and prone to mistakes. How can we fix that?
Enter Release-it — a CLI that helps automate version bumping, changelog generation, Git tagging, GitHub releases, and more. With a few lines of configuration you can turn those 15-minute "release chores" into a single command (or a CI step) you never think about again.
Setup
Prerequisites
Before starting there some mirror prerequisites:
Requirement | Why it matters |
---|---|
Git repository | Release-it tags and pushes via Git |
Follow Conventional Commits | Enables automatic changelog categorisation |
Node ≥ 16 (LTS recommended) | Required runtime for the CLI |
Installation
Starting a fresh project? First, create a package.json:
npm init # creates package.json
Then, whether it’s a new or existing project, install the required dev dependencies:
npm install -D release-it @release-it/conventional-changelog
For convenience, add a script to package.json:
{
"scripts": {
"release": "release-it"
}
}
Now you can run the command npm run release to start the release process. On the first run, Release-it will be prompted to choose between embedding the configuration in package.json or a .release-it.json file.
This guide assumes the latter for clarity.
Configuration
Release-it's configuration is powerful but flexible. Let’s walk through the basics and some advanced options.
Basic Configuration
Here's a minimal configuration to get started:
{
"$schema": "https://unpkg.com/release-it@19/schema/release-it.json",
"git": {
"commitMessage": "chore: release v${version}"
},
"github": {
"release": false // toggle true to create GitHub releases
},
"npm": {
"publish": false // set true for publishing libraries
}
}
Advanced Configuration Options
Git Configuration
{
"git": {
"commitMessage": "chore: release v${version}",
"tagName": "v${version}",
"tagAnnotation": "Release v${version}",
"push": true,
"requireUpstream": true,
"requireCleanWorkingDir": true,
"requireBranch": "main"
}
}
- commitMessage: Customize the commit message format
- tagName: Define the Git tag format
- tagAnnotation: Add detailed tag annotations
- push: Control whether to push to remote
- requireUpstream: Ensure branch is tracking remote
- requireCleanWorkingDir: Prevent releases with uncommitted changes
- requireBranch: Restrict releases to specific branches
GitHub Configuration
{
"github": {
"release": true,
"releaseName": "Release v${version}",
"releaseNotes": null,
"draft": false,
"prerelease": false,
"tokenRef": "GITHUB_TOKEN"
}
}
- release: Enable/disable GitHub releases
- releaseName: Customize release title
- releaseNotes: Override default release notes
- draft: Create releases as drafts
- prerelease: Mark releases as pre-releases
- tokenRef: Specify GitHub token reference
NPM Configuration
{
"npm": {
"publish": true,
"publishPath": ".",
"access": "public",
"otp": null
}
}
- publish: Enable/disable npm publishing
- publishPath: Specify package location
- access: Control package access level
- otp: Two-factor authentication code
Conventional Changelog Configuration
The @release-it/conventional-changelog plugin helps you maintain a standardized changelog based on your commit messages. Here's how to configure it:
{
"plugins": {
"@release-it/conventional-changelog": {
"infile": "CHANGELOG.md",
"preset": {
"name": "conventionalcommits",
"types": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "docs", "section": "Documentation" },
{ "type": "style", "section": "Styles" },
{ "type": "refactor", "section": "Code Refactoring" },
{ "type": "perf", "section": "Performance Improvements" },
{ "type": "test", "section": "Tests" },
{ "type": "build", "section": "Builds" },
{ "type": "ci", "section": "Continuous Integration" },
{ "type": "chore", "section": "Chores" },
{ "type": "revert", "section": "Reverts" }
]
}
}
}
}
Configuration Options
- infile: Path to your changelog file (default: "CHANGELOG.md")
- preset: Configuration for commit types and their sections
- name: The preset to use (conventionalcommits, angular, etc.)
- types: Array of commit types and their corresponding changelog sections
Commit Types and Sections
The plugin supports all standard Conventional Commits types:
- feat: New features
- fix: Bug fixes
- docs: Documentation changes
- style: Code style changes (formatting, etc.)
- refactor: Code refactoring
- perf: Performance improvements
- test: Adding or modifying tests
- build: Build system or external dependency changes
- ci: CI configuration changes
- chore: Other changes that don't modify src or test files
- revert: Reverts a previous commit
Example Changelog Output
# Changelog
## [1.1.0] - 2024-05-05
### Features
- Add new authentication system
- Implement dark mode
### Bug Fixes
- Fix login form validation
- Resolve navigation issues
### Documentation
- Update API documentation
- Add setup instructions
Hooks: Automate Your Workflow
Hooks are powerful tools that let you run custom scripts at specific points in the release process. They follow the format [prefix]:[plugin]:[hook].
Hook Types
- before: Run before a specific step
- after: Run after a specific step
- plugin: Target specific plugin (git, npm, github)
- hook: The specific lifecycle event
Common Hook Examples
{
"hooks": {
// Pre-release checks
"before:init": [
"npm run lint",
"npm test",
"npm run build"
],
// Version bump notifications
"after:bump": "echo 'Version bumped to ${version}'",
// Post-release tasks
"after:release": [
"echo 'Release ${version} completed'",
"npm run deploy"
],
// Git-specific hooks
"after:git:release": "echo 'Git tag v${version} created'",
// GitHub-specific hooks
"after:github:release": "echo 'GitHub release created'"
}
}
Available Variables in Hooks
You can use these variables in your hook commands:
- ${version}: The new version
- ${latestVersion}: The previous version
- ${changelog}: The generated changelog
- ${name}: Package name
- ${repo.repository}: Repository name
- ${branchName}: Current branch
- ${releaseUrl}: URL to the release
Real-world Hook Examples
{
"hooks": {
// Run tests and build before release
"before:init": [
"npm run test:ci",
"npm run build"
],
// Update documentation after version bump
"after:bump": "npm run docs:update",
// Deploy to staging after release
"after:release": "npm run deploy:staging",
// Notify team on Slack
"after:github:release": "curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"New release ${version} is out!\"}' $SLACK_WEBHOOK"
}
}
Dry run
You can preview the release process without modifying Git:
npx release-it --dry-run
Useful Links
- Release-it — GitHub Repository
- Release-it — Documentation
- Release-it — Node.js Version Support
- @release-it/conventional-changelog Plugin
Github Actions
You can automate releases using GitHub Actions, e.g. on merge into main.
name: Release-it
on:
pull_request:
types: [closed]
branches: [main]
permissions:
contents: write
jobs:
release:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set git identity
run:
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
- run: npm install
- run: npm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Conclusion
Manual releases steal time and invite errors. With Release-it you:
- Write clear Conventional Commits.
- Run one command (or let CI run it for you).
- Ship a perfectly tagged, documented release in seconds.
So the next time you finish that sprint, forget the copy-paste routine and let Release-it do the boring stuff—while you start the next great feature.