Whether you have an open source project or work in a private company on a project that other people use in their projects, you probably need to communicate the changes you make to your project, so that others can understand what changed and know if there’re any breaking changes. Some reasons you might want to automate your releases are to:
What if every pull request or commit you made to your release branch would automatically generate you a changelog, figure out the required version bump if any, bump the version for you as well as release your library automatically?
Meet semantic-release. Before we set things up there are two requirements for using semantic-release: “Semantic Versioning” and “Conventional Commits”.
Semantic versioning provides a way to have meaningful version numbers that represent that development of your project.
Given a version number MAJOR.MINOR.PATCH, increment the:
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
Conventional commits are a specification for adding human and machine readable meaning to commit messages
If you’re not familiar with conventional commits take a look at conventional commits or Angular commit style. Basically your commit messages should start with one of the following.
Now to the actual setup:
1. First you need to install semantic-release and the plugins you intend to use based on your configuration, you can see a list of all the available plugins here.
npm i -D semantic-release @semantic-release/
2. Next, follow the documentation here to configure semantic release based on your own needs. My personal configuration looks as follows:
// package.json
"release": "plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
// if you dont want to publish on npm registry, you can set npmPublish to false ["@semantic-release/npm",],
"@semantic-release/changelog",
"@semantic-release/git"
],
"branch": "master"
>
3. You should now be able to automatically create a release by running npx semantic-release from your Continuous Integration system or even manually with the --no-ci flag.
All you need is to set a GH_TOKEN environment variable and you’re good to go.
You can use one of the following CI recipes, in my case I’m using a private bitbucket repository and pipelines as a CI along with a private npm registry where I want to publish my library to, so we need to do some extra work.
# This is a sample build configuration for JavaScript.
# Check our guides at https://confluence.atlassian.com/x/14UWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: node:latestpipelines:
default:
- step:
caches:
- node
script: # Modify the commands below to build your repository.
# Generates a .npmrc file configured for installing private modules:
#
# NPM_REGISTRY_URL: the full URL of your private registry
# defaults to registry.npmjs.org.
# NPM_TOKEN: secret token for installing private modules. This
# this token can be found in your .npmrc, after logging in.
- printf "//`node -p \"require('url').parse(process.env.NPM_REGISTRY_URL || 'https://registry.npmjs.org').host\"`/:_authToken=$\nregistry=$\n" >> ~/.npmrc
- npm install
- npm test
- npx semantic-release
If you set everything up correctly, now every commit that will land in the master branch will trigger a release and execute the configured plugins. When merging feature pull requests you can use the Squash merge strategy which will squash an entire pull request of multiple commits into a single commit where you can even change the commit message to a conventional commit style one.
Make a conventional commit style commit message, merge it to the master branch and watch the magic happen.
A new pipeline was triggered and marked as green, semantic-release pushed a new commit generating the CHANGELOG.md file based on the previous commits and a new git tag was created with the semantically correct version and the package was published to my private npm registry. Pretty awesome, isn’t it?