Module release
First a little bit about npm dist tags, when you publish a package to NPM, you can optionally
choose a "dist-tag" which basically allows you to install using a short-hand. For example the
default when you run npm publish
is latest
dist tag. Latest is the special tag that allows
you to install without specifying a version: npm install my-module
is equivalent
to npm install my-module@latest
but you can also customise these and create distinct streams.
Generally you can't override "tags" (i.e. versions) but when you publish with a dist-tag you get the latest version tagged with that.
In this experimental set up we have 3 streams: latest
, pr
and next
Travis will build the branch when you pull request, it will also publish a completely new stream
based off of the ID of the pull request (number in the URL). For example, if you opened pull
request no. 4, then once travis had build you could install your module
using: npm install my-module@pr-4
and it would pull down that build.
If you push more commits it will also build these, and running that npm command will get you the latest in that PR. (note: you can also target the commits, see the travis logs for exact details)
When you merge your branch into master that commit will be built and also published. This will be
available on the next
stream. So you can install the tip of the master branch at any time by
running npm install my-module@next
.
This is where it gets a little strange. If you want to bump the version of the whole package, you need to follow a few steps. To make this easier there are 2 scripts that do this automatically. The long and short of it is:
- branch off new release branch from master
- bump version
- create tag
- push to origin
You can run this, with choice of semver bump from the root running: npm run release
and it will
take you through the options.
> fesk-release
=> Checking installed versions...
Node version v8.9.3
NPM version v5.6.0
Lerna version v2.9.0
=> Checking out master, pulling down latest changes.
=> Checking version branch and tag doesn't already exist.
| Current Version: 0.0.8
| Increment: patch
| New version: 0.0.9
? Continue with release? (Y/n)
This release command has quite a lot of options, will document later. The result is the same, you will have pushed a new release branch. It will give you a link to open a Pull Request.
Important note here: When you push a tag, it will get built and published to NPM. The release branch
is not an intent to release, but a release itself. Since the release branch is tagged, you need to
merge using --no-ff
which is not available in GitHubs UI. You can only do this from the command line.
Ideally travis would be setup to automatically do this merge, but for now there's another local npm
command. Locally on the release branch run npm run merge
and it will fast-forward master for the release.
This will keep the tag pointing to the same commit and avoid problems where the tagged commit is not in the
master branch at all.
When you push a tag and its built, it immediately becomes available on the latest
or default stream.
DEPLOYING A LATEST RELEASE v0.0.9
> fesk-release --latest --yes
=> Checking installed versions...
Node version v8.9.4
NPM version v5.6.0
Lerna version v2.9.0
=> Preparing to release new "latest" tag
+ @stephenwf/ntrt-test-1@0.0.8
+ @stephenwf/ntrt-test-2@0.0.8
+ @stephenwf/ntrt-test-3@0.0.8
So anyone who runs: npm install my-module
or npm install my-module@latest
will get this new change.
(You have 1 hour if you want to redact a tagged release to NPM, still a manual step. At any time you can
deprecate a version though, which appears to users using the package)
You can do this for major, minor or patch version bumps. In summary:
- Pull requests are available at:
npm install my-module@pr-{number}
- Master branch latest available at:
npm install my-module@next
- Latest tag available at:
npm install my-module
This all happens automatically. Ideally in the future our pull requests and maybe even the next
would be published
to a private NPM repository, avoid spamming NPM with a CI pipeline, but for now I think it will be pretty convenient!
Example travis file
To set this up in travis, you will first need to install this to your project: npm install @fesk/module-release --dev
and also add in the release and merge scripts to your package.json
:
{
"scripts": {
"release": "fesk-release",
"merge": "fesk-merge"
}
}
Note: merge is optional, but useful for preserving tags on commits when they are merged.
travis.yml
:
language: node_js
cache:
directories:
- node_modules
- "$HOME/.npm"
notifications:
email: false
node_js:
- 8.9.4
script:
- ./node_modules/.bin/lerna bootstrap
- npm test
after_success:
- "./deploy.sh"
deploy.sh
:
#!/usr/bin/env bash
echo "//registry.npmjs.org/:_authToken=${NPM_AUTH}" >> ~/.npmrc
if [[ "$TRAVIS_BRANCH" = "master" ]] && [[ "$TRAVIS_PULL_REQUEST" = "false" ]]; then
if [[ "$TRAVIS_TAG" = "$TRAVIS_BRANCH" ]]; then
echo "SKIPPING BUILDING TAG ON MASTER";
else
echo "DEPLOYING A NEXT RELEASE";
npm run release -- --next --yes
fi
fi
if [[ "${TRAVIS_TAG}" != "" ]]; then
echo "DEPLOYING A LATEST RELEASE $TRAVIS_TAG";
npm run release -- --latest --yes
fi
if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then
echo "DEPLOYING A CANARY, NUMBER $TRAVIS_PULL_REQUEST";
npm run release -- --pull-request=$TRAVIS_PULL_REQUEST --yes
fi