Recently I’ve been working to reduce the Travis CI build times of not only WordPress core, but also the WordPress plugins and projects that I maintain.
I’m going to use this post to document patterns and tips that you can use to speed up your build times. Comments welcome!
Travis CI runs its builds with XDebug enabled by default. This is handy if you’re generating code coverage reports, but it really slows things down. On the WordPress core project, build times reduced by a whopping 40% when XDebug was disabled.
Add this line to your
.travis.yml file and watch your build times plummet:
before_install: - phpenv config-rm xdebug.ini
Move Away From the WP_MULTISITE Pattern
If you test your plugin on both multisite and single-site environments, you might be using the
WP_MULTISITE environment variable method in
env: - WP_VERSION=latest WP_MULTISITE=1 - WP_VERSION=latest WP_MULTISITE=0 script: - phpunit
This causes two jobs to run with each build, which isn’t optimal. Instead, switch to a test script which runs PHPUnit once with multisite enabled and once without. This halves the number of jobs, greatly reducing the overall build time.
env: - WP_VERSION=latest script: - ./bin/test.sh
# Run single-site unit tests: export WP_MULTISITE=0 phpunit --exclude-group=ms-required # Run Multisite unit tests: export WP_MULTISITE=1 phpunit --exclude-group=ms-excluded
Cache All The Things
Caching on Travis CI is very effective and very well structured. You can cache Composer dependencies, for example, and they’ll be stored between builds in a persistent cache which is specific to the environment (eg. PHP version). This greatly reduces subsequent build times.
This should cover most of your needs for a WordPress project:
cache: apt: true directories: - node_modules - vendor - $HOME/.composer/cache
Enable Fast Finishing
If you’ve got allowed failures in your test matrix and you enable fast finishing, Travis CI will mark your build as finished as soon as one of two conditions are met: The only remaining jobs are allowed to fail, or a job has already failed.
While this doesn’t technically reduce your build times, it certainly reduces the time you need to wait for the build status to be reported. Drop this into your
matrix: fast_finish: true
Keep Your Fixtures Under Control
Not specific to Travis CI or CI in general, but keeping your fixtures (items such as posts created with the factories) under control can greatly reduce your test times. As an example, if you have a large number of tests which require sites, posts, users, or terms to be set up, consider setting them up once in the
wpSetUpBeforeClass() method and re-using them between tests. This means you only create your fixtures once per test case class, instead of once per test, which reduces the test time.
Take a look at some of the places in WordPress core where tests have been refactored to reuse fixtures between tests.
Reduce Your Environment Matrix
You might not need to test your project on every single version of PHP. My current pattern for my publicly released plugins is to test on the latest in the 5.x and 7.x branches. Currently, this means:
php: - 7.2 - 5.6
If you’re testing on earlier versions of PHP 5, consider removing them if you’re sure that your project doesn’t include functionality specific to those versions.
If your project is a client project with a known environment, then you’ve no need to test on other environments at all. For example, if the live site is hosted on a server running PHP 7.0, then you only need to test 7.0 on Travis CI:
php: - 7.0
Automatically Cancel Waiting Builds
If you push to a repo several times in quick succession, you may start to see a backlog of Travis builds. You can now instruct Travis to automatically cancel waiting builds when new build requests flow in from GitHub. This greatly reduces backlogs of builds and allows you to see test results for your latest build sooner.
(Thanks for the reminder from Inderpreet Singh in the comments.)
If you have any more tips to reducing test and build times, let me know in the comments!