DEV Community

Montana Mendy for Travis CI

Posted on

The Cookbook: Build Matrix

Alt Text

A build matrix in Travis is made up by several multiple jobs that run in parallel. This can be useful in many cases, but the two primary reasons we see people use matricies is for reducing the overall build execution time and running tests against different versions of runtimes or dependencies to get the best version of the build. Let's learn about Build Matricies in Travis CI.

Build Matrix and setting up the .travis.yml

As you know by now, you need to tell Travis which language environment to select for your project. You can do so using the language key option, in this Cookbook we'll be using PHP. You can specify which PHP versions will the tests be executed. Not introducing patch versions tells Travis to use the latest available, which is sometimes referred to edge, or if it's the stable version, you guessed it, it's called stable. So let's start building out our .travis.yml:

language: php

php:
  - 5.3.3
  - 5.4
  - 5.5
  - 5.6
  - hhvm
Enter fullscreen mode Exit fullscreen mode

Env Vars

Let's tell Travis to do multiple runs/builds with different sets of env var values. To do so, add an env key. Each segment is understood as a different environment and tests are run separately as such. We are going to use PHP_SEGMENT_TEST later in the file to run tester with the argument of -p and hhvm option in HHVM environment, so in your .travis.yml file, add the env segment:

env:
  - PHP_SEGMENT_TESTRUN="php-cgi"
  - PHP_SEGMENT_TEST="hhvm"
Enter fullscreen mode Exit fullscreen mode

Now simple math would have it, the combination of five PHP versions and the two env vars generates a total of 10 runs.

Dependency installation using Composer

You'll obviously have an install segment in your .travis.yml. Each sub-segment means one single command. Composer installs your dev dependencies by default. You should use --no-interaction so Composer doesn't ask questions Travis can't answer, and can continue the build.

You'll want the latest build, so in you .travis.yml make sure you run the update flag at before_install, so it would look like:

before_install:
  - composer self-update

install:
  - composer install --no-interaction 
Enter fullscreen mode Exit fullscreen mode

The Build Matrix

Depending on the configuration above (different segments and sub segments), a build matrix wil be generated. The matrix contains all combinations the environment settings. A single combination is called a job and is run separately. You can modify the matrix in matrix section.

If you want to exclude a job, use the exclude key. In our case, we don't want to use -p hhvm parameter for standard PHP versions and -p php-cgi for HHVM:

matrix:
  exclude:
    - php: 5.3.3
      env: PHP_SEGMENT_TEST="hhvm"

    - php: 5.4
      env: TPHP_SEGMENT_TEST="hhvm"

    - php: 5.5
      env: PHP_SEGMENT_TEST="hhvm"

    - php: 5.6
      env: PHP_SEGMENT_TEST="hhvm"

    - php: hhvm
      env: PHP_SEGMENT_TESTRUN="php-cgi"
Enter fullscreen mode Exit fullscreen mode

To your pleasure, you can define jobs that are allowed to fail without causing the whole build to shown as failed. To do so, declare allow_failures. For our sake, we allow HHVM to fail, lets do this via:

matrix:
  allow_failures:
    - php: hhvm
Enter fullscreen mode Exit fullscreen mode

I only specified the PHP version, not the environment variables. This means all jobs with HHVM version will be allowed to fail/retry (if that is an option you have in your .travis.yml. Anyway, nevermind the environment variables values. It works with exclude also.

Running the scripts/tests

Tests are run in script segment of the .travis.yml. Let's assume your tests are in scripts/ folder in your file tree and you provide your own php.ini in the same folder. Additionally, we can tell TESTER to display information about skipped tests with the -s flag and to use value of earlier declared TESTER_SEGMENT_TEST as PHP binary with the -p flag:

script:
  - ./vendor/bin/tester -p $TESTER_SEGMENT_TEST -s -c ./tests/php.ini ./tests
Enter fullscreen mode Exit fullscreen mode

If the build fails we want to use after_failure to get the exact values via:

after_failure:
  # Prints *.actual files contents (if not revert) 
  - for i in $(find ./tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
Enter fullscreen mode Exit fullscreen mode

Other services

Travis comes with multiple popular services and has no shortages of them, (e.g. MySQL, Redis, Docker) pre-installed. However, if you need to use for example Redis storage, you can tell Travis in services section via:

 services:
  - redis-server
Enter fullscreen mode Exit fullscreen mode

DB Init

Depending on what database you chose to use, it can vary -- in this example we are using MySQL. MySQL runs on 127.0.0.1 and you can log in using travis or root as username. Say you have a DB setup script, and it's in tests/montana/testbase.sql., here's a sample segment:

 before_script:
  - mysql -u root -e 'CREATE DATABASE testbase;'
  - mysql -u root testbase < tests/montana/testbase.sql
Enter fullscreen mode Exit fullscreen mode

.travis.yml in it's final form

After a lot of this segment config, this is what you're left with:

language: php

php:
  - 5.3.3
  - 5.4
  - 5.5
  - 5.6
  - hhvm

env:
  - TESTER_SEGMENT_TEST="php-cgi"
  - TESTER_SEGMENT_TESTRUN="hhvm"

matrix:
  allow_failures:
    - php: hhvm

  exclude:
    - php: 5.3.3
      env: TESTER_SEGMENT_TEST="hhvm"

    - php: 5.4
      env: TESTER_SEGMENT_TEST="hhvm"

    - php: 5.5
      env: TESTER_SEGMENT_TEST="hhvm"

    - php: 5.6
      env: TESTER_SEGMENT_TEST="hhvm"

    - php: hhvm
      env: TESTER_SEGMENT_TESTRUN="php-cgi"

services:
  - redis-server

before_install:
  - composer self-update

install:
  - composer install --no-interaction --prefer-source

before_script:
  - mysql -u root -e 'CREATE DATABASE testbase;'
  - mysql -u root testbase < tests/montana/testbase.sql

script:
  - ./vendor/bin/tester -p $TESTER_SEGMENT_TEST -c ./tests/php.ini -s ./tests/

after_failure: # to find actual variables if needed, a verbose esque way of doing things
  # Prints *.actual files content
  - for i in $(find ./tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
Enter fullscreen mode Exit fullscreen mode

Activate webhook

Go to www.travis-ci.com, and flip switch to ON for all repositories you'd like to enable. Travis will now add your repository to queue after every pushed commit or created pull-request. After a short while, your repository will be tested. Now if you'd like the opposite, there's a bash script I've created, which I will attach right below this - as some people find this more efficient:

#!/usr/bin/env sh

echo "Hello from Montana at Travis"
echo $TRAVIS_PULL_REQUEST

if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
  surge --project ./dist --domain auto-deploy-test.surge.sh
else
  echo "This is a PR, not deploying"
fi
Enter fullscreen mode Exit fullscreen mode

To know if your build is successful either check the GitHub status, or generate a status image.

Congratulations

This is Travis's Build Matrix in a nutshell, it can seem a bit confusing but after going over it a few times, it will start to make sense.

Top comments (0)