November 10th 2019

The pull request that was worth $759 or how to migrate from Travis CI to Github Actions

First, a big thanks to the Travis team for their great work.

But in the current case, the project (running on symfony 3.4) is on Github and we have access to the beta of (new) Github Actions. Travis's annual 'Bootstrap plan' costs $759/year and most often, managers ask to save money.

cover

Advantages and disadvantages of migrating:

👍

  • Pricing: from $759/year to $0 (included in Github plan)
  • Parallel running ! (instead Travis CI limit to 1 concurrent job)
  • Fully integrate to github

👎

  • Running time: from ~6min to ~8min (build: ~2,5min / Tests: ~5,5min) (yes, we have to improve that)

Sources

Travis

Old .travis file:

dist: bionic

language: php

# Allows use container-based infrastructure https://docs.travis-ci.com/user/getting-started/#Selecting-infrastructure-(optional)
sudo: enabled

services:
  - mysql
  - redis-server

php:
  - 7.2

# Env
env:
  matrix:
    - DEPENDENCIES="high"
  global:
    - DEFAULT_COMPOSER_FLAGS="--no-interaction --no-ansi --no-progress --no-suggest"

# Cache composer packages so "composer install" is faster
cache:
  directories:
    - $HOME/.composer/cache/files

before_install:
  - echo $TRAVIS_BUILD_DIR
  - cp app/config/parameters-test.yml.dist app/config/parameters-test.yml 
  # Php extensions (https://blog.travis-ci.com/2013-03-08-preinstalled-php-extensions / https://docs.travis-ci.com/user/languages/php/#PHP-extensions)
  - echo "Adding Custom PHP Extensions"
  - echo "extension=redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
  - echo "extension=apcu.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
  - composer global require hirak/prestissimo # downloading dependencies in parallel

# Install
install:
  - echo `pwd`
  - mysql -u root -e "CREATE DATABASE \`${DB_NAME}\`;"
  - if [[ "$DEPENDENCIES" = 'high' ]]; then travis_retry composer install $DEFAULT_COMPOSER_FLAGS; fi
  - if [[ "$DEPENDENCIES" = 'low' ]]; then travis_retry composer install $DEFAULT_COMPOSER_FLAGS --prefer-lowest; fi

before_script:
  - phpenv config-rm xdebug.ini || return 0 # no coverage, not needed
  - echo `pwd`

# Run script
script:
  - composer validate --no-check-all --strict # composer.json and composer.lock should be always kept in sync.
  - ./vendor/bin/phpunit

New workflow .github/workflows/project.yml file:

on: [push]
name: Main
jobs:
  symfony:
    runs-on: ubuntu-latest

    services:
      redis:
        image: redis
        ports:
          - 6379:6379
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - 3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      - name: Configure server
        run: |
          sudo apt-get install language-pack-fr
          sudo apt-get install language-pack-nl
          sudo locale-gen fr_FR
          sudo locale-gen fr_FR.UTF-8
          sudo locale-gen nl_BE
          sudo locale-gen nl_BE.UTF-8
          sudo update-locale
          locale -a

      - name: Verify MySQL connection from host
        run: |
          sudo apt-get install -y mysql-client libmysqlclient-dev
          mysql --host 127.0.0.1 --port ${{ job.services.mysql.ports[3306] }} -uroot -proot -e "SHOW GRANTS FOR 'root'@'localhost'"

      - name: Add mysql test database & user
        run: |
          mysql -uroot -h127.0.0.1 -proot -e "CREATE DATABASE IF NOT EXISTS database_test;"

      # doc: https://github.com/marketplace/actions/setup-php-action
      - name: Setup PHP
        uses: shivammathur/[email protected]
        with:
          php-version: '7.2'
          extension-csv: apcu,redis,dom,gd,intl,mbstring,soap

      - name: Configure PHP
        run: |
          sudo phpdismod -s cli xdebug

      - name: Check PHP
        run: |
          php -v

      - uses: actions/[email protected]
        with:
          fetch-depth: 1

      - name: Install composer dependencies
        run: |
          composer global require hirak/prestissimo --no-interaction --no-ansi --no-progress --no-suggest # downloading dependencies in parallel
          composer install --no-interaction --no-ansi --no-progress --no-suggest -o
          composer validate --no-check-all --strict

      - name: Run tests
        run: |
          ./vendor/bin/phpunit
        env:
          SYMFONY_ENV: test

We use the setup of shivammathur/setup-php which allows us to easily choose the version of PHP and also the extensions we need.

cover

Documentation

Romain Norberg

Romain Norberg

Php developer, play with Symfony and PhalconPhp frameworks.
More on LinkedIn or Github