GitHub Actions


#GitHub Actions

#Introduction

The PrestaFlow GitHub Action runs your PrestaFlow test suites inside a GitHub workflow. It wraps the PHP library (composer run prestaflow:json:file), optionally provisions a full PrestaShop Flashlight instance on the runner so you can test a module or a theme against a real shop without any prior setup, uploads the results to the PrestaFlow API, publishes a GitHub artifact with the raw report and the failure screenshots, and posts (or updates) a summary comment on the pull request. It is a drop-in replacement for the previous shell-based workflow and can run in almost any CI matrix.

#Requirements

  • PHP libraryprestaflow/php-library ^1.5.2 or newer. Earlier versions read the runtime configuration only from $_ENV, which is not populated from the process environment on most CI setups; 1.5.2 introduced the Env helper that also reads getenv(), so the environment variables exported by the action (PRESTAFLOW_FO_URL, PRESTAFLOW_PS_VERSION, PRESTAFLOW_SUITES) are picked up transparently.
  • PHP 8.2 or newer on the runner.
  • Docker, only when flashlight: true — the runner must be ubuntu-latest (or another Linux runner with a working Docker daemon).

#Quick start

The minimal workflow below runs the action on every push and pull request. It covers 90% of use cases: check out the code, install PHP + Composer dependencies, then hand over to the action.

Copied!
1name: PrestaFlow
2 
3on:
4 push:
5 branches: [main]
6 pull_request:
7 branches: [main]
8 
9jobs:
10 tests:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14 
15 - name: Setup PHP
16 uses: shivammathur/setup-php@v2
17 with:
18 php-version: '8.2'
19 extensions: gd
20 tools: composer:v2
21 
22 - name: Install dependencies
23 run: composer install --prefer-dist --no-progress
24 
25 - name: Run PrestaFlow tests
26 uses: PrestaFlow/github-action@v2
27 with:
28 token: ${{ secrets.PRESTAFLOW_TOKEN }}
29 projectId: '42'

Store your PrestaFlow API token as a repository secret named PRESTAFLOW_TOKEN, replace 42 with your actual project id, and the workflow is ready.

#Migration from v1

If you were using PrestaFlow/github-action@v1, migrating is essentially a version bump: the two required inputs (token and projectId) still work the same way, and the action still runs composer run prestaflow:json:file by default. Your existing workflow should keep passing.

What v2 brings on top:

  • Flashlight provisioning — spin up a real PrestaShop instance in the runner with a single flashlight: true input.
  • Suite filtering — pick which suites to run via the suites CSV input, ideal for matrix parallelization.
  • PR comment — an auto-updating comment summarising pass/fail counts and the first failing tests, kept in sync across pushes on the same pull request.
  • GitHub artifactresults.json and failure screenshots are uploaded as a workflow artifact so they can be downloaded or consumed by downstream jobs.
  • Richer outputsid, report-url, passed, failed, skipped, total, duration-ms, status are exposed as step outputs.
  • TypeScript rewrite — the action is now a compiled JavaScript action, no container pull, faster cold starts.

The moving @v2 tag currently points at v2.1.0. Pin a specific patch (@v2.1.0) if you want reproducible upgrades; use @v2 for automatic bugfix and minor pickups.

#Inputs reference

Input Required Default Description
token yes PrestaFlow API token used to upload results. Store as a secret.
projectId no Numerical PrestaFlow project id to associate the run with.
execute no true Run composer run prestaflow:json:file before uploading. Set to false if you already produced the results file.
suites no (empty — all suites) Comma-separated list of suite names to run, e.g. BackOffice,FrontOffice.
flashlight no false Start a PrestaShop Flashlight Docker instance before running the tests.
ps-version no latest PrestaShop version tag used when flashlight: true.
flashlight-mount no auto Where to mount the workspace inside the container: auto (detect from composer.json), root (custom PrestaShop, /var/www/html), modules, or themes.
flashlight-init-scripts no (empty — none) Directory (absolute or relative to workspace) mounted read-only at /tmp/init-scripts; Flashlight runs its executable shebang scripts at boot.
pr-comment no true on pull_request, else false Post (or update) a summary comment on the pull request.
github-token no ${{ github.token }} Token used to post the PR comment. Provide a PAT if the default token lacks the required scope.
upload-artifacts no true Upload results.json and failure screenshots as a workflow artifact.

#Outputs reference

Output Type Description
id string Unique run id assigned by the PrestaFlow API.
report-url string URL to the full report on prestaflow.io.
passed number Number of tests that passed.
failed number Number of tests that failed.
skipped number Number of tests that were skipped.
total number Total number of tests executed.
duration-ms number Total run duration in milliseconds.
status success | failure Overall status of the run.

A downstream step can consume these outputs directly. For example, to fail the job as soon as at least one test regresses:

Copied!
1name: PrestaFlow
2 
3on:
4 pull_request:
5 
6jobs:
7 tests:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 
12 - name: Setup PHP
13 uses: shivammathur/setup-php@v2
14 with:
15 php-version: '8.2'
16 extensions: gd
17 tools: composer:v2
18 
19 - name: Install dependencies
20 run: composer install --prefer-dist --no-progress
21 
22 - name: Run PrestaFlow tests
23 id: prestaflow
24 uses: PrestaFlow/github-action@v2
25 with:
26 token: ${{ secrets.PRESTAFLOW_TOKEN }}
27 projectId: '42'
28 
29 - name: Fail fast on regressions
30 if: steps.prestaflow.outputs.failed != '0'
31 run: exit 1

#Guide: Flashlight

Flashlight provisions a functional PrestaShop instance inside the runner in seconds, saving you from installing PHP, MySQL and the shop by hand. Enable it by passing flashlight: true; the action pulls the prestashop/prestashop-flashlight image, starts it, waits for the shop to be reachable, and points the tests at it.

Copied!
1name: PrestaFlow with Flashlight
2 
3on:
4 pull_request:
5 
6jobs:
7 tests:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 
12 - name: Setup PHP
13 uses: shivammathur/setup-php@v2
14 with:
15 php-version: '8.2'
16 extensions: gd
17 tools: composer:v2
18 
19 - name: Install dependencies
20 run: composer install --prefer-dist --no-progress
21 
22 - name: Run PrestaFlow tests against Flashlight
23 uses: PrestaFlow/github-action@v2
24 with:
25 token: ${{ secrets.PRESTAFLOW_TOKEN }}
26 projectId: '42'
27 flashlight: true
28 ps-version: '9.0.0'

Because Flashlight requires Docker, the workflow must run on ubuntu-latest (or another Linux runner where Docker is available). macOS and Windows runners do not ship with Docker and the action will fail with a clear error.

#What the action provisions

Flashlight does not embed a database, so the action writes a fully-managed docker-compose.yml on the fly with:

  • prestashop — the prestashop/prestashop-flashlight:<ps-version> image, bound to a free host port (starting at 8000, falling back to 8001/8002 if occupied). Waits for the MySQL sidecar's health check before starting.
  • mysql — a mariadb:lts sidecar with the credentials Flashlight expects. Pulled and health-checked automatically; no user configuration needed.

Cold-boot on a clean GitHub-hosted runner takes roughly 90–150 seconds (image pull, MySQL health check, PrestaShop first-run install). The readiness poll gives up after 240 seconds; if it times out, the Flashlight container logs are captured into a collapsible group in the workflow output for triage.

When the container is ready the action exports two environment variables the PHP library reads to target the running shop:

  • PRESTAFLOW_FO_URL — the front-office URL (e.g. http://localhost:8000/). The back-office is derived from it as ${PRESTAFLOW_FO_URL}admin-dev/.
  • PRESTAFLOW_PS_VERSION — the value passed via ps-version, so the library loads the version-specific page namespace (Pages\v8, Pages\v9, …).

#Mount detection

By default (flashlight-mount: auto), the action inspects the repository's composer.json to decide where to mount your working directory inside the container:

  • type: prestashop-module — mounted under /var/www/html/modules/<module-name> (using the name from composer.json after stripping the vendor prefix).
  • type: prestashop-theme — mounted under /var/www/html/themes/<theme-name>.
  • Missing composer.json, missing type, or an unknown type — falls back to /var/www/html/modules/<repo-basename> and logs a warning so you can spot it.

The resolved mount point is printed in the workflow logs.

#Overriding the mount location

Set flashlight-mount explicitly when the automatic detection is not what you want:

  • root — mounts the workspace at /var/www/html. Use this when the repository is itself a custom PrestaShop build (a fork, a full app repo, a shop-under-development). Follows the develop-prestashop reference example shipped with Flashlight.
  • modules / themes — force the corresponding subdirectory even when composer.json says otherwise. Handy for repositories where the type field is missing or incorrect and you would rather set it once in the workflow than fix the manifest.
Copied!
1- name: Run PrestaFlow tests against a custom PrestaShop
2 uses: PrestaFlow/github-action@v2
3 with:
4 token: ${{ secrets.PRESTAFLOW_TOKEN }}
5 projectId: '42'
6 flashlight: true
7 ps-version: '9.0.0'
8 flashlight-mount: root

Compatibility notes

Mounting a custom PrestaShop at /var/www/html overrides Flashlight's baked-in codebase, but three things still come from the Flashlight image itself:

  • PHP runtime — the image ships a specific PHP version tuned for the baked-in PrestaShop (PHP 7.4 for 1.7.8, PHP 8.1 for 8.x, PHP 8.3 for 9.x). A code mount that expects a different PHP boots but risks fatals or deprecations from unmatched extensions and syntax.
  • nginx configuration — rewrite rules differ across PrestaShop majors (admin-dev/ handling, module routes, etc.). A mismatch produces "clean" 404s on paths the mounted code expects to work.
  • MySQL dump — Flashlight restores a dump matching its baked-in version. Your mounted code will hit the shop with the wrong schema — missing columns, wrong tables, install checks failing on boot.

Rule of thumb: set ps-version to at least the same major.minor as the code you are mounting. 9.0.0 for a shop on 9.0.x, 8.2.6 for an 8.2.x shop, etc. Mixing majors is not supported by Flashlight and rarely works.

Older or unusual versions (PrestaShop 1.6 / 1.7, forks with heavy overrides): Docker Hub only publishes images for 8.x and 9.x. The PrestaShop Flashlight repository declares support for older majors in prestashop-versions.json, but you need to build the image yourself from source. For heavily customised PrestaShop 1.7 shops, a workflow that targets a running preprod (via PRESTAFLOW_FO_URL in the library's .env, no Flashlight) is often simpler than fighting the image build.

Custom database state: even with a matching major, you may want to seed the shop with your own SQL dump (specific data, an existing configuration). Use flashlight-init-scripts and drop a .sh that runs mysql < your-dump.sql before nginx starts.

#Init scripts (advanced)

Flashlight runs every executable file it finds in /tmp/init-scripts at boot, alphabetically, after the MySQL dump is restored and before nginx starts. This is the hook to seed additional data, patch configuration, install extra dependencies, or wire in an internal module before the tests run.

Point flashlight-init-scripts at a directory in your repository (path is absolute, or relative to the workspace):

Copied!
1- name: Run PrestaFlow tests with init scripts
2 uses: PrestaFlow/github-action@v2
3 with:
4 token: ${{ secrets.PRESTAFLOW_TOKEN }}
5 projectId: '42'
6 flashlight: true
7 ps-version: '9.0.0'
8 flashlight-init-scripts: flashlight/init-scripts

Each script must be executable (chmod +x) and start with a shebang (#!/bin/sh, #!/usr/bin/env bash, etc.) — Flashlight silently skips files that do not satisfy both conditions. Prefix filenames with a two-digit index (01-seed-products.sh, 02-configure-cache.sh, …) to control the order.

The action validates the path at parse time and fails fast with a clear message if it does not exist or is not a directory.

#Guide: Filtering suites

Pass a comma-separated list of suite names via suites to run only a subset:

Copied!
1name: PrestaFlow — BackOffice + FrontOffice only
2 
3on:
4 pull_request:
5 
6jobs:
7 tests:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 
12 - name: Setup PHP
13 uses: shivammathur/setup-php@v2
14 with:
15 php-version: '8.2'
16 extensions: gd
17 tools: composer:v2
18 
19 - name: Install dependencies
20 run: composer install --prefer-dist --no-progress
21 
22 - name: Run selected suites
23 uses: PrestaFlow/github-action@v2
24 with:
25 token: ${{ secrets.PRESTAFLOW_TOKEN }}
26 projectId: '42'
27 suites: BackOffice,FrontOffice

For heavier test bases, a strategy.matrix gives you one runner per suite so the wall-clock time is bounded by the slowest suite:

Copied!
1name: PrestaFlow — parallel suites
2 
3on:
4 pull_request:
5 
6jobs:
7 tests:
8 runs-on: ubuntu-latest
9 strategy:
10 fail-fast: false
11 matrix:
12 suite: [BackOffice, FrontOffice, Api]
13 steps:
14 - uses: actions/checkout@v4
15 
16 - name: Setup PHP
17 uses: shivammathur/setup-php@v2
18 with:
19 php-version: '8.2'
20 extensions: gd
21 tools: composer:v2
22 
23 - name: Install dependencies
24 run: composer install --prefer-dist --no-progress
25 
26 - name: Run ${{ matrix.suite }}
27 uses: PrestaFlow/github-action@v2
28 with:
29 token: ${{ secrets.PRESTAFLOW_TOKEN }}
30 projectId: '42'
31 suites: ${{ matrix.suite }}

#Guide: PR comment

On pull_request events the action posts a summary comment listing the pass/fail/skipped counts, the run duration and a link to the full report on prestaflow.io. The comment is tagged with a hidden marker (<!-- prestaflow-report -->) so subsequent pushes on the same pull request update the existing comment in place rather than appending a new one — the PR timeline stays clean.

Example of a PrestaFlow test report comment on a pull request, showing 4 passed, 3 failed, 0 skipped tests in 3m 08s against PrestaShop 9.0.0, with the three failure descriptions and file:line locations expanded.

If the API response does not include a report URL (for example on a private PrestaFlow instance), the "View full report" link is omitted entirely rather than rendered as a broken link.

For the comment to be posted, the workflow must grant write access to pull requests:

Copied!
1name: PrestaFlow
2 
3on:
4 pull_request:
5 
6permissions:
7 contents: read
8 pull-requests: write
9 
10jobs:
11 tests:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v4
15 
16 - name: Setup PHP
17 uses: shivammathur/setup-php@v2
18 with:
19 php-version: '8.2'
20 extensions: gd
21 tools: composer:v2
22 
23 - name: Install dependencies
24 run: composer install --prefer-dist --no-progress
25 
26 - name: Run PrestaFlow tests
27 uses: PrestaFlow/github-action@v2
28 with:
29 token: ${{ secrets.PRESTAFLOW_TOKEN }}
30 projectId: '42'

When at least one test fails, the comment lists up to 10 failing tests with their source location (file and line, if the report exposes it) and error message so the reviewer can triage from the PR without opening the full report. Beyond ten failures, a "…and N more" trailer links to the complete report on prestaflow.io.

To opt out (for example on a private mirror where you do not want a bot comment), set pr-comment: false.

#Guide: GitHub artifacts

By default the action uploads a workflow artifact named prestaflow-report-<run-id>-<attempt> containing:

  • results.json — the raw JSON report produced by the PHP library;
  • screenshots/ — the failure screenshots generated by the browser, when any.

The artifact makes it trivial to inspect a failing run locally, or to hand the report to another job in the same workflow:

Copied!
1name: PrestaFlow with downstream analysis
2 
3on:
4 pull_request:
5 
6jobs:
7 tests:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v4
11 
12 - name: Setup PHP
13 uses: shivammathur/setup-php@v2
14 with:
15 php-version: '8.2'
16 extensions: gd
17 tools: composer:v2
18 
19 - name: Install dependencies
20 run: composer install --prefer-dist --no-progress
21 
22 - name: Run PrestaFlow tests
23 uses: PrestaFlow/github-action@v2
24 with:
25 token: ${{ secrets.PRESTAFLOW_TOKEN }}
26 projectId: '42'
27 
28 analyse:
29 needs: tests
30 runs-on: ubuntu-latest
31 steps:
32 - uses: actions/download-artifact@v4
33 with:
34 name: prestaflow-report-${{ github.run_id }}-${{ github.run_attempt }}
35 
36 - name: Inspect results.json
37 run: cat results.json | jq '.summary'

To skip the upload entirely, set upload-artifacts: false.

#Troubleshooting

  • Docker missing — the action fails with flashlight: true requires Docker (use ubuntu-latest runner). This happens when flashlight: true is combined with a runner that has no Docker daemon. Fix: use runs-on: ubuntu-latest (Docker is not available on the macos-* and windows-* runners).

  • Port 8000 already in use — Flashlight tries to bind to host port 8000 first, and automatically falls back to 8001 then 8002. If all three are already taken (typical of self-hosted runners with multiple concurrent jobs), the action fails with a clear message. Free one of these ports or run the job on a fresh runner.

  • Invalid token / 401 — the upload step reports a 401 when the PrestaFlow API rejects the token. Verify that secrets.PRESTAFLOW_TOKEN is set for the repository (Settings → Secrets and variables → Actions), that its value matches the token displayed on your PrestaFlow account, and that the token has access to the target projectId.

  • PR comment not posted (403 / permission) — GitHub blocks the comment API when the workflow token lacks the right scope. Add permissions: pull-requests: write at the workflow or job level, or pass a custom github-token (a PAT or a GitHub App token) with sufficient scope through the github-token input.

  • Class "…\\Pages\\v8\\…\\Page" not found — with flashlight: true and ps-version: '9.0.0', the library still tried to load v8-namespaced pages. Root cause: the library reads its version selector from an environment variable, and until prestaflow/php-library@1.5.2 that lookup only saw $_ENV, not the process environment the action exports. Bump your dependency to ^1.5.2 and re-run.

  • PR comment shows "0 tests passed in 0s" — the composer script crashed before writing prestaflow/results.json. The action can only report what the library produced. Open the workflow step preceding the action's output to find the real error (missing class, syntax error in a test file, browser crash, etc.). When there is no results.json the action skips the API upload silently and posts the zero-state comment so the PR still reflects that something went wrong.

  • Flashlight not ready after 240000ms — the shop container failed to respond within four minutes. The action captures the Flashlight logs into a collapsed group in the workflow output; expand it to see whether MySQL failed to become healthy, the PS installer crashed, or a firewall rule prevented the readiness probe from reaching the container.

  • flashlight-mount: root + SQL errors / missing tables / 500 on boot — the code you mounted at /var/www/html expects a different database schema than the one Flashlight restored. Check that ps-version matches your mounted code at least at the major.minor level. If you are mounting a heavily customised shop that ships its own SQL dump, restore it via flashlight-init-scripts — the dump runs after Flashlight's own restore, so it overrides it. See the compatibility notes in the Flashlight guide.

  • flashlight-mount: root + flashlight: true + no image published for your PrestaShop version — Docker Hub currently only publishes Flashlight images for PrestaShop 8.x and 9.x. Support for older majors is declared in the prestashop-versions.json manifest but you need to build the image yourself. For shops on 1.6 or 1.7, targeting a running preprod via PRESTAFLOW_FO_URL (no Flashlight, no mount) is usually the pragmatic path.