Skip to content
rasmusp.com

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:

RequirementWhy it matters
Git repositoryRelease-it tags and pushes via Git
Follow Conventional CommitsEnables 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:

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:

.release-it.json
      {
  "$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:

.release-it.json
      {
  "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

    

Github Actions

You can automate releases using GitHub Actions, e.g. on merge into main.

.github/workflows/release-it.yml
      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.