How I develop Meteorjs apps - part 3. Continuous Integration and Delivery of your Meteor “package for everything” project.

This is the last article in a series: “How I develop Meteor apps”. You can jump to the other articles:

In the last article in this series I will present you a step by step tutorial of how to add Continuous Integration and Continuous Delivery processes to your “package for everything” MeteorJS app.

What are Continuous Integration (aka CI) and Continuous Delivery (aka CD) ?

CI and CD combined together create a process in which an external server:

  1. clones your code each time you make a push to the repo
  2. tests the code against automated tests (usually)
  3. deploys your code when tests pass.

As simple as that - let’s do it!

Prerequisites

For continuous integration server I will use Codeship.io. The app will be deployed on digitalocean using Meteor up deploy script.

I assumed the following:

  • your “package for everything” app has tests and those tests pass,
  • your code is hosted either on Github or Bitbucket,
  • you have a Codeship account,
  • you have the basic knowledge of “Meteor up”,
  • you have a digitalocean account,
  • your app uses the latest version of Meteor (1.1.0.2 in the time of writing)

If you meet all of those criteria, move forward to the first step.

Step 1. Run tests locally

First we have to ensure that tests can be run in the terminal. To do this, instead of

Meteor test-packages --driver-package respondly:test-reporter package:name`  

run the following command:

Meteor test-packages --velocity  

(you can add --settings settings.json when your packages depend on it).

When you see in the terminal “TESTS RAN SUCCESSFULLY” and the test runner stopped execution - move forward to the next step.

But if the process is still running:

  • make sure you use the latest version of Meteor
  • check if in all of your packages you defined mike:mocha-package in the latest version (mike:mocha-package@0.5.7 in the time of writing)

Step 2. Setup Codeship for continuous integration

Now it’s time to run tests on continuous integration server for the first time. To do this:

Create a new project

In the first stage Codeship tells you to pick a repository from which the code will be cloned. Pick the right repo and in the next screen set up configuration.

Setup command

Codeship.io doesn’t have MeteorJS preinstalled, so you have to set up Codeship to download it and install before each test run. There are 2 ways of doing this:

  • clone latest Meteor repo from github
  • use MeteorJS install script, but before you run it make sure you change the settings so that it can be run by a “normal user” (sudo not required)

Long story short - execution time of the second approach is shorter, so we will use it in our configuration. Paste the following script to “Setup Commands” section (from this discussion ):

curl -o Meteor_install_script.sh https://install.Meteor.com/  
chmod +x Meteor_install_script.sh  
sed -i "s/type sudo >\/dev\/null 2>&1/\ false /g" Meteor_install_script.sh  
./Meteor_install_script.sh
export PATH=$PATH:~/.Meteor/  

What it does:

  1. downloads MeteorJS install script,
  2. allows for file execution
  3. allows it to run by a “normal” user
  4. installs Meteor
  5. adds Meteor executable to Codeship.io PATH

Test command

And now paste the following:

Meteor test-packages --velocity  

(or with --settings part)

This is the same command we use in step 1. Save the project and after the next push Codeship will run your tests automatically.

Step 3. Run deploy locally

Similarly as before, let’s start with setup process to run locally and then move it to Codeship. In the beginning of this article I mentioned that we will use digitalocean along with Meteor up deployment script.

Let’s start with digitalocean.

Digitalocean

After logging in create your Bucket with the following setup

  • name: pick suitable name,
  • for bucket size - let’s go with default version for 10$
  • region doesn’t matter here - pick the one closest to you
  • image should be latest ubuntu 14.04

Before clicking “save” let’s add 2 SSH keys:

  • key on your dev machine - it should be located in ~/.ssh/id_rsa.pub. When in ~/.ssh there are no keys just create one
  • key from codeship. You can find it “general settings” of your project

And now you can click “save”.

After about 1 minute the bucket will be created - remember its IP address and move to the next step.

Setup Meteor up (aka mup)

Setting Meteor up is quite straightforward:

  1. install package: npm install -g mup
  2. in your project root run mkdir -p .deploy/staging (let’s say this will be your staging environment) and cd to it cd .deploy/staging (we use “.deploy” with “dot” as a name for main configuration folder - this way Meteor won’t compile it as other files on run).
  3. initialize Meteor up configuration: mup init

You can read more details about setting up Meteor up on projects github page.

Meteor up creates 2 files: one with settings.json which will be copied to the server and available under Meteor.settings. Change it according to your project.

The other file is an actual mup configuration. In mup.json change:

  • in servers section set up hostname with IP of your newly created Bucket
  • remove password key, since we won’t use it. That’s also why you have to uncomment "pem": "~/.ssh/id_rsa". - When you run mup on your local machine it will point to your local key, where on codeship - it will point to codeship’s key.
  • change location to "app": "../../" (two folders “above” mup.json)
  • and finally in env section set rooturl to “http://yourbucket_ip”.

Now add the created files to the repo and push it.

Important info: adding mup configuration files to the repo is a bad thing in general, because suddenly all your secret credentials placed in settings.json will be available to all folks who have access to the git repo. I have proposed this way of set up to demonstrate the process on a simple example - feel free to change anyhow you like.

Run mup locally

first set up created bucket - run:

mup setup  

and after it is done deploy your app with the following command:

mup deploy  

If everything went fine you should be seeing your app online under bucket IP address. If not, check logs: mup logs -f

Step 4. Run deploy by Codeship

Let’s go back to your Codeship project. Under “project settings/deployment” click tab: “add new deployment pipeline”. Basically, pipelines are scripts which will be triggered for different branches.

Choose master as a branch name (it means that it will be run whenever you push something to the master branch and tests pass).

On the next screen choose “custom script” (last option) and under the deployment command write:

npm install -g mup  
cd .deploy/staging  
mup deploy  

It’s as simple as that (but please note that before this happens you had to add ssh key to your bitbucket to make it work).
Of course, all kinds of things can go wrong. You can verify each command by debugging the build in Codeship. You can read more about it here

Along with CI

After configuring CI/CD you can also set up Codeship to send notifications to your Slack, Hipchat, whatever. This way you will have an immediate feedback on what happens in the code.

Summary

Continuous Integration and Delivery are a bless when working with startups, where multiple developers work on the same codebase and 10 deploys per day is a standard.

Want more? - subscribe of follow me @wojtek_krysiak and don't miss anything.

#meteor
Wojciech Krysiak
CTO and co-founder of RST-IT. Technology enthusiast with a passion for coding. Wojtek is a charismatic Team Leader, who never allows anyone in the team to lose energy