Comment utiliser les Github Actions

Découvrez comment utiliser les github actions pour tester et déployer vos projets Python.

Publié le par Gabriel Trouvé (mis à jour le )
27 minutes

GitHub Actions est un outil d'intégration continue (CI) et de déploiement continu (CD) permettant d'automatiser des « workflows » (= une liste de processus prédéfinis) sans utiliser de service externe.

Dans cet article, nous allons nous intéresser à l'intégration continue (CI), en utilisant GitHub Actions avec un projet Django.

Les workflows sont déclenchés par des événements dans votre dépôt GitHub, comme un push ou une pull request.

GitHub Actions permet donc d'exécuter un workflow, déclenché par un événement, qui va exécuter un ou plusieurs travaux (jobs).

Ces jobs sont eux-mêmes composés d'étapes (steps).

Concrètement, ces workflows permettent d'automatiser le lancement de tests, le linting (analyse statique du code source pour détecter des problèmes) ou encore le déploiement de votre code.

Structure d'un fichier GitHub Actions

Les workflows sont définis dans des fichiers YAML (extension .yml ou .yaml). YAML est un format texte qui utilise l'indentation pour organiser les relations hiérarchiques entre les données.

name: Nom du workflow

on: # Événements qui déclenchent le workflow
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  nom_du_job:
    runs-on: ubuntu-latest # Système d'exploitation du runner

    steps:
    - name: Nom de l'étape
      uses: action/quelconque@version # Action à utiliser

    - name: Autre étape
      run: commande-à-exécuter # Commande shell à exécuter

Dans cet exemple, plusieurs composants :

  • Le nom (name) du workflow qui apparaît dans l'interface GitHub

  • La section on qui définit les déclencheurs du workflow (push et pull request dans l'exemple)

  • Les jobs qui représentent les travaux à effectuer

  • runs-on qui spécifie l'environnement d'exécution

Concernant le runs-on, GitHub propose plusieurs types d'environnements virtuels. Il est possible d'exécuter les actions sur Ubuntu (ubuntu-latest), Windows (windows-latest) ou macOS (macos-latest) par exemple. Vous retrouverez une liste des environnements disponibles sur cette page.

Chaque job contient des étapes (steps) qui peuvent utiliser des actions prédéfinies (uses) ou exécuter des commandes shell (run).

Configuration de base pour un projet Django

Création de l'Action

Pour cet article, j'ai créé un projet Django et un dépôt sur GitHub.

Vous pouvez ensuite depuis votre dépôt sur Github, cliquer sur l'onglet Actions et utiliser un template Django existant (s'il n'apparaît pas directement, vous pouvez utiliser le moteur de recherche).

Onglet Actions de github

Onglet Actions de github

Avant les prochaines étapes :

  • Pensez à générer un requirements.txt pour votre projet

  • Ajoutez un test dans votre projet (vous pouvez ajouter un test factice qui retourne True au départ pour tester le bon fonctionnement du workflow)

En sélectionnant le template Django via le bouton Configure, un fichier est créé dans .github/workflows/django.yml.

J'y apporte quelques modifications :

  • Les versions de Python : je spécifie des versions plus récentes, tout en les nommant entre guillemets (cela évite des problèmes d'interprétation du fichier)

  • La commande de test, car j'utilise pytest

Vous pouvez ensuite cliquer sur Commit changes et le workflow va s'exécuter.

Fichier django.yml de github actions

Fichier django.yml de github actions

En revenant sur l'onglet Actions, nous remarquons que le workflow s'est exécuté avec succès.

Workflow exécuté avec succès

Workflow exécuté avec succès

Pensez maintenant à faire un git pull dans le terminal de votre projet pour intégrer le workflow en local.

Composition d'un fichier de workflow

Comme nous l'avons vu précédemment, un workflow est défini par un fichier YAML situé dans le répertoire .github/workflows de votre dépôt. Ce fichier décrit l'ensemble du processus d'automatisation.

name: Django CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: ["3.10", "3.11"]

    steps:
    - uses: actions/checkout@v4
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v3
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run Tests
      run: |
        pytest

Les déclencheurs

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

Cette section va déterminer quand le workflow va s'exécuter. Dans ce cas :

  • à chaque push sur la branche main,

  • à chaque pull request ciblant la branche main.

Les jobs

jobs:
  build:

Un job est une tâche qui va s'exécuter dans votre workflow, qui peut éventuellement en contenir plusieurs. Dans notre cas, nous avons un unique job que nous appelons build (mais on pourrait l'appeler autrement).

L'environnement d'exécution

runs-on: ubuntu-latest

Cette ligne spécifie sur quel type de machine virtuelle sera exécuté le job. Dans ce cas, la dernière version d'ubuntu.

La stratégie

strategy:
  max-parallel: 4
  matrix:
    python-version: ["3.10", "3.11"]
  • matrix permet de définir des combinaisons de variables pour générer des exécutions multiples du job,

  • max-parallel limite le nombre de jobs du matrix qui peuvent s'exécuter en même temps.

Les étapes d'exécution (steps)

- uses: actions/checkout@v4

Cette étape utilise l'action checkout qui permet de récupérer le code source du dépôt et de le clôner dans l'environnement d'exécution. Le paramètre @v4 indique que nous utilisons la version 4 de cette action.

- name: Set up Python ${{ matrix.python-version }}
  uses: actions/setup-python@v3
  with:
    python-version: ${{ matrix.python-version }}

Cette étape permet de configurer l'environnement Python pour chaque version spécifiée dans le matrix.
python-version: ${{ matrix.python-version }} permet de préciser la version de python à installer de manière dynamique.

L'installation des dépendances

- name: Install Dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt

Cette étape utilise run pour exécuter des commandes shell, pour installer les dépendances depuis le fichier requirements.txt.

L'exécution des tests

- name: Run Tests
  run: |
    pytest

Cette dernière étape exécute la commande pytest pour lancer les tests du projet Django.

Configurer les secrets

Il arrive bien souvent qu'on ait besoin de créer un fichier .env pour stocker des informations sensibles comme les clés secrètes, des identifiants de base de données ou des clés d'API.

Ces informations n'apparaissent (heureusement !) pas en clair dans votre code et sont bien souvent stockées dans un fichier à part.

Gestion des données avec django-environ

Dans le projet qui sert d'exemple, j'installe django-environ pour gérer les données sensibles. Ici, on prendra l'exemple de la SECRET_KEY de Django.

Attention

N'oubliez pas d'ajouter django-environ au fichier requirements.txt. Sinon, le package ne sera pas installé au moment de l'exécution du workflow.

Voici à quoi ressemblent les premières lignes du fichier settings.py :

from pathlib import Path
import environ

env = environ.Env()

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

environ.Env.read_env(BASE_DIR / '.env')


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

Il faut importer environ, initialiser une variable env avec :
env = environ.Env()

Et récupérer le fichier .env avec :
environ.Env.read_env(BASE_DIR / '.env')

Il faut donc créer un fichier .env dans votre projet Django, y insérer la clé secrète :
SECRET_KEY=django-insecure-p67cf0xh#*tax*c-gkv2ij96659v#^x$3+542br2$4=n_kge_h

Et la récupérer dans votre fichier settings.py :
SECRET_KEY = env('SECRET_KEY')

Configurer les secrets sur GitHub

Il faut maintenant penser à configurer les secrets sur GitHub, pour récupérer cette clé secrète, car le fichier .env n'est bien sûr pas versionné pour ne pas exposer les clés.

Il faut donc un moyen de donner ces clés secrètes à notre workflow.

Le menu settings de GitHub

Le menu settings de GitHub

Pour ce faire, il suffit d'aller dans le menu Settings > Secrets and variables > Actions et cliquer sur New repository secret.

Ajout d'un secret dans GitHub

Ajout d'un secret dans GitHub

Utiliser les secrets dans le workflow

Une fois les secrets configurés (dans cet exemple je n'ai configuré que la clé secrète de Django), il faut la référencer dans le workflow :

name: Django CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    env:
      SECRET_KEY: ${{ secrets.SECRET_KEY }}

    strategy:
      max-parallel: 4
      matrix:
        python-version: ["3.10", "3.11"]

    steps:
    - uses: actions/checkout@v4
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v3
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run Tests
      run: |
        pytest

Dans le job build, j'ai ajouté :

    env:
      SECRET_KEY: ${{ secrets.SECRET_KEY }}

Vous pouvez évidemment ajouter plusieurs secrets dans votre dépôt GitHub, mais pensez bien à les renseigner à chaque fois dans votre fichier de workflow.

Désormais, quand je fais un commit et que je push mes modifications, le workflow est de nouveau exécuté. Si vous avez bien configuré votre ou vos secrets, vous ne devriez pas avoir d'erreurs :

Nouvelle exécution du workflow

Nouvelle exécution du workflow

Avec quelques lignes de YAML, des secrets bien configurés, vous avez mis en place un workflow directement sur GitHub en quelques minutes 💪

Vous disposez désormais d'un processus d'intégration continue (CI) qui permet de vérifier à chaque modification de votre projet que vos tests et autres processus s'exécutent correctement.

Cela vous permet d'éviter beaucoup de problèmes en amont.

Vous pourrez par la suite envisager un système de déploiement continu (CD) pour déployer votre code si l'intégration continue passe avec succès.

Cela permet d'être sûr que votre projet fonctionnera bien en production (du moins, les fonctionnalités qui auront été testées, si celles-ci sont correctement testées, mais c'est un autre sujet !).

Bravo, tu es prêt à passer à la suite

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.