The Cookbook: Build Matrix
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
language: php php: - 5.3.3 - 5.4 - 5.5 - 5.6 - hhvm
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 seperately as such. We are going to use
PHP_SEGMENT_TEST later in the file to run tester with the argument of
hhvm option in HHVM environment, so in your
.travis.ymlfile, add the
env: - PHP_SEGMENT_TESTRUN="php-cgi" - PHP_SEGMENT_TEST="hhvm"
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
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"
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
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
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. Additionaly, 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
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
# 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
# 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
.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
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
To know if your build is successful either check the GitHub status, or generate a status image.
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.