npm-based release workflow
Releasing a package to the npm registry can be error prone. It involves git tagging, to update a CHANGELOG
file, to compile assets, to version bump etc.
Plus, it can happen multiple times a week and the process must be shared with all the project collaborators.
We will explore how to proceed, by relying solely on the npm
command.
§tl;dr
Part of package publishing involves a release process. It goes beyond version bump and can be automated via npm
lifecycle scripts.
§npm
scripts
As a reminder, the npm
command can be leveraged through the scripts
field of the package.json
file.
1 |
|
This way, executing npm run lint
will execute eslint to against our src
folder. No need for a grunt or gulp plugin.
Remember: npm run
expands the [scope of $PATH
](https://en.wikipedia.org/wiki/PATH_(variable) by prepending $PWD/node_modules/.bin
to it. Exactly like PATH="./node_modules/.bin:$PATH" npm run lint
would do. This way you can run any executables provided by local dependencies.
Documentation is available under the run-script
section of the npm
cli. Also, consider reading my previous post about self contained Node.js scripts for a more in depth coverage of this topic.
§npm version {major,minor,patch}
npm@1.1.0
introduced the version auto-increment from the command line. Further documentation improvements made this feature more visible and more explicit.
Considering our current package version is 1.0.0
, the npm version {something}
feature acts as following:
npm version major
→2.0.0
(creates git tagv2.0.0
);npm version minor
→1.1.0
(creates git tagv1.1.0
);npm version patch
→1.0.1
(creates git tagv1.0.1
).
The one liner updates the version
field in the package.json
file, runs git tag
and git commit
for us.
§npm version
hooks
The npm
command introduced the preversion
and postversion
scripts a while ago too. They are executed as follows:
preversion
: performs operations before altering the version number;version
: performs operations after having altered the version number and before the git commit;postversion
: performs operations after the git commit.
Artefacts can be added to the npm version
git commit since npm@2.13.0
– mid-July 2015. This is what makes the workflow handy and streamlined.
§npm release process example
We will use a CHANGELOG
generator to illustrate the previous statement: github-changes. We want the changelog to be in sync with the new version number and to be committed prior to the npm version
change.
1 |
|
The above example will execute the following after we type npm version patch
:
- preversion: run tests;
- version: npm computes a new package version, here
1.0.1
; - version: we generate a
CHANGELOG.md
file based on merged GitHub pull requests, with$npm_package_version
environment variable equalling to1.0.1
; - version: we stage the altered
CHANGELOG.md
; - version: npm creates a commit labelled
1.0.1
; - version: npm tags the commit as
v1.0.1
; - postversion: N/A.
§npm version from-git
I stumbled on two alternatives while researching this article via git blame:
npm version <semver>
;npm version from-git
.
The last one is particularly interesting as it reverses the previous workflow and gives back control to git as a primary publishing tool.
Whereas npm version {major,minor,patch}
would compute the version for you, npm version from-git
will read the version from the git history.
The following code block illustrates how an automated release would happen with the Travis CI npm deployer:
1 |
|
It will:
- deploy only on a new git tag push;
- trigger
npm version
(up to you to configure the variouspreversion
,version
andpostversion
scripts); - publish the new package to the npm registry.
§Conclusion
The npm
command became a powerful release tool since summer 2015, all thanks to a simple lifecycle change.
Wether you choose to use one of the approach or not is up to you. I have a personal preference for npm version {major,minor,patch}
but I kind of like the idea of the CI doing all the work with npm version from-git
on a new git tag rather than having to rely on my machine setup. Or anybody machine setup.