Automated build with Travis CI


Advanced Expert

Goal of this post is to guide through how to set up Travis CI workflow tool to run your code builds. I have use this to set up Gatsby.js build to Firebase hosting when ever I update content in WordPress, so this is what we will do in our example.

Account

First we need a Travis account. If you have a non-commercial project with public github repo you can use free Travis.org. For commercial projects with closed Github repos you should use paid Travis.com. Here are the steps to create the account in both cases.

  • Sign up with your Github account and give Travis access to your repositories
  • Activate Travis for repository you want to use

Changes to package.json

Since Travis CI is first and foremost meant for testing it tries to run tests first and won’t let you do the build if it fails. So first if we don’t have tests we need to do a little change in our package.json file. Gatsby ships with test script that throws an error and complains you don’t have any tests. To make this pass in Travis we need to make our test script look like this (so it gives warning, not error). Also add deploy script with firebase deploy to your scripts.

  "scripts": {
    "build": "gatsby build",
    "develop": "gatsby develop",
    "start": "npm run develop",
    "format": "prettier --write \"src/**/*.js\"",
    "build:prod": "yarn build -- --prefix-links",
    "deploy": "yarn build:prod && firebase deploy",
    "test": "echo \"Warning: no test specified\" && exit 0"
  },

Add .travis.yml file

Then the most important part. Add your .travis.yml file. This is allmost all your Travis configuration. In Travis UI you basicly just add your Firebase auth token (we will do this next), which we are referring to in our file. Add this to the root of your repo.

Here is a simple boilerplate that works. You can add more options and scripts according to your needs. Most of the stuff build environment configs but part that is interesting is at the end. You can specify before build scripts (in our case we install firebase tools and gatsby), actual test and build scripts and after succesful build after scripts (our case we will deploy our build to firebase.

language: node_js
node_js:
  - "8"
cache: yarn
addons:
  apt:
    packages:
      - g++-4.8
    sources:
      - ubuntu-toolchain-r-test
env:
  CXX=g++-4.8
branches:
  only:
    - master
before_script:
  - "yarn global add firebase-tools"
  - "yarn global add gatsby"
script:
  - "yarn test"
  - "yarn build:prod"
after_success:
  - "firebase deploy --token=${FIREBASE_TOKEN}"

Create Firebase token and do a test commit

To make a Firebase token you have to have Firebase tools installed. Creating a token is simple. Just run this scripts. It forces you to log in to your Firebase account and then gives you a token. Then you go to Travis web UI and put in as a env variable with the name FIREBASE_TOKEN.

firebase login:ci

Then just do a commit and push it to your master branch and check in Travis CI web interface is the build starting.

Run build when you edit/add content in WordPress

WordPress is full of webhooks so this part is not difficult. Just add this simple script or something similar to you functions.php and edit it to point to your project. This hooks to save_post hook so every time any post is saved this will run. First we get our post type. Then we check is this one of the post types we want to launch our request. If not we will kill the script there. Then we do our post request. I suggest using WP built in wp_remote_post function everytime you need to send external http request in WordPress, since it’s makes your code easy to read, edit and understand.

Note that in our http request url has one funny detail. Between repository owner and repository name there needs to be %2F instead of /. Next chapter will tell how to get Travis token in code.

function jst_save_posts( $post_id, $post, $update ) {

    $post_type = get_post_type($post_id);

    // If saved post isn't in a post type 'post', don't do anything
    // CHANGE THIS TO WHATEVER POST TYPE YOU WANT TO BE EFFECTED
    if ( "post" != $post_type ) return;

      // POST REQUEST
      $response = wp_remote_post( 'https://api.travis-ci.com/repo/yourgithubhandle%2Fyourrepositoryname/requests', array(
      'method' => 'POST',
      'timeout' => 45,
      'httpversion' => '1.0',
      'blocking' => true,
      'headers' => array(
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
        'Travis-API-Version' => 3,
        'Authorization' => 'token YOURTOKENCOMESHERE',
      ),
      'body' => json_encode(array( 'request' => array(
        'branch' => 'master'
      ))
        ))
    );

    if ( is_wp_error( $response ) ) {
      $error_message = $response->get_error_message();
      echo "Something went wrong: $error_message";
    } else {
      return;
    }

  }
  add_action( 'save_post', 'jst_save_posts', 10, 3 );

 

Get Travis token

As you noticed reading the code you will need Travis access token to send request. You will get it like this. Put –com or –org depending are you using open source .org or commercial .com version. Remember you need to have Travis CLI tools installed.

travis login --com
travis token --com

That’s it. Then just test everything works. I hope this makes it easier to do for you than it was for me when I did it first time a while ago, since Travis docs aren’t so awesome.