Appearance
CI
The repository ships a GitLab template with two tiers, because they cost very different amounts. An extension repository opts in with three lines in its own .gitlab-ci.yml:
yaml
include:
- project: qoliber-internal/furnace
ref: main
file: /gitlab/extension.yml| Job | Runs | Needs | Cost |
|---|---|---|---|
furnace:static | every push, merge request and tag, one job per PHP 8.1 to 8.5 | any shared runner with a PHP image | seconds |
furnace:certify | manual or scheduled | a runner on the cell host, tagged furnace | minutes per cell |
furnace:certify:release | every tag, cannot be skipped | same | minutes per cell |
The static tier runs furnace run --gate=syntax --syntax-php=$PHP_VERSION in a plain PHP container and keeps a JSON report per version. Certification uses the furnace checkout the cell host already has (FURNACE_HOME), so the tool and the cells stay in step; the runner needs Composer credentials for any private repositories and the Chromium system libraries for Playwright. The furnace repository must permit the consuming project's CI_JOB_TOKEN to clone it.
Exit codes carry the verdict: 0 certified or passing, 1 a gate failed or the run is incomplete, 2 invalid options.
The release job matters most: tagging on a version bump without testing anything is the one moment with no coverage at all, and furnace:certify:release closes it.
The certify tier has no host yet
The cell fleet exists only on the workstation. The runner host has PHP 8.1 to 8.5 and Docker but no cells, no MageBox and no furnace checkout, so furnace:certify has nothing to run against there. Building a fleet on it is four to six hours with scripts/provision-cell.sh, and is what actually gates CI certification. See status.
Variables the jobs rely on
| Variable | Set by | Meaning |
|---|---|---|
PHP_VERSION | the static matrix | which PHP minor the syntax job checks |
FURNACE_HOME | the runner | the furnace checkout on the cell host |
FURNACE_CELLS, FURNACE_SNAPSHOTS, FURNACE_RUNS | optional | where the cells, goldens and run logs live, when not at their defaults |
COMPOSER_AUTH | the runner's protected variables | registry credentials, as composer reads them |