Setting up a CI server

Continuous integration servers are a great way to make sure that all changes to master are tested before deploying. CI servers are also great for automating the deployment part. CI servers used to be a real pain to configure. Cloud-based CI servers have simplified things so that now there's no reason not to set one up for any project that needs public deployment.

This page describes setting up Travis CI for a React app that is stored on Github and hosted on Firebase.

Prerequisite: A React app on Github

Identify or create a React app that you want Travis to handle. Make a repository for it on Github if one doesn't already exist.

Verify that the React scripts build and test your app by running the following in your app's root directory.

npm test
npm run build

Give Travis access to your Github repositories

You have to tell Travis where to find your repository, and tell Github to give Travis permission to watch the repository and get code from it. Fortunately, this takes just a few button clicks.

Go to Travis and click the button that says "Sign in with Github".

What happens next can depend on whether you've done this before. If you are redirected to Github, Github will ask if you want to give Travis access, and then if you want to install Travis on Github. If you are the owner of the repository, you can grant access. If you are not the owner, the owner will be sent an email asking for permission. You can progress after it is granted.

If you have granted Travis access before, then you will stay on the Travis site. Click on your Github icon on the Travis page to see your repositories, and change which ones Travis should watch. By default, Travis will watch any new repositories, but not "legacy" repositories in place before Travis was granted access.

Tell Travis how to build your app

Once you've done the above, Travis will notice when you change the master branch on your repository. But it won't be able to do anything until you create a .travis.yml file in your repository that says how to build your app.

Note that the file name starts with a period. That's important but easy to miss. It also means that the file is not displayed when you do ls in a Linux or Unix system, such as MacOS. You need to do ls -a.
.travis.yml is a YAML file. YAML ("YAML Ain't a Markup Language") is a very simple language for configuration files.

First, you must tell Travis to use Node to build and test your React app. Travis is a general CI server for many languages. It assumes your app uses Ruby unless you say otherwise. If you get errors about "Gem not found", you forgot to tell Travis you have a React app.

With React, it's also important to tell Travis to use a recent version of Node. Travis assumes Node 0.10. If you get a long list of warnings from Travis, you probably forgot to tell it to use a modern Node.

I recommend you first try the following .travis.yml:

language node_js
  - "node"

This tells Travis to use the current version of Node. That's Node 12 at the time this was written. If you get errors doing that, but not when you build and test locally, replace "node" with the version of Node you have, e.g., "10".

Travis will use npm to build and test your app, unless it sees a yarn.lock file. Your build will probably fail if yarn is used, so be sure to delete any yarn.lock files.

The Travis YAML file needs to be in the same directory as your app's package.json -- neither higher nor lower. If you get errors about make test exited with 2, it's often because Travis couldn't find package.json.

If your app code is in a subdirectory, you need to tell Travis to change to that directory:

language node_js
  - "node"
  - cd subdirectory

Test your Travis configuration

If the owner of the repository is , then the results of the build, and a history of previous builds, can be found at the URL .

Commit your .travis.yml file in Git, then push your changes to master. If everything is properly set up, then in a few minutes Travis should

  • notice master has changed
  • see the YAML file
  • spin up a virtual machine
  • build your app from scratch
  • run the tests, if any
  • send an email on the results

All this will take several minutes or more. That's fine. Except when first testing your CI configuration, you do not wait to see if your build and tests succeed on the CI server. Just build and test locally, commit and push, and go on to your next task. Travis will let you and the team know if your changes broke master.

Tell Travis how to deploy your app

The above is continuous integration. All changes to master are tested to make sure that master is not broken. This is the original motivation for CI servers. But mature software development teams with solid testing practices also do continuous deployment. That means that if changes pass the tests, they are immediately deployed to a development server, or perhaps even production.

Here, we'll assume you are hosting your app on Firebase.

Verify that deployment works:

npm run build
firebase deploy

When this command completes, you should be able to see the current version of your app running on Firebase.

To automate deployment, you need to give Travis a token to authenticate itself with Firebase. In your app directory, call

firebase login:ci

This will send you to Firebase to approve the request and generate a token.

Set the FIREBASE_TOKEN environment variable in Travis, as described on this page.

Now add the commands to install the Firebase CLI, and build and deploy your app, to your .travis.yml file:

language: node_js
- node
  - npm run build
  - npm install -g firebase-tools
  - firebase deploy --token $FIREBASE_TOKEN --non-interactive

Commit, push to master, and verify that Travis successfully builds and deploys your app to Firebase.

Debugging Travis issues

Setting up Travis CI is a snap, compared to how complicated setting up a CI server used to be. Still, there are several moving parts that can get jammed up.

The first thing to do when a build fails or nothing seems to update is to study the build logs. Any line that has a twist-down triangle on the left is a summary that can be opened to reveal more detail. If a step failed, the detail will usually say why. Even if the summary appears to have succeeded, but the details may show a problem that was not recognized as a build failure. Besides warnings and error messages, look for commands being executed that seem unrelated to your app.

I spent two hours on a deployment problem. I thought it was due to bad authentication tokens. Opening the relevant part of the build log revealed it was a missing directory issue.

Make sure you're looking at the current build, not one of the old jobs in the build history.

Check your .travis.yml file carefully against the model versions presented above. Specifically, check that you

© 2019 Chris Riesbeck
Template design by Andreas Viklund