GitHub Actions
On this page
#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 library —
prestaflow/php-library^1.5.2or newer. Earlier versions read the runtime configuration only from$_ENV, which is not populated from the process environment on most CI setups;1.5.2introduced theEnvhelper that also readsgetenv(), so the environment variables exported by the action (PRESTAFLOW_FO_URL,PRESTAFLOW_PS_VERSION,PRESTAFLOW_SUITES) are picked up transparently. - PHP
8.2or newer on the runner. - Docker, only when
flashlight: true— the runner must beubuntu-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.
1name: PrestaFlow 2 3on: 4 push: 5 branches: [main] 6 pull_request: 7 branches: [main] 8 9jobs:10 tests:11 runs-on: ubuntu-latest12 steps:13 - uses: actions/checkout@v414 15 - name: Setup PHP16 uses: shivammathur/setup-php@v217 with:18 php-version: '8.2'19 extensions: gd20 tools: composer:v221 22 - name: Install dependencies23 run: composer install --prefer-dist --no-progress24 25 - name: Run PrestaFlow tests26 uses: PrestaFlow/github-action@v227 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: trueinput. - Suite filtering — pick which suites to run via the
suitesCSV 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 artifact —
results.jsonand failure screenshots are uploaded as a workflow artifact so they can be downloaded or consumed by downstream jobs. - Richer outputs —
id,report-url,passed,failed,skipped,total,duration-ms,statusare 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:
1name: PrestaFlow 2 3on: 4 pull_request: 5 6jobs: 7 tests: 8 runs-on: ubuntu-latest 9 steps:10 - uses: actions/checkout@v411 12 - name: Setup PHP13 uses: shivammathur/setup-php@v214 with:15 php-version: '8.2'16 extensions: gd17 tools: composer:v218 19 - name: Install dependencies20 run: composer install --prefer-dist --no-progress21 22 - name: Run PrestaFlow tests23 id: prestaflow24 uses: PrestaFlow/github-action@v225 with:26 token: ${{ secrets.PRESTAFLOW_TOKEN }}27 projectId: '42'28 29 - name: Fail fast on regressions30 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.
1name: PrestaFlow with Flashlight 2 3on: 4 pull_request: 5 6jobs: 7 tests: 8 runs-on: ubuntu-latest 9 steps:10 - uses: actions/checkout@v411 12 - name: Setup PHP13 uses: shivammathur/setup-php@v214 with:15 php-version: '8.2'16 extensions: gd17 tools: composer:v218 19 - name: Install dependencies20 run: composer install --prefer-dist --no-progress21 22 - name: Run PrestaFlow tests against Flashlight23 uses: PrestaFlow/github-action@v224 with:25 token: ${{ secrets.PRESTAFLOW_TOKEN }}26 projectId: '42'27 flashlight: true28 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— theprestashop/prestashop-flashlight:<ps-version>image, bound to a free host port (starting at8000, falling back to8001/8002if occupied). Waits for the MySQL sidecar's health check before starting.mysql— amariadb:ltssidecar 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 viaps-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 thenamefromcomposer.jsonafter stripping the vendor prefix).type: prestashop-theme— mounted under/var/www/html/themes/<theme-name>.- Missing
composer.json, missingtype, 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 thedevelop-prestashopreference example shipped with Flashlight.modules/themes— force the corresponding subdirectory even whencomposer.jsonsays otherwise. Handy for repositories where thetypefield is missing or incorrect and you would rather set it once in the workflow than fix the manifest.
1- name: Run PrestaFlow tests against a custom PrestaShop2 uses: PrestaFlow/github-action@v23 with:4 token: ${{ secrets.PRESTAFLOW_TOKEN }}5 projectId: '42'6 flashlight: true7 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):
1- name: Run PrestaFlow tests with init scripts2 uses: PrestaFlow/github-action@v23 with:4 token: ${{ secrets.PRESTAFLOW_TOKEN }}5 projectId: '42'6 flashlight: true7 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:
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@v411 12 - name: Setup PHP13 uses: shivammathur/setup-php@v214 with:15 php-version: '8.2'16 extensions: gd17 tools: composer:v218 19 - name: Install dependencies20 run: composer install --prefer-dist --no-progress21 22 - name: Run selected suites23 uses: PrestaFlow/github-action@v224 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:
1name: PrestaFlow — parallel suites 2 3on: 4 pull_request: 5 6jobs: 7 tests: 8 runs-on: ubuntu-latest 9 strategy:10 fail-fast: false11 matrix:12 suite: [BackOffice, FrontOffice, Api]13 steps:14 - uses: actions/checkout@v415 16 - name: Setup PHP17 uses: shivammathur/setup-php@v218 with:19 php-version: '8.2'20 extensions: gd21 tools: composer:v222 23 - name: Install dependencies24 run: composer install --prefer-dist --no-progress25 26 - name: Run ${{ matrix.suite }}27 uses: PrestaFlow/github-action@v228 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.

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:
1name: PrestaFlow 2 3on: 4 pull_request: 5 6permissions: 7 contents: read 8 pull-requests: write 9 10jobs:11 tests:12 runs-on: ubuntu-latest13 steps:14 - uses: actions/checkout@v415 16 - name: Setup PHP17 uses: shivammathur/setup-php@v218 with:19 php-version: '8.2'20 extensions: gd21 tools: composer:v222 23 - name: Install dependencies24 run: composer install --prefer-dist --no-progress25 26 - name: Run PrestaFlow tests27 uses: PrestaFlow/github-action@v228 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:
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@v411 12 - name: Setup PHP13 uses: shivammathur/setup-php@v214 with:15 php-version: '8.2'16 extensions: gd17 tools: composer:v218 19 - name: Install dependencies20 run: composer install --prefer-dist --no-progress21 22 - name: Run PrestaFlow tests23 uses: PrestaFlow/github-action@v224 with:25 token: ${{ secrets.PRESTAFLOW_TOKEN }}26 projectId: '42'27 28 analyse:29 needs: tests30 runs-on: ubuntu-latest31 steps:32 - uses: actions/download-artifact@v433 with:34 name: prestaflow-report-${{ github.run_id }}-${{ github.run_attempt }}35 36 - name: Inspect results.json37 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 whenflashlight: trueis combined with a runner that has no Docker daemon. Fix: useruns-on: ubuntu-latest(Docker is not available on themacos-*andwindows-*runners). -
Port 8000 already in use — Flashlight tries to bind to host port
8000first, and automatically falls back to8001then8002. 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_TOKENis 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 targetprojectId. -
PR comment not posted (403 / permission) — GitHub blocks the comment API when the workflow token lacks the right scope. Add
permissions: pull-requests: writeat the workflow or job level, or pass a customgithub-token(a PAT or a GitHub App token) with sufficient scope through thegithub-tokeninput. -
Class "…\\Pages\\v8\\…\\Page" not found— withflashlight: trueandps-version: '9.0.0', the library still tried to loadv8-namespaced pages. Root cause: the library reads its version selector from an environment variable, and untilprestaflow/php-library@1.5.2that lookup only saw$_ENV, not the process environment the action exports. Bump your dependency to^1.5.2and 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 noresults.jsonthe 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/htmlexpects a different database schema than the one Flashlight restored. Check thatps-versionmatches 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 viaflashlight-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 theprestashop-versions.jsonmanifest but you need to build the image yourself. For shops on 1.6 or 1.7, targeting a running preprod viaPRESTAFLOW_FO_URL(no Flashlight, no mount) is usually the pragmatic path.