You've built an awesome JavaScript library and can't wait to share it with the world. But how do you package and release your library, manage versioning, and maintain a tidy, structured changelog?
Doing these tasks by hand can quickly become a hassle. If you're open to receiving contributions from others, it can be an even bigger headache. In this post we'll cover how to use changesets to automate all of these steps.
Setting up changesets
Changesets is a tool to manage versioning and changelogs in an automated way. It works by keeping a markdown file per change, conveniently called a "changeset". This file is used to track the type of change together with a description.
To install changesets, run the following command in your project root:
npm install --save-dev @changesets/cli && npx changeset init
Running this command will generate a .changeset
folder. This folder contains a README.md
with some general info and a config.json
file to customize the tool. All "changesets" will also be stored in this folder.
Versioning
Now that changesets is set up you can start making improvements to your project. Once you're ready to open a PR and merge your changes, it is time to add a "changeset".
Changesets follow semantic versioning conventions. In a nutshell, this indicates that the version number follows the fixed format of major.minor.patch
. A patch is a backwards-compatible bugfix, a minor is a feature that is backwards compatible, and a major is for any change that isn't backwards compatible.
To create a "changeset", simply run:
npx changeset
It will first ask to choose the type of version change (patch, minor, or major) followed by a description of the change that's made. This description is what will end up in the changelog when a release is done. After running this command a new markdown file will be created in the .changeset
folder. Congratulations, you've made your first "changeset"!
To remind contributors (and yourself!) to add this changeset to PRs, install the Changeset bot from the GitHub Marketplace.
Release action on GitHub
You've now merged a couple of great new features and it's time for a release of your package! While changesets offers commands to do this process manually, let's go all out and automate this using GitHub actions. This will save time, and perhaps more importantly, reduce potential manual errors.
Create a file .github/workflows/release.yml
with the following content:
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Setup Node.js 20.x
uses: actions/setup-node@v3
with:
node-version: 20.x
- name: Install Dependencies
run: npm install
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
publish: npx changeset publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
The action needs access to your NPM token in order to be able to do releases. Add this secret in your repository's settings located at Settings > Secrets and variables > Actions
using the name NPM_TOKEN
. If you do not yet have an NPM token, create one on npmjs.com. Make sure the token supports automation as it will be used to run in CI.
The newly added GitHub action will run every time a commit is made on the main branch. If the commit has a "changeset" it will open the release PR. (or update, if there is already one open) This PR gives an overview of all changes which are currently on the main branch but not yet in the latest release. The PR will include three changes:
- The removal of all "changeset" markdown files
- The package version is bumped accordingly
- A changelog entry is added for every "changeset"
The next package version is determined by looking at all "changeset" entries. When two "changesets" are included which are of the type minor, the minor release will only be bumped once. Likewise, when a mix of version types are included, the most significant version is bumped. For example: if both a bugfix and minor are included, only the minor version will be bumped. The days of manually calculating the correct package version are gone!
Finally, when you're ready to go, the release PR can be merged and the GitHub Action will automatically do a publish of the package to NPM.
Bonus: upgrade your changelog game with GitHub links
By default the changelog just combines all changeset descriptions. With custom formatters, it can be extended to do more.
The @changesets/changelog-github
package formats the changelog to include links to the merged PRs as well as a reference to the GitHub user who submitted this change. This is great to give proper credit to contributors as well as easily finding back changes that have been made. It can be installed with the following command:
npm install --save-dev @changesets/changelog-github
Next, register it as the changelog formatter in your .changeset/config.json
.
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"changelog": ["@changesets/changelog-github", {
"repo": "your-org/your-repo"
}],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
Upon merging the release PR, the changelog will now include links to PRs as well as the authors.
Conclusion
Changesets is a great tool to automate versioning and changelogs for JavaScript packages. By streamlining the release process, it not only saves time but also reduces the potential for errors.