I talked about this at the Sydney Meteor meetup. The slides for the talk are available here.
I have been using an amazing tool called Meteor Up to deploy my app to a virtual server. But as the app grew, the deployment took longer and became more bandwidth-consuming.
That meant that I couldn’t deploy if I didn’t have a decent Internet connection. This is a problem because I usually work in places with not-so-fast Internet speed (cafe, library, etc.).
So I set up a continuous delivery with TravisCI. This way, I can simply push my code to the GitHub repository, and TravisCI will deploy it using Meteor Up as long as my tests pass.
In this article I would like to share how I set it up. You can find a demo app at GitHub with a step-by-step instruction. Also, I did a presentation on this topic at Meteor Sydney, and the slides can be viewed here.
I am using Mocha and Velocity to run my tests.
Build Meteor app with TravisCI
Before setting up a continuous delivery, we need to tell TravisCI to build our app. This is quite simply done by enabling the app on TravisCI, and adding
.travis.yml to our repo.
sudo: required language: node_js node_js: - '0.12' before_install: - curl https://install.meteor.com/ | sh services: mongodb script: - meteor --test --release velocity:[email protected]_3
before_install, we are installing meteor. And in
services, we are specifying mongodb as our test database. In
script, we are specifying the script to run our test as per the instruction from Velocity.
You need to add console-reporter in you app because CIs use exit status of the test command to determine if the build passed.
This works, but what if you want to specify
--settings option, perhaps with your
You can encrypt
settings.json with TravisCI, and add
--settings option to the test script in
.travis.yml. Do not check the raw
settings.json into your source control! We will take a further look at this below.
Setup deployment on successful builds
We will tell TravisCI to deploy the app using Meteor Up. We do this in
after_success in our
.travis.yml (See build lifecycle in the official doc for more info about what
But we have a problem: Meteor Up needs to use
settings.json, and perhaps our pem file for server authentication.
We want to encrypt them rather than committing them. But doing so is not simple because encrypting only works with one file.
In the offical doc, TravisCI suggests an alternative way of encrypting multiple files. Let us try that way.
We can compress our files into a
.tar file, and encrypt that file. When the build runs, we will need to decrypt, and decompress the file to get
settings.json, and pem file back.
Let’s compress those files into
tar cvf secrets.tar mup.json settings.json private_key
And ecrypt it:
travis encrypt-file secrets.tar --add
--add flag simply adds the decryption process to
.travis.yml so you don’t have to do it manually.
The above command creates
secrets.tar.enc. You need to commit this into your source control.
We need to tell TravisCI to decompress
secrets.tar.enc once decrypted. Also, let’s install
mup before the test runs.
Having done those, our
before_install script in
.travis.yml should look like this:
before_install: - curl https://install.meteor.com/ | sh - npm install -g mup # Add this line to install mup - openssl ... in secrets.tar.enc -out secrets.tar -d - tar xvf secrets.tar # Add this line to decompress secrets.tar
after_success and run
after_success: - mup deploy
We are done here. But an improvement can be made. Obviously, we would not want to deploy all branches. Let us customize branches for deployment.
Only deploy for certain branches
Typically, we want to deploy only certain branches to our production. We wouldn’t want to release the code in a feature branch into the wild.
While TravisCI lets you specify branch under
deploy key in
.travis.yml, it does not allow us to do that for
My solution is to use
TRAVIS_BRANCH environment variable provided by TravisCI to see the current branch and conditionally execute
mup deploy. Here is a simple script I wrote, also hosted on GitHub.
#!/bin/bash echo "On branch '$TRAVIS_BRANCH'." if [ "$TRAVIS_BRANCH" == "prod" ]; then echo "Triggering Mup deployment..." mup deploy else echo "Not deploying. Use 'prod' branch to deploy." fi
Make an executable
.sh file in your app like the above, and simply execute it in
To use the above script, you can simply add the following to your
.travis.yml and curl the script straight from GitHub:
after_success: - curl -L http://git.io/vqbln | sh
There are some things to note:
We are assuming our
mup.json, and the pem file are in our app root directory. Configure
mup.jsonto use the correct path.
Also, if any of those files change, you need to make a new
secret.tar, encrypt it to overwrite the old
Now you can just push to a particular branch to deploy your app, rather than running
mup deploy locally and waiting for the result.
As mentioned, you can find the demo app with instructions on GitHub. Have fun!