Changesets
Last modified on Tue 28 Jan 2025

Changesets is a lightweight tool that helps you manage versions and generate changelogs for packages in a monorepo (or single-package repository). By adding a small file describing each change, Changesets can automatically bump versions, publish packages, and create release notes with minimal friction.

Why Use Changesets?

  1. Immediate Documentation: Document your changes while opening a PR instead of waiting for the final release. This ensures you never forget important details.
  2. Clear Separation of Concerns: Changesets decouple the intent to change (patch, minor, major) from the act of publishing. Your changelogs and version bumps become transparent to the entire team.
  3. Easy Collaboration & Review: Each pull request can include a changeset file that explicitly states how the package version should be updated and why. This fosters more meaningful code reviews.
  4. Automated Versioning: When merged, changesets can automatically handle version bumps, changelog generation, and publishing. This saves time and reduces human error.
  5. Monorepo Ready: Designed for multi-package repositories, Changesets resolve inter-package dependencies, ensuring consistent and reliable versioning across the codebase.

For more info, see the official Changesets documentation.

Getting started

Install and initialize

Install the Changesets CLI in your repository:

pnpm install -D -E @changesets/cli

Then, initialize Changesets:

pnpm changeset init

This creates a hidden folder, .changeset/, with a base configuration file. You’re now ready to track changes in your repo.

Adding a Changeset to every Pull Request

Whenever you open a Pull Request, add a changeset to describe how the changes affect the package(s).

  1. Creating a changeset

After committing your code changes, run:

pnpm changeset

This interactive prompt asks:

  1. Commiting the changeset

Once you select the affected packages, version bump type and write down summary of changes, a .md file is created in the .changeset/ folder (the file name is automatically generated, e.g. strange-bees-visit.md):

---
"@infinum/some-package": minor
---

Introduce a new method `doSomethingAwesome` and fix a small bug in the `init` function.

You should commit the .changeset file:

git add .
git commit -m "chore: add changeset for [feature or fix]"

And push your branch - this changeset becomes part of the PR for reviewers to see.

Note: You don’t have to create a dedicated commit for your changeset. Feel free to include the changeset file in the same commit as your code changes. The key point is that the changeset exists for the release automation to reference, regardless of how it’s committed.

Day-to-day example

1. Pull Latest

git pull origin master

2. Create or Switch to a Feature Branch

git checkout -b feat/improve-logging

3. Make Your Code Changes

(Fix a bug, add a feature, etc.)

4. Run pnpm changeset to create your changeset.

5. Commit and Push

git add .
git commit -m "feat(logging): improve error logging format"
git push -u origin feat/improve-logging

6. Open a PR

GitHub will show the changes, including the new .md in .changeset/.

7. Review & Merge

Once approved and merged, the CI pipeline will handle version bumps and publishing automatically.

Continuous Integration Setup

Although changesets can function without continuous integration (CI), it's recommended to use it with a CI system to automate versioning and publishing. You can utilize the Github Action provided by the changesets team.

To use the action, create a .github/workflows/release.yml file. Follow the instructions under the With Publishing section in the documentation, with minor adjustments. This flow updates the versions of changed packages and publishes them to npm registry.

name: Release

on:
  push:
    branches:
      # Make sure to check the branch name here; usual values are `main` and `master`
      - master

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4

      # Corepack makes sure to use correct Node.js version for your project, it requires having "engines" specified in package.json file
      # Read more about Corepack and advanced dependencies caching at: https://infinum.com/handbook/frontend/node/managing-node-npm-versions
      - name: 🗃️ Enable corepack
        run: corepack enable
        shell: bash

      - name: Setup Node.js
        uses: actions/setup-node@v4

      - name: Install Dependencies
        run: pnpm install --prod --frozen-lockfile

      - name: Create Release Pull Request or Publish to npm registry
        id: changesets
        uses: changesets/action@v1
        with:
          publish: pnpm ci:publish
          # if your repository is using conventional commits, you should use the following option (the message can be customized)
          # commit: 'ci: version packages'
        env:
          # GITHUB_TOKEN is required for creating a pull request and will be provided by the Github Action automatically
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # NPM_TOKEN is required for publishing to registry and needs to be provided manually
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      # This step will push tags to the repository after the packages are published and will create a new release on Github
      - name: Push git tag after publish
        if: steps.changesets.outputs.published == 'true'
        run: git push --follow-tags

Before using the action, ensure the following checklist is complete:

GitHub Actions Gotchas

If you actually want to deploy applications with changesets, not just publish new packages to NPM registry, there are 2 gotchas:

But those issue can be tackled:

Example release published trigger:

on:
  release:
    types: [published]

It has some drawbacks — either your own user will be creating all commits, pull requests, tags, and releases needed for deployment, or you'll need to create a dedicated user for that. Some organizations may need to pay for an additional seat, but it's usually not a big deal.

Creating Fine-grained Personal Access Token

Required repository permissions:

⚠️ Warning! If possible, create a dedicated user for that, and it should have access only to this single repository. Alternatively, create this token on an organization level and limit repository access as needed.

After you’ve created the Fine-grained PAT, you have to add it to your repository secrets. In the examples below, it’s named CHANGESETS_GITHUB_PAT.

Updated Release workflow

Example .github/workflows/release.yml:

name: 📢 Release

on:
  push:
    branches:
      - main

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
  release:
    name: 📢 Release
    runs-on: ubuntu-22.04
    steps:
      - name: 📥 Checkout Repository
        uses: actions/checkout@v4
        with:
          token: '${{ secrets.CHANGESETS_GITHUB_PAT }}'

      - name: 💻 Node setup
        uses: ./.github/actions/node-setup

      - name: 🧑‍💻 Configure Git User
        run: |
          git config --global user.name "Bot Kamil"
          git config --global user.email "kamil@infinum.com"

      - name: 🏷️ Create Release Pull Request
        uses: changesets/action@v1
        with:
          publish: pnpm changeset tag
          setupGitUser: false
        env:
          GITHUB_TOKEN: ${{ secrets.CHANGESETS_GITHUB_PAT }}
          HUSKY: 0

Changeset Bot

You can install Changeset Bot to get additional automated PR comments. Once installed, if a PR lacks a changeset, the bot will prompt you to add one. This is highly recommended for teams to maintain consistent usage.

Pre-Releases (Beta, Alpha, RC)

Pre-releases allow you to publish “unstable” versions (e.g., 1.2.0-beta.1) for testing before a final release. See the official docs for details.

⚠️ Warning! Prereleases are very complicated! Using them requires a thorough understanding of all parts of npm publishes. Mistakes can lead to repository and publish states that are very hard to fix.

Typical workflow:

  1. Enter Pre-Release Mode
   pnpm changeset pre <tag>

Usually <tag> is beta, but you can use alpha, rc, next, etc.

  1. Version & Commit
   pnpm changeset version
   git add .
   git commit -m "chore: release beta"
  1. Publish the Pre-Release
   pnpm changeset publish

⚠️ Important! Use changeset publish instead of pnpm publish to respect pre-release mode.

  1. Push Tags
   git push --follow-tags

You can also manually create a GitHub release if desired.

  1. Exit Pre-Release Mode
   pnpm changeset exit pre
   git add .
   git commit -m "chore: exit pre-release mode"

After this, the packages return to normal versioning.

See it in action

Changesets are already implemented in a few repositories. Check them out to see how they work:

Resources