Mise en place d'un workflow CI/CD pour un projet Symfony à l'aide des actions GitHub

Publié le 28/03/2020 • Mis à jour le 28/03/2020

Dans cet article nous allons voir comment mettre en place un workflow CI/CD pour un projet Symfony à l'aide des actions GitHub. Nous couvrirons de la configuration de PHP sur la machine hôte, au lancement des tests unitaires et fonctionnels de l'application Symfony. C'est parti ! 😎


English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧 Close

» Publié dans "Une semaine Symfonique #691" (du 23 au 29 mars 2020).

Durant cette période très particulière, j'espère que vous allez bien et que vous prenez soin de vous. Prenez aussi soin des autres s'il vous plait : #StayTheFuckHome .

Prérequis

J'assumerai que avez les compétences de base concernant Symfony. Que vous savez comment initialiser une application et lancer des tests. Pour pouvoir utiliser les actions GitHub, vous devez avoir un dépôt public ou un compte PRO pour vos dépôt privés.

[🇫🇷 🇬🇧] : Désolé, il y a pas mal d'anglicismes dans cet article, je les ai mis en italique pour la plupart.

Configuration

  • PHP 7.4
  • Symfony 5.1.2

Introduction

Les "actions" GitHub sont disponibles depuis quelques mois, mais je n'avais pas encore essayé cet outil. Comme j'utilise beaucoup GitHub où j'y ai tous mes projets, il me semblait naturel d'y avoir également mon environnement CI/CD.

But

Le but va être d'être capable de lancer les tests unitaires et fonctionnels de ce projet mais aussi de vérifier le code sur de multiples versions de PHP. Jusqu'à maintenant, j'utilisais PHP 7.2 sur mon serveur de production, mais j'envisage de migrer vers PHP 7.4. Est-ce que mon projet est prêt pour cette version ? 🤔

[Edit 03/04/2020] J'ai depuis migré vers PHP 7.4.🙂

Si vous ne connaissez pas les actions GitHub et que vous voulez les utiliser pour votre projet Symfony, le fichier workflow suivant peut-être une bonne base à adapter à vos besoins.

Creation d'un workflow

Créez un fichier .github/workflows/symfony.yml dans votre projet. Ce fichier ne contiendra qu'un travail (🇬🇧 job) qui contiendra tout le workflow dont j'ai besoin. Je n'ai pas envie d'avoir quelque chose de trop compliqué, donc gardons l'ensemble le plus simple possible. Comme je joue assez souvent avec en ce moment, il se peut que le contenu de ce fichier puisse varier mais je reporterai les modifications sur cet article pour chaque changement impactant. Dans le chapitre suivant nous reviendrons plus en détail sur chaque partie de ce fichier et j'expliquerai chaque étape de manière plus détaillée. Donc, voici le fichier dans son intégralité :

# https://help.github.com/en/actions
name: Full CI process for Symfony 5
on:
  push:
    branches:
    - master
env:
  ES_HTTP_PORT: 9209
jobs:
  symfony:
    name: Symfony 5.0 (PHP ${{ matrix.php-versions }})
    # https://hub.docker.com/_/ubuntu/
    runs-on: ubuntu-18.04
    services:
      # https://docs.docker.com/samples/library/mysql/
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
      # https://hub.docker.com/_/elasticsearch/
      elasticsearch:
        image: elasticsearch:6.8.6
        ports:
          - 9209:9200
        options: -e="discovery.type=single-node" --health-cmd="curl http://localhost:9200/_cluster/health" --health-interval=10s --health-timeout=5s --health-retries=10
    strategy:
      fail-fast: true
      matrix:
        php-versions: ['7.2', '7.4']
    steps:
      # —— Check Elasticsearch 🔎 ——————————————————————————————————————————————
      - name: Check the Elasticsearch connection from runner host
        run: |
          curl -fsSL "http://localhost:$ES_HTTP_PORT"
          curl -fsSL "http://localhost:$ES_HTTP_PORT/_cluster/health?pretty"

      # —— Setup Github actions 🐙 —————————————————————————————————————————————
      # https://github.com/actions/checkout (official)
      - name: Checkout
        uses: actions/checkout@v2

      # https://github.com/shivammathur/setup-php (community)
      - name: Setup PHP, extensions and composer with shivammathur/setup-php
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-versions }}
          extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, dom, filter, gd, iconv, json, mbstring, pdo
        env:
          update: true

      # https://github.com/zhulik/redis-action (community)
      - name: Setup Redis with zhulik/redis-action
        uses: zhulik/redis-action@1.1.0
        with:
          redis version: '5'

      # —— Composer 🧙‍️ —————————————————————————————————————————————————————————
      - name: Validate composer.json and composer.lock
        run: composer validate

      - name: Get composer cache directory
        id: composer-cache
        run: echo "::set-output name=dir::$(composer config cache-files-dir)"

      - name: Cache composer dependencies
        uses: actions/cache@v1
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: ${{ runner.os }}-composer-

      - name: Install Composer dependencies
        run: make install

      # —— Symfony 🎵 ——————————————————————————————————————————————————————————
      - name: Check Symfony requirements
        run: vendor/bin/requirements-checker

      - name: Check the Symfony console
        run: |
          php bin/console -V
          php bin/console strangebuzz:version

      ## —— Coding standards ✨ ————————————————————————————————————————————————
      - name: Coding standards checks (php_codesniffer + PHPStan)
        run: make cs

      ## —— Tests ✅ ———————————————————————————————————————————————————————————
      - name: Load Doctrine fixtures and populate the Elasticsearch indexes
        run: |
          make load-fixtures
          make populate

      - name: Run functionnal and unit tests
        run: |
          cp phpunit.xml.ci phpunit.xml
          make test

Paramètres du workflow

Voyons les paramètres les plus importants de ce fichier. Tel qu'indiqué par le paramètre runs-on, le lanceur (🇬🇧 runner) utilisera la distribution Linux Ubuntu 18.04 LTS (Bionic); c'est celle que j'utilise sur mon serveur de production. L'autre paramètre principal est celui concernant la matrice PHP :

  matrix:
    php-versions: ['7.2', '7.4']

Cela signifie que le workflow va s'exécuter à la fois sur PHP 7.2 et 7.4. Ça nous permet d'éviter la duplication de ce fichier de configuration pour chacune de ces versions. Ici, je n'ai mis que deux versions : ma version actuelle et celle vers laquelle j'apprête à migrer. Pour un projet open source, par exemple, vous mettrez toutes les version mineures (ou même majeures) que votre librairie supporte. Le paramètre fail-fast indique si la matrice doit s'arrêter dès qu'une erreur est rencontrée.

Dans la section service, on indique la version des composants que nous allons utiliser (En fait, la version Redis est quant à elle paramétrée dans son action spécifique, voir ci-dessous) :

  • MySQL 5.7
  • Elasticsearch 6.8
  • Redis 5

Les étapes du workflow

Plusieurs étapes constituent le workflow. Quand une étape échoue, le processus stoppe et rien de ce qui suit n'est exécuté, le workflow est marqué en erreur ❌ (failed). Sinon, il est en succès. Dans les trois sections suivantes, pour chaque action, vous pouvez voir les logs relatifs en cliquant sur le lien ‣ Cliquez ici pour voir / cacher la sortie de cette étape ✅. Si vous voulez voir tous les logs sans cliquer sur chaque lien, utilisez le bouton juste en dessous. Afin de rendre ces logs plus lisibles, j'y ai supprimé toutes les lignes redondantes ou inutiles.

 ≪ this.expanded ? this.trans.button_collapse_all : this.trans.button_expand_all ≫

• Étapes d'initialisation

Ces étapes sont responsables d'initialiser le job qui va exécuter les actions Github.

» Configuration du job

Cette étape instancie un runner et télécharge les dépôts des différentes actions utilisées dans le workflow.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Current runner version: '2.165.2'
Prepare workflow directory
Prepare all required actions
Download action repository 'actions/checkout@v2'
Download action repository 'shivammathur/setup-php@v2'
Download action repository 'zhulik/redis-action@1.1.0'
Download action repository 'actions/cache@v1'

» Construction de zhulik/redis-action@1.1.0

Action de configuration de Redis : télécharge et construit le conteneur qui va fournir le service Redis sur le port 6379. Cette action est disponible dans la market place de la communauté. Je voulais essayer pour voir si ça fonctionne bien. Mais on peut bien sûr l'initialiser manuellement dans la section service du fichier, tout comme MySQL et Elasticsearch.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Build container for action use: '/home/runner/work/_actions/zhulik/redis-action/1.1.0/Dockerfile'.
##[command]/usr/bin/docker build -t e87b52:d5b46c5afa2544c8b9b1b35120a65556 "/home/runner/work/_actions/zhulik/redis-action/1.1.0"
Sending build context to Docker daemon  7.168kB
Step 1/4 : FROM docker:stable
stable: Pulling from library/docker
c9b1b535fdd9: Already exists
cd54125436dc: Pulling fs layer
6aca4f909924: Waiting
70d1554c15cb: Verifying Checksum
70d1554c15cb: Download complete
cd54125436dc: Pull complete
Digest: sha256:5bca19bb6d8f0aea380902af97be841d5841353c04e3eda5f87b4e932a509e94
Status: Downloaded newer image for docker:stable
 ---> e036013d6d10
Step 2/4 : COPY entrypoint.sh /entrypoint.sh
 ---> c4ea3853cc97
Step 3/4 : RUN chmod +x /entrypoint.sh
 ---> Running in ab6b87d4b7a0
Removing intermediate container ab6b87d4b7a0
 ---> 87aee15fd9a8
Step 4/4 : ENTRYPOINT ["/entrypoint.sh"]
 ---> Running in 4becfb378f5b
Removing intermediate container 4becfb378f5b
 ---> f3a67891445a
Successfully built f3a67891445a
Successfully tagged e87b52:d5b46c5afa2544c8b9b1b35120a65556

» Initialisation des conteneurs

Cette étape va être responsable de créer tous les autres conteneurs déclarés dans le workflow. Cela va créer les ressources déclarées dans la section jobs > symfony > services de notre fichier. Dans les logs suivants, les deux messages essentiels sont : MySQL service is healthy et Elasticsearch service is healthy. Ces deux services sont prêts à être utilisés par notre application.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
##[command]/usr/bin/docker version --format '{{.Server.APIVersion}}'
'1.40'
Docker daemon API version: '1.40'
##[command]/usr/bin/docker version --format '{{.Client.APIVersion}}'
'1.40'
Docker client API version: '1.40'
##[command]/usr/bin/docker ps --all --quiet --no-trunc --filter "label=e87b52"
##[command]/usr/bin/docker network prune --force --filter "label=e87b52"
##[command]/usr/bin/docker network create --label e87b52 github_network_51587edd68e3421d88eaf5842fb44d03
3cfd017711d1c2c4b50be2f3db048ea812df776c39aca4d608c97410dc1d0810
##[command]/usr/bin/docker pull mysql:5.7
5.7: Pulling from library/mysql
68ced04f60ab: Pulling fs layer
702ec598d0af: Waiting
f9748e016a5c: Verifying Checksum
f9748e016a5c: Download complete
68ced04f60ab: Pull complete
Digest: sha256:f4a5f5be3d94b4f4d3aef00fbc276ce7c08e62f2e1f28867d930deb73a314c58
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
##[command]/usr/bin/docker create --name bfb02f6b5a4a454280b6be3fed6e1ba7_mysql57_ad121e --label e87b52 --network github_network_51587edd68e3421d88eaf5842fb44d03 --network-alias mysql -p 3306/tcp --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 -e "MYSQL_ROOT_PASSWORD=root" -e GITHUB_ACTIONS=true mysql:5.7
05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41
##[command]/usr/bin/docker start 05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41
05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41
##[command]/usr/bin/docker ps --all --filter id=05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41 --filter status=running --no-trunc --format "{{.ID}} {{.Status}}"
05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41 Up Less than a second (health: starting)
##[command]/usr/bin/docker port 05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41
3306/tcp -> 0.0.0.0:32768
##[command]/usr/bin/docker pull elasticsearch:6.8.6
6.8.6: Pulling from library/elasticsearch
ab5ef0e58194: Pulling fs layer
02437bb6d816: Waiting
5abe907f1981: Verifying Checksum
5abe907f1981: Download complete
ab5ef0e58194: Pull complete
Digest: sha256:be763d0b98b58a963f0496677be546211ec9aa336b0981ede98cec63325f55ef
Status: Downloaded newer image for elasticsearch:6.8.6
docker.io/library/elasticsearch:6.8.6
##[command]/usr/bin/docker create --name 7a612b8d5fa24e87830a2cc1e03aaa56_elasticsearch686_ce1133 --label e87b52 --network github_network_51587edd68e3421d88eaf5842fb44d03 --network-alias elasticsearch -p 9209:9209 -e="discovery.type=single-node" -e="http.port=9209" --health-cmd="curl http://localhost:9209/_cluster/health" --health-interval=10s --health-timeout=5s --health-retries=10 -e GITHUB_ACTIONS=true elasticsearch:6.8.6
64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
##[command]/usr/bin/docker start 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
##[command]/usr/bin/docker ps --all --filter id=64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0 --filter status=running --no-trunc --format "{{.ID}} {{.Status}}"
64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0 Up Less than a second (health: starting)
##[command]/usr/bin/docker port 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
9209/tcp -> 0.0.0.0:9209
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 05937a8d432624612b1d06f6c174b26d6023cb9f9c0bae7efeaf36f252c5aa41
healthy
mysql service is healthy.
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
starting
elasticsearch service is starting, waiting 2 seconds before checking again.
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
starting
elasticsearch service is starting, waiting 4 seconds before checking again.
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
starting
elasticsearch service is starting, waiting 8 seconds before checking again.
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
starting
elasticsearch service is starting, waiting 18 seconds before checking again.
##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 64475ed7c281304c3f62e9108bcfa5b922e7c6ab2825ec4ded7937a0cc1faaf0
healthy
elasticsearch service is healthy.

• Étapes principales

Les étapes précédentes étaient automatiquement ajoutées et lancées par Github. Maintenant commencent les actions que nous avons définies. Elles correspondent à la section jobs > symfony > steps du fichier.

» Vérification du bon accès de la machine hôte à Elasticsearch

Quand j'ai commencé à travailler sur ce workflow, j'ai eu des problèmes pour configurer Elasticsearch. C'est pourquoi j'ai ajouté cette étape très tôt pour éviter de continuer si celui-ci n'était pas démarré et joignable par l'application. Dans les commandes lancées, vous pouvez voir qu'on utilise une variable d'environnement $ES_HTTP_PORT que nous avons définie au préalable en tout début de fichier dans la section env. Avec le premier appel CURL on vérifie le numéro de version et avec le second on vérifie que le cluster est OK (green).

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run curl -fsSL "http://localhost:$ES_HTTP_PORT/"
{
  "name" : "uwLkILk",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "_doe3REkQ4KutBwyauK1lg",
  "version" : {
    "number" : "6.8.6",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "3d9f765",
    "build_date" : "2019-12-13T17:11:52.013738Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.2",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
Run curl -fsSL "http://localhost:$ES_HTTP_PORT/_cluster/health?pretty"
{
  "cluster_name" : "docker-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 0,
  "active_shards" : 0,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

» Checkout

Cette étape va récupérer le projet du dépôt.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run actions/checkout@v2
Added matchers: 'checkout-git'. Problem matchers scan action output for known warning or error strings and report these inline.
Syncing repository: COil/strangebuzz.com
Working directory is '/home/runner/work/strangebuzz.com/strangebuzz.com'
[command]/usr/bin/git version
git version 2.25.1
Deleting the contents of '/home/runner/work/strangebuzz.com/strangebuzz.com'
[command]/usr/bin/git init /home/runner/work/strangebuzz.com/strangebuzz.com
Initialized empty Git repository in /home/runner/work/strangebuzz.com/strangebuzz.com/.git/
[command]/usr/bin/git remote add origin https://github.com/COil/strangebuzz.com
[command]/usr/bin/git config --local gc.auto 0
[command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader
[command]/usr/bin/git config --local http.https://github.com/.extraheader AUTHORIZATION: basic ***
[command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +b0134f36a4f5989986a47425c7bfb0ccf7687a0e:refs/remotes/origin/master
remote: Enumerating objects: 1379, done.
remote: Counting objects:   0% (1/1379)
remote: Counting objects: 100% (1379/1379), done.
remote: Compressing objects:   0% (1/1195)
remote: Compressing objects: 100% (1195/1195), done.
Receiving objects:   0% (1/1379)
Receiving objects: 100% (1379/1379), 104.69 MiB | 35.17 MiB/s, done.
Resolving deltas:   0% (0/179)
Resolving deltas: 100% (179/179), done.
From https://github.com/COil/strangebuzz.com
 * [new ref]         b0134f36a4f5989986a47425c7bfb0ccf7687a0e -> origin/master
[command]/usr/bin/git checkout --progress --force -B master refs/remotes/origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
[command]/usr/bin/git log -1
commit b0134f36a4f5989986a47425c7bfb0ccf7687a0e
Author: COil
Date:   Tue Mar 27 09:38:48 2020 +0100
    [github] pr template
Removed matchers: 'checkout-git'

» Configuration de PHP, des extensions et de Composer avec l'action shivammathur/setup-php

Cette action de la communauté va configurer PHP à la dernière version de maintenance de la version mineure spécifiée et va activer les extensions que nous avons spécifiées dans les paramètres de l'action (with > extensions). Cette action est très complète, je vous invite à lire la documentation, on peut même utiliser Blackfire !

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run shivammathur/setup-php@v2
/bin/bash /opt/hostedtoolcache/linux.sh 7.4 /home/runner/work/_actions/shivammathur/setup-php/v2/dist

==> Setup PHP
✓ PHP Switched to PHP 7.4.4

==> Setup Tools
✓ composer Added

==> Setup Extensions
✓ mbstring Enabled
✓ xml Enabled
✓ ctype Enabled
✓ iconv Enabled
✓ intl Enabled
✓ pdo_sqlite Enabled
✓ dom Enabled
✓ filter Enabled
✓ gd Enabled
✓ iconv Enabled
✓ json Enabled
✓ mbstring Enabled
✓ pdo Enabled

» Démarrer Redis avec zhulik/redis-action

Cette étape va lancer le conteneur Docker que nous avons construit au préalable grâce à l'action zhulik/redis-action.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run zhulik/redis-action@1.1.0
/usr/bin/docker run --name e87b52a634b55d4bea4f1a995d572615c8eea1_5d7367 --label e87b52
--workdir /github/workspace --rm -e ES_HTTP_PORT -e INPUT_REDIS_VERSION -e INPUT_NUMBER_OF_DATABASES
-e HOME -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
-e GITHUB_ACTOR -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
-e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e RUNNER_OS -e RUNNER_TOOL_CACHE
-e RUNNER_TEMP -e RUNNER_WORKSPACE -e ACTIONS_RUNTIME_URL -e ACTIONS_RUNTIME_TOKEN
-e GITHUB_ACTIONS=true --network github_network_218d01d494464f389e98156544786390
-v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home"
-v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -
v "/home/runner/work/strangebuzz.com/strangebuzz.com":"/github/workspace" e87b52:a634b55d4bea4f1a995d572615c8eea1
Unable to find image 'redis:5' locally
5: Pulling from library/redis
68ced04f60ab: Already exists
7ecc253967df: Pulling fs layer
76feb725b7e3: Waiting
75797de34ea7: Verifying Checksum
75797de34ea7: Download complete
765957bf98d4: Pull complete
Digest: sha256:ddf831632db1a51716aa9c2e9b6a52f5035fc6fa98a8a6708f6e83033a49508d
Status: Downloaded newer image for redis:5
9e01d93b3b8d465e1ae8208454fc0193f93dad224750a4ad0ee002d5e336e022

» Valider les fichiers composer.json et composer.lock

Maintenant, nous allons démarrer tout ce qui est relatif à PHP et Composer. La première chose à faire est de s'assurer que le fichier composer.lock est bien synchronisé avec composer.json.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run composer validate
 ./composer.json is valid

» Récupérer le répertoire du cache Composer & cacher les dépendances

Les deux étapes suivantes ne sont pas quelque chose que nous avons à faire en local puisque c'est déjà géré par Composer. Mais comme nous créons le runner de zéro, il n'y a pas de cache Composer existant. C'est le but de ces deux étapes. La première va calculer le nom de répertoire du cache et la deuxième va cacher les dépendances si besoin.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run echo "::set-output name=dir::$(composer config cache-files-dir)"
Run actions/cache@v1
Cache Size: ~33 MB (34280929 B)
/bin/tar -xz -f /home/runner/work/_temp/c575859b-081d-44fc-9467-3b9688b76b7c/cache.tgz -C /home/runner/.composer/cache/files
Cache restored from key: Linux-composer-472b10dc8f0c399944d4bbea30b2ac3699a936a5bbd2a87a1ec4fcbfe3845039

» Installer les dépendances Composer

Maintenant nous pouvons installer des dépendances Composer comme nous avons l'habitude de le faire. Veuillez noter que j'utilise directement des cibles de mon Makefile afin d'utiliser les mêmes commandes et arguments. Vous pouvez trouvez mon fichier Makefile complet dans ce snippet.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run make install
php composer.phar install --no-progress --no-suggest --prefer-dist --optimize-autoloader
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 164 installs, 0 updates, 0 removals
  - Installing ocramius/package-versions (1.4.2): Loading from cache
  - Installing ... (): Loading from cache
  - Installing symfony/phpunit-bridge (v5.0.6): Loading from cache
Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.
Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
Package guzzlehttp/streams is abandoned, you should avoid using it. No replacement was suggested.
Package guzzlehttp/ringphp is abandoned, you should avoid using it. No replacement was suggested.
Generating optimized autoload files
Deprecation Notice: Class EasyRdf_Serialiser_JsonLd located in ./vendor/easyrdf/easyrdf/lib/EasyRdf/Serialiser/JsonLd_real.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///home/runner/work/strangebuzz.com/strangebuzz.com/composer.phar/src/Composer/Autoload/ClassMapGenerator.php:185
Deprecation Notice: Class EasyRdf_Parser_JsonLd located in ./vendor/easyrdf/easyrdf/lib/EasyRdf/Parser/JsonLdImplementation.php does not comply with psr-0 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///home/runner/work/strangebuzz.com/strangebuzz.com/composer.phar/src/Composer/Autoload/ClassMapGenerator.php:185
Deprecation Notice: Class Doctrine\Bundle\FixturesBundle\Tests\IntegrationTest\IntegrationTest located in ./vendor/doctrine/doctrine-fixtures-bundle/Tests/IntegrationTest.php does not comply with psr-4 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///home/runner/work/strangebuzz.com/strangebuzz.com/composer.phar/src/Composer/Autoload/ClassMapGenerator.php:185
Deprecation Notice: Class Doctrine\Bundle\FixturesBundle\Tests\IntegrationTest\IntegrationTestKernel located in ./vendor/doctrine/doctrine-fixtures-bundle/Tests/IntegrationTest.php does not comply with psr-4 autoloading standard. It will not autoload anymore in Composer v2.0. in phar:///home/runner/work/strangebuzz.com/strangebuzz.com/composer.phar/src/Composer/Autoload/ClassMapGenerator.php:185
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class

» Vérification des prérequis Symfony

Les paquets ont été installés par Composer. Mais est-ce que machine hôte a les prérequis pour pouvoir exécuter notre application Symfony ? Vérifions cela à l'aide de la commande requirements-checker.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run vendor/bin/requirements-checker

Symfony Requirements Checker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> PHP is using the following php.ini file:
/etc/php/7.4/cli/php.ini

> Checking Symfony requirements:
.....................................

                                                                                                                        
 [OK]                                                                                                                   
 Your system is ready to run Symfony project                                                                            
                                                                                                                        

Note  The command console could use a different php.ini file
~~~~  than the one used with your web server. To be on the
      safe side, please check the requirements from your web
      server using the public/check.php script.

» Vérification de la console Symfony

Parfait, le worker satisfait aux prérequis Symfony 5. Testons notre application désormais. Tout d'abord nous allons exécuter la console Symfony. Si elle ne fonctionne pas, il n'y a aucun moyen pour que les tests unitaires ou fonctionnels puissent s'exécuter sans rencontrer de problème. Tout d'abord nous exécutons la console avec uniquement le paramètre -V, cela va nous retourner le numéro de version de Symfony. Puis, nous exécutons la commande du projet strangebuzz:version qui retourne le numéro de version de l'application.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run php bin/console -V
Symfony 5.0.7 (env: dev, debug: true)

Run php bin/console strangebuzz:version

 ! [NOTE] strangebuzz 2.0.1                                                                                             
                                                                                                                        
 [OK]  -> DONE!                                                                                                         
                                                                                                                        

» Vérification des coding standards (php_codesniffer + PHPStan)

Avant de lancer les tests, vérifions les coding standards. Cela va lancer les analyses php_codesniffer et PHPStan. J'ai mis cette étape ici car je voulais avoir les tests en tout dernier.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run make cs
./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcs.xml -n -p src/
............................................................  60 / 101 (59%)
.........................................                    101 / 101 (100%)


Time: 2.43 secs; Memory: 16MB

./vendor/bin/phpstan analyse -l max --memory-limit 1G -c phpstan.neon src/
   0/101 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░]   0%
  40/101 [▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░]  39%
  80/101 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░]  79%
 101/101 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

                                                                                                                        
 [OK] No errors                                                                                                         
                                                                                                                        

» Chargement des fixtures Doctrine et création des index Elasticsearch

Pour pouvoir lancer les tests, nous devons charger les fixtures Doctrine dans la base de données MySQL et alimenter les index Elasticsearch.

Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Run make load-fixtures

php bin/console doctrine:cache:clear-metadata

 // Clearing all Metadata cache entries

                                                                                                                        
 [OK] Successfully deleted cache entries.                                                                               
                                                                                                                        

php bin/console doctrine:database:create --if-not-exists

Created database `strangebuzz` for connection named default

php bin/console doctrine:schema:drop --force

 Dropping database schema...

                                                                                                                        
 [OK] Database schema dropped successfully!                                                                             
                                                                                                                        

php bin/console doctrine:schema:create


 !                                                                                                                      
 ! [CAUTION] This operation should not be executed in a production environment!                                         
 !                                                                                                                      

 Creating database schema...

                                                                                                                        
 [OK] Database schema created successfully!                                                                             
                                                                                                                        

php bin/console doctrine:schema:validate

Mapping
-------

 [OK] The mapping files are correct.

Database
--------

                                                                                                                        
 [OK] The database schema is in sync with the mapping files.                                                            
                                                                                                                        

php bin/console doctrine:fixtures:load -n

   > purging database
   > loading App\DataFixtures\LoadArticleTypeData
   > loading App\DataFixtures\LoadImageObjectData
   > loading App\DataFixtures\LoadOrganizationData
   > loading App\DataFixtures\LoadArticleData

php bin/console fos:elastica:reset

Resetting app
Resetting suggest

php bin/console fos:elastica:populate --index=app

Resetting app
  0/79 [>---------------------------]   0%
 79/79 [============================] 100%
Populating app/articles
Refreshing app

php bin/console strangebuzz:populate
Populate the "suggest" Elasticsearch index
 -> TODO: 2942 -> DONE: 2942, "fr" keywords indexed.
 -> TODO: 2046 -> DONE: 2046, "en" keywords indexed.

» Lancer les tests unitaires et fonctionnels

Les données sont chargées. Maintenant, lançons tous les tests. C'est l'étape finale qui va décider si notre build est en succès ou pas. Avant de lancer les tests, je copie un fichier de configuration spécifique pour l'environnement de CI.

Run cp phpunit.xml.ci phpunit.xml
./vendor/bin/phpunit --testsuite=main --stop-on-failure
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

Testing
...............................................................  63 / 235 ( 26%)
............................................................... 126 / 235 ( 53%)
............................................................... 189 / 235 ( 80%)
..............................................                  235 / 235 (100%)

Time: 19.74 seconds, Memory: 98.25 MB

OK (235 tests, 346 assertions)

Victoire ! 🎉 C'était la dernière étape de la build. Tous les tests unitaires et fonctionnels sont verts ✅. Nous pouvons livrer le code en production sereinement.

• Arrêt du job

Nous en avons fini avec les étapes que nous avons définies. Maintenant il reste quatre étapes internes à Github qui vont terminer le job proprement. Les voici, j'ai agrégé l'ensemble des logs de ces quatre étapes. La dernière consiste à détruire les différents conteneurs Docker qui ont été créés durant le processus.

  • Post cache des dépendances Composer
  • Post checkout
  • Arrêt des conteneurs
  • Terminer le job
Cliquez ici pour voir / cacher la sortie de cette étape ✅.
Post job cleanup.
Cache hit occurred on the primary key Linux-composer-472b10dc8f0c399944d4bbea30b2ac3699a936a5bbd2a87a1ec4fcbfe3845039, not saving cache.
Post job cleanup.
[command]/usr/bin/git version
git version 2.25.1
[command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader
http.https://github.com/.extraheader
[command]/usr/bin/git config --local --unset-all http.https://github.com/.extraheader
Stop and remove container: 17a0515ca90e4d00923b6ed3b6f2e9f0_mysql57_58c726
##[command]/usr/bin/docker rm --force c4d2e8de1f3465c60085624ea5efb82e9e0a124a5bd5a8460097fbc623c62226
c4d2e8de1f3465c60085624ea5efb82e9e0a124a5bd5a8460097fbc623c62226
Stop and remove container: 93aca059f6194ee38a764314b1f45fb7_elasticsearch686_1e39f8
##[command]/usr/bin/docker rm --force e96226707f7050abcb10c740530990ab4eef0f25ff96261777c6e0eea9159c53
e96226707f7050abcb10c740530990ab4eef0f25ff96261777c6e0eea9159c53
Remove container network: github_network_218d01d494464f389e98156544786390
##[command]/usr/bin/docker network rm github_network_218d01d494464f389e98156544786390
github_network_218d01d494464f389e98156544786390
Cleaning up orphan processes

Et voici à quoi ça ressemble quand tout fonctionne sans problème. Motivant de voir autant de "vert" ✅ , n'est-ce pas ? 😁

Toutes les actions GitHub sont en succès !

Et bien sûr, le check global associé à chaque commit:

Le check global par commit

Conclusion

J'ai découvert les actions GitHub récemment; je dois dire que j'en suis très satisfait. C'est maintenant mon principal fournisseur CI/CD comme tous mes projets sont sur Github. Bien sûr, il y a beaucoup de choses à ajouter ou améliorer. Mais ce workflow fait le travail. Il assure que tous les tests passent et que le projet est prêt à être migré vers PHP 7.4 sans avoir à changer la moindre ligne de code.

Et voilà ! J'espère que vous avez aimé. Découvrez d'autres informations en rapport à cet article avec les liens ci-dessous. Comme toujours, retours, likes et retweets sont les bienvenus. (voir la boîte ci-dessous) À la revoyure ! COil. 😊

  Lire la doc  Plus sur le web  Plus sur Stackoverflow

Ils m'ont donné leurs retours et m'ont aidé à corriger des erreurs et typos dans cet article, un grand merci à : Laurent Q, jmsche. 👍


A vous de jouer !

Ces articles vous ont été utiles ? Vous pouvez m'aider à votre tour de plusieurs manières : (cf le tweet à droite pour me contacter )

  • Me remonter des erreurs ou typos.
  • Me remonter des choses qui pourraient être améliorées.
  • Aimez et retweetez !
  • Suivez moi sur Twitter
  • Inscrivez-vous au flux RSS.
  • Cliquez sur les boutons Plus sur Stackoverflow pour me faire gagner des badges "annonceur" 🏅.

Merci d'avoir tenu jusque ici et à très bientôt sur Strangebuzz ! 😉

COil