Files
apf_portal/.gitlab-ci.yml
T
Julien Gautier 441b9297ce
CI / scan (pull_request) Successful in 2m48s
CI / commits (pull_request) Successful in 2m59s
CI / check (pull_request) Successful in 3m13s
CI / a11y (pull_request) Successful in 1m34s
CI / perf (pull_request) Successful in 6m22s
fix(ci): give gitlab perf job a discoverable chromium (ADR-0028)
The perf job ran on the Playwright image, which bundles Chromium at
a non-standard path that Lighthouse's chrome-launcher cannot find —
the job failed at the healthcheck with 'Chrome installation not
found'.

Switch perf to node:24-bookworm and apt-install Debian's chromium
(/usr/bin/chromium), pointing CHROME_PATH at it. Preferred over
wiring CHROME_PATH to Playwright's bundled Chromium because the
latter couples the job to an exact @playwright/test-version vs
image-tag match that a Renovate bump would silently break.

The future ADR-0016 axe-core e2e job will use the Playwright image;
Lighthouse and Playwright want different things, so they get
different images rather than one that serves both poorly.
2026-05-28 10:03:56 +02:00

160 lines
5.9 KiB
YAML

# Per ADR-0028 (CI/CD migration from Gitea Actions to GitLab CE).
# Thin YAML — orchestration lives in package.json scripts (ci:check,
# ci:catalogue-drift, ci:audit, ci:commits, ci:perf, ci:gzip-budgets)
# and Nx targets. Any change to gate behaviour belongs in those
# scripts, not in this file — see ADR-0015 §"Thin pipeline YAML…"
# (principle preserved by ADR-0028 at the migration boundary).
#
# Phase 2 of ADR-0028: ships alongside .gitea/workflows/ci.yml. Both
# pipelines must remain in parity until cutover (Phase 3), at which
# point the Gitea workflow gets deleted.
include:
# GitLab built-in scanners — replace the manual Trivy + gitleaks
# install in .gitea/workflows/ci.yml. Both add their own jobs to
# the pipeline; their default stage is `test`, which is mapped in
# `stages:` below.
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
stages:
- check
- test
- commits
- perf
- a11y
workflow:
rules:
# MR pipelines — covers GitLab MR review flow once it lands.
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Direct pushes — covers post-merge runs on main today, and Phase 2
# parity testing on feature branches mirrored from Gitea. To be
# tightened to `$CI_COMMIT_BRANCH == "main"` at the Phase 3 cutover
# once GitLab is the source of truth.
- if: $CI_PIPELINE_SOURCE == "push"
# Shared shape for jobs that need Node + pnpm. Hidden (`.` prefix) so
# GitLab does not try to execute it. Inheriting jobs `extends: .node-job`.
.node-job:
image: node:24-bookworm
cache:
key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store/
before_script:
- corepack enable
- corepack prepare pnpm@10.33.4 --activate
- pnpm config set store-dir "$CI_PROJECT_DIR/.pnpm-store"
check:
extends: .node-job
stage: check
# `nx affected` needs a base SHA to diff against. Mirrors the
# equivalent step in .gitea/workflows/ci.yml — same logic, GitLab
# variable names. Replaces nrwl/nx-set-shas (GitHub-only).
script:
- |
if [ "$CI_PIPELINE_SOURCE" = "merge_request_event" ]; then
git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --depth=100
export NX_BASE=$(git merge-base HEAD "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME")
else
export NX_BASE="HEAD~1"
fi
export NX_HEAD="HEAD"
- pnpm install --frozen-lockfile
- pnpm ci:check
# Catalogue-vs-code drift gate per ADR-0025 §"Confirmation". The
# script's own unit tests run first — if they fail the gate itself
# is broken and the actual catalogue check would be noise.
- pnpm ci:catalogue-drift:test
- pnpm ci:catalogue-drift
audit:
extends: .node-job
stage: test
# npm-advisory check against pnpm-lock.yaml. Trivy's dependency-vuln
# role from the Gitea workflow is now covered by the SAST include
# (which includes Dependency Scanning analyzers); `pnpm audit` stays
# in-pipeline as defense in depth against the npm advisory DB
# specifically.
script:
- pnpm install --frozen-lockfile
- pnpm ci:audit
commits:
extends: .node-job
stage: commits
# MRs opened by Renovate (apf-portal-bot) carry commit messages from
# a vetted Conventional-Commits template — running commitlint on
# them is tautological. Per ADR-0017 amendment.
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN != "apf-portal-bot"
variables:
# Default `GIT_DEPTH: 20` is too shallow to diff against
# origin/main on long-running branches. Full clone so commitlint
# can walk all the way back.
GIT_DEPTH: 0
script:
- git fetch origin main
- pnpm install --frozen-lockfile
- COMMIT_LINT_FROM=origin/main pnpm ci:commits
perf:
extends: .node-job
stage: perf
# Lighthouse CI drives a real Chrome via chrome-launcher, which
# probes the PATH / CHROME_PATH for a standard Chrome/Chromium
# binary. The Playwright image bundles Chromium under /ms-playwright
# with a non-standard name chrome-launcher cannot discover, so we
# stay on the base Node image and apt-install Debian's `chromium`
# (lands at /usr/bin/chromium). The future ADR-0016 axe-core e2e job
# — which drives Playwright directly — will use the Playwright image
# instead: the two tools want different things, so they get
# different images rather than one image that serves both poorly.
image: node:24-bookworm
variables:
CHROME_PATH: /usr/bin/chromium
before_script:
- !reference [.node-job, before_script]
- apt-get update -qq && apt-get install -y -qq --no-install-recommends chromium
# Skip on Renovate MRs (same rationale as commits + the perf signal
# on a dep bump is essentially zero). Push events on `main` still
# run perf — we catch regressions immediately post-merge, not
# pre-merge. Per ADR-0017 amendment.
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN != "apf-portal-bot"
script:
- pnpm install --frozen-lockfile
- pnpm ci:perf
artifacts:
when: always
paths:
- .lighthouseci/
expire_in: 30 days
a11y:
extends: .node-job
stage: a11y
# Placeholder until the e2e a11y suite (axe-core via Playwright, per
# ADR-0016) is wired with the first real screens. The job exists so
# branch protection can require it from day one — currently no-ops
# with a clear message.
script:
- echo "a11y gate placeholder - axe-core via Playwright wires up with the first real screens (ADR-0016)."
# Place SAST + Secret Detection in the `test` stage to mirror the
# Gitea workflow's grouping (where Trivy + gitleaks + audit all
# lived in the `scan` job). Override does not change behaviour —
# only stage placement. The included templates set sensible defaults
# (run on default branch + MRs, full repo on default branch / diff
# on MRs); revisited in Phase 3 if pipeline duration becomes a pain.
sast:
stage: test
secret_detection:
stage: test