The goal is simple. We want to build a library without having to manually:
- Update the version
- Update the changelog
- Create a new release
- Publish to NPM
Enter Changesets. This handy package solves all of our problems in a very elegant way.
Just tell me how it works, I’m in a rush
OK, here’s how it works in a CI environment, like GitHub Actions.
- If your changes should update the package version, you have to include a small markdown file (changeset). No worries about the format, it’s auto-generated by the Changeset CLI. Just run
npx/yarn changeset
, follow the prompt and you’re good. - Push the changes or merge the PR - essentially just get the updates to the base branch.
- A GitHub action will check for any number of these specific markdown files, calculate the final semver and finally open a PR with the proposed version & the generated changelog. Here’s an example from the emotion repository. You read that right. If Alice made a patch change and Bob a minor & a patch one, the final version will be just a minor bump.
- When you’re ready, merging this PR will add the changelog and will trigger another GitHub action that will publish the package in the background.
Installation & configuration
For simplicity's sake, I will use npm
. Replace npx install
with yarn add
& npx
with yarn
depending on your favorite package manager.
Let’s start by adding the CLI package that helps us with the version bumping, and another one to enrich our changelog with more metadata.
Initialize the configuration..
and you will be greeted by the following message:
All good. If you navigate inside .changeset/
, you'll find the configuration file
I would suggest updating only this rule for now, which will include the PR & author links next to each commit entry.
If you’re into tweaking it, here you can find detailed explanations for all the rules. Finally, let’s update the npm scripts, and let Changeset take over the release.
Setting up Workflows
Before we proceed we need two tokens:
- A GitHub token with
repo
,write:packages
permissions - An NPM token with write permission
After you obtain them, make sure to add them under GitHub Secrets, so that GitHub Actions can access them.
Let’s create a release.yml
under .github/workflows/
Code taken from changesets/action
This action will create (or update) a PR every time a new changeset is added to the main branch. It will calculate the final version for the next release and prepare the changelog. When the said PR is merged, these changes will be pushed to the main branch while triggering a background job to push the package to NPM. A couple of moments later you might notice that there is a new package version if you’re using the GitHub registry. That's it!
You might also want to add the changeset-bot that will notify you in PRs if there are any changesets. I find this very useful as I’m introducing new components in a design-system I’m working on, and keep forgetting to add changelog entries.
Adding a changeset
Enough of the configuration, let’s do some work, and call npx changeset
to version the changes. Remember, not every commit or feature needs a changeset. Updating docs or improving the test suite doesn’t justify creating a new release for your end-users.
Anyway back to the terminal, let’s pick our change type..
Fill with the appropriate summary for the changelog..
And call it a day. Under .changeset/
you will notice a new markdown file (its name is randomly generated), with the change-type and summary.
Push the file along with the rest of the changes, and let the GitHub actions do the heavy-lifting for you. As for the markdown file, it will be deleted by our GitHub action when the entry that's referencing is added to the changelog.
Final thoughts
Changeset is godsend. Recently I had to set up a library and getting versioning/automatic publishing out of the way early was very high on my list. Thanks to Changesets the bulk of the work is invisible to me, and I only have to make the decision when to version my changes.
Previously I was using Semantic release, but I prefer keeping my commit format separate from the versioning process.
Many great libraries like MobX, XState & Formik are using it, so feel free to include it in your projects.
Resources