7 Tips to Get the Most out of Travis CI

Travis CI is the most spread CI in checking open-source projects.

Do you want to know how to use it 3x faster?
How to make Travis generate code for you?
And how to make your tokens safe?

1. Skip x-debug

Xdebug makes everything much slower in exchange for deep analysis. It's usefulonly for code coverage in CI.

Turn it off to get faster:

before_script:
    - phpenv config-rm xdebug.ini || return 0

Do you use coverage? Just use condition:

before_script:
    # disable xdebug if not coverage
    - if [[ $COVERAGE == "" ]]; then phpenv config-rm xdebug.ini; fi

2. Deliver PR Checks Fast

The speed of feedback loop in PRs has the same effect as page load time. If the page is loading more than 4 seconds, most people leaves thinking it's broken.

What is must-have in PR check?

What can be checked later?

When tests, static analysis, and coding style can finish in 3 minutes including composer install, the code coverage and deploy could prolong waiting to 9 minutes. For no added value, because it should be performed on merge.

Would you contribute to PR where you wait 9 minutes or 3 to know it passed?

For these reasons, there is $TRAVIS_BRANCH ENV var:

after_script:
    - |
      if [[ $COVERAGE == true && $TRAVIS_BRANCH == "master" ]]; then
        vendor/bin/phpunit --coverage-clover coverage.xml
        wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar
        php php-coveralls.phar --verbose
      fi

This way coverage is run just once the PR merged. Imagine the safe process time and human nerves in PR where were additional 10 commits after code-review.

3. Use ENV vars

ENV vars is a standard approach to set secure values, pass options to containers and PHP application. It's a trend Symfony pushes every version, recently with this Symfony 4.2 deprecation:

-php bin/console command_name --env=test --no-debug
+APP_ENV=test APP_DEBUG=0 php bin/console command_name

How to use them?

language: php

matrix:
    include:
      - php: 7.2
        env: STATIC_ANALYSIS=true
      - php: 7.2

script:
    - vendor/bin/phpunit

    - |
      if [[ $STATIC_ANALYSIS == true ]]; then
        vendor/bin/ecs check src
        vendor/bin/phpstan analyze src --level max
      fi

Travis also allows Stages oppose ENV variables. I've tried that and it has much more complicated YAML syntax, than just VAR=value. Also due to ENV trends lead by Docker, containers in general and Symfony, I'd stick with ENV vars for open-source projects.

For private projects stages are great since you need to deploy migrations and the code itself. But for private projects, I think Gitlab CI is a much more valuable option. Ask Jan Mikeš about that.

4. Use Travis to do More Just Watching

Most projects use Travis to check tests and analyze code. But did you know you can also use it for open-source deploy? And even more:

script:
    # make sure there are no duplicates
    - bin/console validate-groups

    # import data and genearte YAML
    - bin/console import

    # generate website to "/output" directory
    - vendor/bin/statie generate source

Since filesystem exists as long as the container is running, you can download, dump and work with almost any data in it.

One more thing: Travis is super fast. What on my laptop takes 10 minutes, it can solve in 2.

5. Rebuild your GitHub Pages Daily

One of the sexy features of Travis are Cron Jobs in combination with Github Pages and deploy:

It is this easy to deploy Statie website to Github Pages:

language: php

php: 7.2

install:
    - composer install

script:
    - vendor/bin/statie generate source

deploy:
    provider: pages
    skip_cleanup: true
    github_token: $GITHUB_TOKEN
    local_dir: output
    on:
        branch: master

Check real life .travis.yml to getter better idea:

6. Stay Secure

When I said you can Tweet with your Travis, I mean it. That's what me lazy bastard does on this blog:

after_deploy:
    - |
      if [[ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]]; then
        packages/StatieTweetPublisher/bin/publish-new-tweet
      fi

You may think "that not secure, bro", and you're right! To be able to tweet Travis needs to know the auth tokens that Twitter generates for you:

language: php

env:
    - TWITTER_CONSUMER_KEY="asd0830GA709GA"
    - TWITTER_CONSUMER_SECRET="asd0830GA709GA"
    - TWITTER_OAUTH_ACCESS_TOKEN="asd0830GA709GA"
    - TWITTER_OAUTH_ACCESS_TOKEN_SECRET="asd0830GA709GA"
    # they're all fake, don't even try it!

This could work, but then everyone would see it.

How to do it in secret?

You can actually enter them manually in Travis administration of your repository - here is the tutorial.

But still, what if someone will send you following PR:

script:
    - echo $TWITTER_CONSUMER_KEY
    - echo $TWITTER_CONSUMER_SECRET
    - echo $TWITTER_OAUTH_ACCESS_TOKEN
    - echo $TWITTER_OAUTH_ACCESS_TOKEN_SECRET

That's not nice and you should not do that to your friends! No, really, it a good way of thinking how to hack - good job.

Travis thought about this:

But what if you try:

$secret = getenv('TWITTER_CONSUMER_KEY');
for ($i = 0; $i < strlen($secret); ++$i) {
    echo $secret[$i] . PHP_EOL;
}

Well, that still won't work (I tried that), since these variable are available only for the repository owner.

But if you as an owner do echo it like this PHP script, you're screwed :).

7. Make use of Composer Scripts

Did you know you can define your own composer scripts and run them with composer <name>? If not, check Have you tried Composer Scripts? You may not need Phing that explains it in a very practical way.

So instead of writing it manually in Travis and locally and just waiting for a typo or miss use of invalid config:

script:
    # static analysis
    - vendor/bin/ecs check bin src test packages
    - vendor/bin/phpstan analyze packages bin src tests packages --level max

you can actually use these in Travis as well:

script:
    # static analysis
    - composer check-cs
    - composer phpstan

Anyone who needs to debug and know what's behind these shortcuts can just open composer.json:

{
    "scripts": {
        "check-cs": "vendor/bin/ecs check bin src tests packages",
        "phpstan": "vendor/bin/phpstan analyse bin src tests packages --level max"
    }
}


Did I miss some tip you use every day or do you know a better one? Share in comments!


Typo? Fix it, please  and join 49 people who build this website