npm package: @fesk/module-release
Description: Module publisher for the Frontend Starter Kit
Latest version: 0.0.3

# 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`:

```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`:

```yaml
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`:

```bash
#!/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
```