Retour au blog
TestsPrestaFlow

PrestaFlow en CI hors GitHub Actions : GitLab, Bitbucket, CircleCI, Jenkins

PrestaEdit
PrestaFlow en CI hors GitHub Actions : GitLab, Bitbucket, CircleCI, Jenkins

Décor

L’article 2 de la série a posé deux niveaux de CI :

  • Niveau 1 — la CLI PrestaFlow dans un workflow, sans compte prestaflow.io, avec Docker pour lancer Flashlight à la main.
  • Niveau 2 — l’intégration officielle qui gère Flashlight, la matrice, le commentaire PR/MR, et la synchro plateforme (report URL, historique, régressions visuelles).

Au moment où l’article 2 est paru, le niveau 2 n’existait que pour GitHub Actions. Ce n’est plus le cas : trois nouvelles intégrations officielles sont disponibles, chacune avec ses propres inputs et sa mécanique.

PlateformeNiveau 2 officielRéférence
GitHubActionPrestaFlow/github-action@v2
GitLabCI/CD Componentgitlab.com/prestaflow/ci/prestaflow@v0.1.0
BitbucketPipe Dockerprestaflow/pipe-push:1.0.0
CircleCIOrbprestaflow/prestaflow@1.0.0
Jenkins— (niveau 1 uniquement)pipeline scripté

Cette annexe donne les gabarits pour ces quatre plateformes, avec pour chacune le niveau 1 (autonome, sans compte) et le niveau 2 (intégration officielle) quand il existe.

Ce qui doit tourner, quel que soit le CI

Le workflow niveau 1 fait cinq choses, dans l’ordre :

  1. git clone du projet (implicite dans tout CI)
  2. Installer PHP (typiquement 8.2) et Composer
  3. composer install
  4. Démarrer Flashlight en arrière-plan, attendre qu’il réponde en HTTP
  5. Lancer ./vendor/bin/prestaflow run tests/prestaflow avec les env vars pointant sur http://localhost/

Toute la variation d’un CI à l’autre au niveau 1 concerne uniquement la syntaxe pour exprimer ces cinq étapes, plus les mécanismes de secrets et d’artifacts. Le niveau 2 remplace ces étapes par un appel à l’intégration officielle, qui les regroupe et ajoute la remontée vers la plateforme.

GitLab CI

Niveau 1 — CLI seule

Créez .gitlab-ci.yml à la racine :

stages:
  - test

e2e:
  stage: test
  image: php:8.2-cli
  services:
    - name: prestashop/prestashop-flashlight:8.1.7
      alias: prestashop
  variables:
    PRESTAFLOW_PS_VERSION: "8.1.7"
    PRESTAFLOW_LOCALE: fr
    PRESTAFLOW_FO_URL: http://prestashop/
    PRESTAFLOW_BO_URL: http://prestashop/admin-dev/
    PRESTAFLOW_BO_EMAIL: admin@prestashop.com
    PRESTAFLOW_BO_PASSWD: prestashop
    PRESTAFLOW_HEADLESS: "true"
  before_script:
    - apt-get update && apt-get install -y curl chromium libgd-dev unzip git
    - docker-php-ext-install gd
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
    - composer install --prefer-dist --no-progress
    - for i in $(seq 1 60); do curl -sf http://prestashop/ > /dev/null && break; sleep 2; done
  script:
    - ./vendor/bin/prestaflow run tests/prestaflow
  artifacts:
    when: on_failure
    paths:
      - tests/prestaflow/reports/
      - prestaflow/screens/errors/
    expire_in: 1 week

Trois particularités GitLab :

  • services: permet de lancer un conteneur en side-car, accessible par son alias comme hostname (ici prestashop). Plus propre que le docker run -d manuel de GitHub Actions.
  • image: de niveau job = le conteneur qui exécute le script. On prend php:8.2-cli officiel et on y ajoute Chromium + composer.
  • artifacts: ne s’attache qu’on_failure — même pattern que le if: failure() de GitHub. Le rapport HTML et les captures d’erreur restent téléchargeables 7 jours.

Niveau 2 — CI/CD Component

Depuis la v0.1.0, PrestaFlow expose un component GitLab standard :

include:
  - component: gitlab.com/prestaflow/ci/prestaflow@v0.1.0
    inputs:
      token: $PRESTAFLOW_TOKEN
      project_id: pk_01ABCDEF
      flashlight: "true"
      ps_version: "9.0.0"
      suites: "BackOffice,FrontOffice"
      visual: "true"
      mr_comment: "true"

Les inputs clés : token (variable masquée), project_id (Product Key pk_…), flashlight (bootstrap PS via Docker), ps_version, suites (filtre), visual (baselines + diffs), mr_comment, execute, upload_artifacts.

Deux env vars à configurer côté projet :

  • PRESTAFLOW_TOKEN — variable CI/CD masquée pour l’API.
  • GITLAB_TOKEN — token GitLab avec scope api pour poster les notes MR. Le CI_JOB_TOKEN par défaut ne peut pas commenter les MR, c’est le piège classique.

Le component publie un artifact prestaflow.env (format dotenv) exposant PRESTAFLOW_REPORT_ID, PRESTAFLOW_REPORT_URL, PRESTAFLOW_PASSED/FAILED/SKIPPED/TOTAL, PRESTAFLOW_DURATION_MS, PRESTAFLOW_STATUS. Un job downstream y accède via needs: [{job: prestaflow, artifacts: true}].

Matrice multi-versions PS avec parallel:matrix: :

test-ps:
  parallel:
    matrix:
      - PS_VERSION: ["8.1.7", "9.0.0"]
  variables:
    ps_version: $PS_VERSION

Bitbucket Pipelines

Niveau 1 — CLI seule

Créez bitbucket-pipelines.yml :

image: php:8.2-cli

pipelines:
  default:
    - step:
        name: E2E — PrestaShop 8.1.7
        services:
          - flashlight
        script:
          - apt-get update && apt-get install -y curl chromium libgd-dev unzip git
          - docker-php-ext-install gd
          - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
          - composer install --prefer-dist --no-progress
          - for i in $(seq 1 60); do curl -sf http://localhost/ > /dev/null && break; sleep 2; done
          - export PRESTAFLOW_FO_URL=http://localhost/
          - export PRESTAFLOW_BO_URL=http://localhost/admin-dev/
          - export PRESTAFLOW_BO_EMAIL=admin@prestashop.com
          - export PRESTAFLOW_BO_PASSWD=prestashop
          - export PRESTAFLOW_HEADLESS=true
          - ./vendor/bin/prestaflow run tests/prestaflow
        artifacts:
          - tests/prestaflow/reports/**
          - prestaflow/screens/errors/**

definitions:
  services:
    flashlight:
      image: prestashop/prestashop-flashlight:8.1.7

Deux particularités Bitbucket :

  • La syntaxe services: se déclare dans un bloc definitions: séparé et se référence dans le step: par son nom. Les services partagent le réseau du step, donc on parle à Flashlight via http://localhost/ — pas via un alias.
  • Les artefacts sont toujours produits, il n’existe pas de conditionnel natif on_failure — on paie donc un peu plus de stockage. Alternative : && exit 0 || (tar cf reports.tgz tests/prestaflow/reports/ && exit 1) pour un tar conditionnel dans le script.

Niveau 2 — Pipe officiel

Depuis la 1.0.0, PrestaFlow publie un pipe Docker sur Docker Hub :

image: php:8.3-cli

pipelines:
  pull-requests:
    '**':
      - step:
          name: PrestaFlow
          services: [docker]
          artifacts: [prestaflow.env]
          script:
            - pipe: docker://prestaflow/pipe-push:1.0.0
              variables:
                TOKEN: $PRESTAFLOW_TOKEN
                PROJECT_ID: pk_01ABC...
                FLASHLIGHT: 'true'
                PS_VERSION: '9.0.0'
                BITBUCKET_ACCESS_TOKEN: $PRESTAFLOW_BITBUCKET_TOKEN

      - step:
          name: Notify
          script:
            - . prestaflow.env
            - echo "Report → $PRESTAFLOW_REPORT_URL"

Variables principales : TOKEN, PROJECT_ID, FLASHLIGHT, PS_VERSION, SUITES, VISUAL (défaut true), PR_COMMENT (auto), EXECUTE, FLASHLIGHT_MOUNT (auto/root/modules/themes), BITBUCKET_ACCESS_TOKEN pour les commentaires PR.

Deux points à noter :

  • services: [docker] est obligatoire dès que FLASHLIGHT=true — le pipe monte le sidecar MariaDB et le conteneur PS via le daemon Docker du runner.
  • Commentaires PR idempotents — le pipe insère un marqueur <!-- prestaflow-run:<project-key> --> dans la note, ce qui lui permet de mettre à jour un commentaire existant plutôt que d’en ajouter un à chaque run. Rien à faire côté config.

Le prestaflow.env produit contient les mêmes variables que le component GitLab (PRESTAFLOW_REPORT_URL, PRESTAFLOW_STATUS, etc.) et se source dans un step suivant.

CircleCI

CircleCI a longtemps été le grand absent de cet inventaire. Il a maintenant son orb officiel prestaflow/prestaflow@1.0.0, publié en canal stable (le canal volatile reste dispo pour les fixes non-taggés).

L’orb expose un push all-in-one plus des commandes granulaires (flashlight, run-tests, visual-download, upload, comment-pr, set-outputs, install-deps) qu’on compose soi-même si besoin.

.circleci/config.yml minimal :

version: 2.1
orbs:
  prestaflow: prestaflow/prestaflow@1.0.0
workflows:
  test:
    jobs:
      - prestaflow/test:
          project_id: pk_01ABCDEFGHIJKLMNOPQR10
          flashlight: true
          ps_version: "9.0.0"
          context: prestaflow

Trois particularités CircleCI :

  • Exécuteur machine obligatoire dès qu’on active Flashlight — setup_remote_docker ne permet pas les bind mounts dont Flashlight a besoin. L’orb bascule automatiquement, mais gardez-le en tête pour vos surcoûts crédits.
  • GITHUB_TOKEN ou BITBUCKET_ACCESS_TOKEN à créer à la main — CircleCI n’injecte pas de token VCS par défaut. Sans ça, pas de commentaire PR (mais le run remonte quand même côté plateforme).
  • Outputs via BASH_ENV — les variables (PRESTAFLOW_REPORT_URL, etc.) sont exportées dans BASH_ENV et dans un prestaflow.env artifact, plutôt qu’en outputs de step comme sur GitHub.

Jenkins (déclaratif)

Jenkins n’a pas d’intégration officielle — le niveau 2 y passe par un sh curl vers l’API prestaflow.io depuis un pipeline scripté (voir la fin de l’article). Le niveau 1 reste donc la voie normale.

Créez Jenkinsfile à la racine :

pipeline {
    agent {
        docker {
            image 'php:8.2-cli'
            args '--network host'
        }
    }

    environment {
        PRESTAFLOW_PS_VERSION = '8.1.7'
        PRESTAFLOW_LOCALE = 'fr'
        PRESTAFLOW_FO_URL = 'http://localhost/'
        PRESTAFLOW_BO_URL = 'http://localhost/admin-dev/'
        PRESTAFLOW_BO_EMAIL = 'admin@prestashop.com'
        PRESTAFLOW_BO_PASSWD = credentials('prestashop-admin-passwd')
        PRESTAFLOW_HEADLESS = 'true'
    }

    stages {
        stage('Prepare') {
            steps {
                sh 'apt-get update && apt-get install -y curl chromium libgd-dev unzip git'
                sh 'docker-php-ext-install gd'
                sh 'curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer'
                sh 'composer install --prefer-dist --no-progress'
            }
        }

        stage('Start Flashlight') {
            steps {
                sh 'docker run -d --rm --name ps --network host prestashop/prestashop-flashlight:8.1.7'
                sh 'for i in $(seq 1 60); do curl -sf http://localhost/ && break; sleep 2; done'
            }
        }

        stage('Run PrestaFlow') {
            steps {
                sh './vendor/bin/prestaflow run tests/prestaflow'
            }
        }
    }

    post {
        failure {
            archiveArtifacts artifacts: 'tests/prestaflow/reports/**,prestaflow/screens/errors/**', allowEmptyArchive: true
        }
        always {
            sh 'docker rm -f ps 2>/dev/null || true'
        }
    }
}

Trois particularités Jenkins :

  • Docker-in-Docker requis — l’agent est un conteneur PHP, mais on lance Flashlight via un docker run qui doit passer le socket Docker de l’host. C’est du DinD, à configurer côté Jenkins (mount de /var/run/docker.sock, sinon Cloud plugin type Kubernetes).
  • credentials() — Jenkins Credentials Store fournit les secrets sous forme de variables d’environnement quand on les référence via credentials(...). Plus verbeux mais plus explicite que les secrets GitHub/GitLab.
  • post { always } garantit la stop du conteneur Flashlight même en cas d’échec, évitant les zombies sur le nœud.

Ce qui reste identique partout

Peu importe le CI et le niveau, les mêmes règles s’appliquent :

  • Wait explicite après le boot Flashlight — 30 à 60 secondes. Sans quoi le premier it tombe sur une boutique pas prête, avec une capture d’erreur inutile.
  • Env vars PRESTAFLOW_* — mêmes noms, mêmes rôles, quelle que soit la plateforme. Le code de la lib ne connaît rien du CI qui l’exécute.
  • Artefacts sur échec — le rapport HTML dans tests/prestaflow/reports/, les captures d’erreur dans prestaflow/screens/errors/. Les rendre téléchargeables est essentiel pour debug hors du CI.
  • Exit code non-nul de la CLI = job rouge. Ne pas court-circuiter avec un || true bien intentionné qui rendrait le CI aveugle.

Au niveau 2, les quatre intégrations officielles (Action, Component, Pipe, Orb) exposent les mêmes clés de sortiePRESTAFLOW_REPORT_ID/URL/PASSED/FAILED/SKIPPED/TOTAL/DURATION_MS/STATUS — via le mécanisme natif de leur plateforme (step outputs, dotenv artifact, BASH_ENV). Le contrat côté downstream est stable, ce qui rend les workflows portables d’une plateforme à l’autre.

Le cas Jenkins : niveau 2 fait maison

Sans intégration officielle, deux options si vous êtes sur Jenkins et voulez la synchro plateforme :

  • Rester au niveau 1 — vous avez le CI qui rougit sur les régressions fonctionnelles. Vous n’avez ni le commentaire PR agrégé, ni l’historique côté plateforme, ni les régressions visuelles synchronisées. C’est déjà utile.
  • Faire soi-même le POST vers l’API prestaflow.io — la plateforme expose POST /api/projects/{id}/runs (visible dans l’annexe cloud runs, badge uploaded_via: api). Un sh qui prend le results.json produit par PrestaFlow et le pousse via curl avec le PRESTAFLOW_TOKEN. Le badge api est prévu pour ça — c’est exactement le canal utilisé par les intégrations officielles quand elles remontent leurs résultats.

Ce second cas justifierait à lui seul un article dédié (auth, retries, formatage, artifacts screenshots). Pour l’instant, on note l’option et on renvoie à la doc API.

Notes

Dans la Série Prestaflow — article 5 sur 14