-
Notifications
You must be signed in to change notification settings - Fork 12
Continuous Deployment strategies
At the time of writing this post (08-Nov-19), some steps are manually controlled, like lerna publish
and ember deploy
for example. Can we make use of travis for CI and automate this process?
I've found 2 ways to solve this problem:
A. Fully "automatic"
B. Half & Half
It's really cool to automate everything but there is a thing to solve, "how to tell travis what should be the next semver bump?". Anyway, this workflow can still be useful for staging/dev scenarios where you can publish to an internal registry for example or something like that.
The important bits of .travis.yml
:
language: node_js
node_js:
- "10"
cache:
yarn: true
directories:
- "node_modules"
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s
- export PATH="$HOME/.yarn/bin:$PATH"
before_script:
- yarn run lerna run prepublish
script:
- yarn test
before_deploy:
- git config --global user.email ${GITHUB_EMAIL}
- git config --global user.name ${GITHUB_USER}
- git remote set-url origin "https://${GITHUB_TOKEN}@github.com/YOUR/PROJECT.git" > /dev/null 2>&1
- git checkout release
- echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" >> $HOME/.npmrc 2> /dev/null
deploy:
provider: script
script: "yarn run lerna:publish"
skip_cleanup: true
on:
node: "10"
branch: release
Using this config you can deploy (for our purposes, deploy == release) only when a merge happens to a branch called "release". So as you may figure it out, on a workflow like this you will end up having a parallel release branch. This branch will be used to track our releases.
When you want to trigger a release you should create a PR from master to release. When the PR is approved and it's merged this will signal the condition and travis will execute the deploy part. Finally, when the PR got merged you should create another PR from release back to master to get the changelog changes and version bumps.
Since we are pushing and publising from travis, we will need to pass: a GITHUB_EMAIL
(this can be [email protected]), GITHUB_USER
(Deployment Bot), GITHUB_TOKEN
and finally a NPM_TOKEN
.
The previous strategy has a clear drawback, you can't specify the next semver and it is logical, this is a manual part of the process.
But, we have another option. Lerna from version 3 splitted out the version from the publish. In fact they are now 2 different commands. Having this in mind, we could divide the release process in 2 steps that will be quite close each other. One would involve the version bump, push and tag. The other, the npm publish. We can connect both using travis conditions.
The first part involves versioning, the command (npm script) will look like this:
"lerna:version": "lerna version prerelease --preid beta"
Also, it is very convenient to add the following to the lerna.json file to limit the branch where we want to release:
"command": {
"publish": {
"allowBranch": "master"
}
}
So far, so good. If we run the lerna:version
script we would only need to choose/confirm the version bump and we will end up with a new version and a new tag on github.
For the publish we will use the new tag on master as a travis condition for deploy:
language: node_js
node_js:
- "10"
cache:
yarn: true
directories:
- "node_modules"
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s
- export PATH="$HOME/.yarn/bin:$PATH"
before_script:
- yarn run lerna run prepublish
script:
- yarn test
before_deploy:
- echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" >> $HOME/.npmrc 2> /dev/null
deploy:
provider: script
script: "yarn run lerna:publish"
skip_cleanup: true
on:
node: "10"
tags: true
The relevant parts from the travis setup are the tags: true
condition and the NPM_TOKEN
being set as part of the "local" .npmrc
file. For the conditional, tags: true
means that travis will only deploy iff the TRAVIS_TAG
env var is set and the var will only be set if we are building from a git tag.
Combining the travis condition a github protected branch and the lerna version protection too we can have a quite robust split workflow.
Finally, let's take a look into the travis deploy script, it will look like this:
"lerna:publish": "lerna publish from-git --yes --npm-client yarn --npm-tag beta
Here we are telling lerna to use the version from the current git commit this is a special option very useful for a CI scenario like ours.
Like we said, this is a "2 steps" workflow.
- From
master
you can launch the versioning:yarn run lerna:version
- The automatic step, travis will detect a new tag on master and this will trigger a new deploy. 🚀
We only need a NPM_TOKEN
for travis.