In an ideal world, the source code of an npm library is in sync with the versions published to the npm registry.
The problem is that the latest package versions published to npm are lacking behind their code. This results in
- Frustrated contributors, whose pull requests got merged and now wait to use the new version that includes their fixes or features
- Confused users that run into a bug that is marked as resolved on GitHub
- Stressed maintainers that are pressured by comments such as "When will this fix be released?" on closed issues and pull requests.
The solution: automation. Enter semantic-release
In a nutshell, semantic-release
relies on commit message conventions to calculate and publish a new version of your package. By default, the 3 conventions are
-
fix: ...
prefix in commit subject: triggers a fix release version, e.g.1.2.3
→1.2.4
-
feat: ...
prefix in commit subject: triggers a feature version, e.g.1.2.3
→1.3.0
-
BREAKING CHANGE:
in commit body: triggers breaking version release, e.g.1.2.3
→2.0.0
That is all you need to learn.
Based on these conventions, new versions are continuously published to npm. Your code on GitHub and published versions on npm will never be out of sync again.
But semantic-release does much more than this:
- It creates GitHub releases to mirror the versions published to npm and adds changelogs based on above conventions and adds them to the GitHub releases.
- It notifies contributors with comments in pull requests and resolved issues that a new version has been released
- It lets you control in a single place who can both merge changes into the
master
branch and publish new versions to npm.
Setup using GitHub Actions
semantic-release
supports a variety of CI providers, git hosts and package registries. For this example, I'll use GitHub Actions to publish to npm.
Install semantic-release
npm install --save-dev semantic-release
If this is an existing project, make sure to create a git tag that matches the last version in the npm registiry, using a v
prefix. For example, if the last version published to npm is 2.0.4
, create a v2.0.4
tag and push it to your repository.
git tag v2.0.4
git push --tags
No need to create a tag for new packages that have not yet been published.
Next, replace the version in your package.json
file with "0.0.0-development". The version will be updated automatically by semantic-release. You no longer need to worry about it.
Next, create an npm token for your account at https://www.npmjs.com/settings/[YOUR USERNAME]/tokens
with the read and publish
setting. Copy that token and store it in your repository's secrets using the name NPM_TOKEN
.
Finally, create a .github/workflows/release.yml
file to run semantic-release each time a change is pushed to your repository's master
branch.
name: Release
on:
push:
branches:
- master
jobs:
release:
name: release
runs-on: ubuntu-latest
steps:
# check out repository code and setup node
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: "12.x"
# install dependencies and run semantic-release
- run: npm ci
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
That's it. Next time you merge a pull request with commit messages following the conventions mentioned above, semantic-release will create the npm and GitHub releases as well as comments on the pull request and linked issues.
Closing words
You can see semantic-release
in action all over my projects on GitHub. I usually make multiple releases each work day. I don't even think about it any longer. It frees up my time and thoughts to focus on the code instead of the chores around it.
And lastly, a tip: automating releases goes hand-in-hand with automating dependency updates. Services such as Greenkeeper even follow the required commit conventions when they send their pull requests. Merging the PRs is all it takes to release a new version. I highly recommend to use them both!
Top comments (2)
One of the best articles I read in the last few days!!!
Thanks Matei for the kind words, it means a lot :) Let me know if there is anything else you'd be interested in learning that I know a thing or two about. I'm still figuring out this writing thing