Stella

Passer de Travis CI à GitHub Actions

En dehors de Stella, on s’occupe de projets libres (comme WeasyPrint par exemple). Et bien sûr, ils ont des tests ! Après avoir utilisé Travis CI, nous avons décidé de passer sur GitHub Actions. En voici un petit retour d’expérience :).

Pourquoi Travis ?

De nombreux services proposent de l’intégration continue, peu importe la plateforme où sont les dépôts des projets (dans notre cas, c’est GitHub). Parmi ces services, on retrouve Travis CI, GitLab CI ou encore GitHub Actions.

Au début, Travis a été choisi tout simplement parce que c’était le seul service largement utilisé qui existait et qui était gratuit, au moins pour les projets libres.

Pourquoi changer ?

Travis offre des fonctionnalités plutôt pratiques, comme par exemple de pouvoir lancer les tests sur MacOS et Windows. C’est plutôt bien et ce n’est pas forcément le cas de tous les services de CI.

La configuration se fait assez simplement avec un fichier .travis.yml à mettre à la racine du projet.

Par contre, Python ne fait pas partie des langages supportés pour Windows et MacOS, ce qui est un peu dommage quand on a des projets en Python. Malgré cela, on peut quand même s’en sortir.

Mais surtout… c’est lent.

Changer, oui. Mais pour quoi ?

Alors oui c’est lent, mais il nous fallait un service qui dispose de fonctionnalités au moins équivalentes. Hors de question de perdre les tests sous Windows qui avaient été enfin mis !

Dans les choix possibles, nous avions GitLab CI et GitHub Actions qui proposent un service gratuit sans limite de minutes d’utilisation trop restrictives pour notre utilisation.

Malgré notre grand amour pour GitLab, il n’est pas possible de lancer des tests sous MacOS et la fonctionnalité est en bêta pour Windows…

Alors oui, il est possible d’installer soi-même des runners sur ses machines pour avoir tout ça. Mais quand on n’a pas de Windows ou de Mac sous la main… c’est de suite plus compliqué. (Note : il y a des runners partagés pour Windows.)

Et avec GitHub Actions, on peut lancer des tests sur Windows et MacOS. C’est fantastique, voici l’élu !

GitHub Actions en action

De la même manière que Travis, la configuration se fait par un fichier YAML à mettre dans un dossier à la racine du dépôt. On peut y mettre plusieurs fichiers si l’on veut faire différentes choses et bien les séparer (mais nous, on veut juste lancer les tests, pour l’instant).

Dans un fichier de configuration GitHub Actions, chaque ligne qui est exécutée est une Action. Et GitHub Actions dispose d’Actions déjà toutes faites qui nécessitent juste d’être appelées (et tout le monde peut proposer les siennes aussi :) ). Ainsi une instance « vide » est facilement customisable pour préparer tout ce dont on a besoin pour lancer nos tests.

Dans ce large univers d’Actions, il y en a une qui nous intéresse tout particulièrement : setup-python. C’est elle qui va installer le minimum requis pour faire des choses avec du Python. Du genre : Python et pip par exemple, très pratique. Pour Linux, MacOS et Windows. Avec la version de Python souhaitée. Vraiment très pratique.

Après, il n’y a rien de bien différent. On peut faire des matrices pour gérer les combinaisons de versions et d’OS.

Un petit comparatif peut-être ?

Pour un projet plutôt basique en Python, nous avions ce fichier pour Travis :

language: python
env: PYTHON=python3

jobs:
  include:
    - python: 3.6
    - python: 3.7
    - python: 3.8
    - python: pypy3
    - os: osx
      language: generic
    - os: windows
      language: shell
      env: PYTHON=/c/Python38/python

install:
  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install -y python; fi
  - $PYTHON -m pip install --upgrade pip setuptools
  - $PYTHON -m pip install .[test]

script:
  - $PYTHON -m pytest --isort --flake8 --ignore=tests/css-parsing-tests

Ce qui lance des tests sur Linux pour quatre différentes versions de Python, ainsi que sur MacOS et Windows pour une seule version. Soit au total six environnements de test. Travis met entre 2 min 30 et 15 min pour tout faire.

Pour GitHub Actions, nous avons à présent ce fichier :

name: tinycss2's tests
on: [push]

jobs:
  tests:
    name: ${{ matrix.os }} - ${{ matrix.python-version }}
    runs-on: ${{ matrix.os }}
    strategy:
      # En cas d’échec sur un environnement, les autres ne sont pas interrompus
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: [3.6, 3.7, 3.8, pypy3]
        # On peut exclure des combinaisons de la matrice
        exclude:
          # pytest-isort not working
          - os: windows-latest
            python-version: pypy3
    steps:
      # Actions qui clone le dépôt
      - uses: actions/checkout@v2
        # Ce projet utilise des sous-modules
        with:
          submodules: true
      # L’environnement python est préparé pour les versions définies dans la matrice
      - uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Upgrade pip and setuptools
        run: python -m pip install --upgrade pip setuptools
      - name: Install tests's requirements
        run: python -m pip install .[test]
      - name: Launch tests
        run: python -m pytest --isort --flake8 --ignore=tests/css-parsing-tests

C’est onze environnements de test qui sont lancés, pour un temps d’exécution entre 1 min 20 et 4 min.

GitHub Actions est bien plus rapide que Travis et nous permet de couvrir plus d’environnements différents !

Pour aller plus loin

Nous avons pris en exemple un projet qui ne nécessite que très peu de mise en place.

Pour des projets où l’on veut exécuter des choses uniquement sur certains environnements, GitHub Actions offre une configuration plus élégante.

Par exemple, pour WeasyPrint avec Travis nous avions :

- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then export "PATH=$PATH;C:\msys64\mingw64\bin"; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install -y python dejavufonts; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wget "http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz"; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then 7z e msys2-base-x86_64-20180531.tar.xz; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then 7z x -y msys2-base-x86_64-20180531.tar -oc:\\; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then powershell "C:\msys64\usr\bin\bash -lc 'pacman -S mingw-w64-x86_64-gtk3 --noconfirm'"; fi

- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mkdir -p ~/.fonts; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget "https://github.com/Kozea/Ahem/blob/master/Ahem.ttf?raw=true" -O ~/.fonts/Ahem.ttf; fi

- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew tap homebrew/cask-fonts; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew cask install font-dejavu; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cairo pango gdk-pixbuf libffi; fi

Et maintenant avec GitHub Actions :

- name: Install DejaVu (Ubuntu)
  if: matrix.os == 'ubuntu-latest'
  run: sudo apt-get update -y && sudo apt-get install ttf-dejavu -y
- name: Install DejaVu, cairo, pango, gdk-pixbuf and libffi (MacOS)
  if: matrix.os == 'macos-latest'
  run: |
    brew tap homebrew/cask-fonts
    brew cask install font-dejavu
    brew install cairo pango gdk-pixbuf libffi
- name: Install msys2 and DejaVu (Windows)
  if: matrix.os == 'windows-latest'
  run: |
    choco install -y --no-progress msys2
    powershell "C:\tools\msys64\usr\bin\bash -lc 'pacman -S mingw-w64-x86_64-ttf-dejavu mingw-w64-x86_64-gtk3 --noconfirm'"
    xcopy "C:\tools\msys64\mingw64\share\fonts\TTF" "C:\Users\runneradmin\.fonts" /e /i
    $env:PATH += ";C:\tools\msys64\mingw64\bin"
    echo "::set-env name=PATH::$env:PATH"

Nous avons beaucoup parlé des environnements Python sur GitHub Actions, mais ce n’est pas le seul langage supporté. Il y a de nombreuses Actions pour plein de langages et pour faire plein de choses ;).