P0 / P1 · Chapter 07 / 15
GitLab CI/CD
The 60-second cheat sheet#
CI turns a commit into reproducible validation and evidence; CD promotes approved artifacts. A pipeline contains stages and jobs executed by runners. A quality gate must fail on meaningful critical defects and be enforced by merge settings. Shards divide the suite across jobs; workers execute within each Playwright run.
Pipeline structure and Jenkins translation#
| GitLab concept | Jenkins analogy / decision |
|---|---|
.gitlab-ci.yml pipeline |
Jenkinsfile pipeline as code |
| Runner + image | Agent/node plus tool/container environment |
| Stages / jobs | Stage/parallel steps; jobs have separate workspaces |
needs |
DAG dependency; can run earlier than stage ordering |
| Cache | Reusable downloads; not reliable artifact transport |
| Artifacts | Explicit retained outputs/reports; sensitive material needs access control |
| MR pipeline | Feedback before merge; main/nightly prove broader integration |
Install via package lockfile with npm ci. Choose either a concrete version-matched Playwright image or install browsers for the locked package. The following uses the latter so no fake container tag is presented. Node 22 is an example supported runtime line; production CI should pin an approved digest and periodically update it.
Annotated GitLab YAML#
# .gitlab-ci.yml: valid example, assumes package-lock and Playwright config exist.
stages: [validate, test]
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
typecheck:
stage: validate
image: node:22-bookworm
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
script:
- npm ci
- npx tsc --noEmit
- npm run lint
playwright:
stage: test
image: node:22-bookworm
parallel: 4
variables:
CI: "true"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
script:
- npm ci
- npx playwright install --with-deps chromium
# Auth setup runs inside this job, with job-specific leased credentials.
- |
if [ "$CI_PIPELINE_SOURCE" = "merge_request_event" ]; then
npx playwright test --project=chromium --grep @smoke --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
else
npx playwright test --project=chromium --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
fi
artifacts:
when: always
paths: [playwright-report/, test-results/]
reports:
junit: reports/junit.xml
expire_in: 7 days
allow_failure: false
This YAML expects npm run lint, TypeScript and the reporter config in framework configuration. It does not create accounts: wire a real authorized lease/provisioning process before running. Container/browser installation adds time; an approved version-matched official image avoids repeated browser installs. Keep its tag matched to the locked Playwright package. Restrict artifact access; even failure screenshots and traces can expose sensitive data. Do not add auth JSON paths.
The same explicit rules include both static validation and browser tests in MR/default-branch/scheduled pipelines. In GitLab, jobs without rules can have different default MR inclusion behavior; do not accidentally omit typecheck from the MR gate. Workflow rules avoid unrelated duplicate branch pipelines in this minimal policy; extend deliberately for release branches or manual runs.
allow_failure and protected merges#
| Setting | Effect | Senior interpretation |
|---|---|---|
allow_failure: false |
Job failure fails pipeline | Critical smoke/validation should normally block |
allow_failure: true |
Job can fail without failing pipeline | Explicit optional experiment, with visible ownership |
| Pipeline success required in project merge settings | Gates merging on pipeline status | YAML alone cannot enforce protected branch policy |
| Test runner retries | Rerun failed tests | Classify flaky results; do not treat recovered pass as fixed |
| GitLab job retry | Rerun job, possibly all side effects | Restrict retry conditions to understood infrastructure failures |
A critical test cannot safely become optional merely to make the pipeline green. Quarantine requires tracked issue, owner, expiry, risk acceptance and replacement evidence. If pipelines are skippable or the wrong pipeline is associated with an MR, validate the project workflow settings too. Use protected branches and human review, not agent writes to main.
Shards, resources and isolation#
# GitLab parallel jobs provide CI_NODE_INDEX and CI_NODE_TOTAL (1-based index).
npx playwright test --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
# Worker count is within one run, not the number of CI shards.
npx playwright test --workers=2
Separate jobs have separate filesystems. Prefer authenticating inside each job; passing auth artifacts between jobs needs additional protected handling and can create expired/shared-session problems. Suite balancing depends on test layout and fullyParallel configuration; measure slow shard tails rather than assuming four jobs means fourfold speedup. Tune workers against CPU/memory, database pools and account capacity. Four shards × four workers can mean sixteen concurrent slots.
Reports, secrets and suite policy#
HTML helps investigation, JUnit feeds CI summaries, traces connect actions/DOM/network, screenshots show state, video sometimes adds sequence. Retain only useful evidence with short expiry and restricted access. Masking is not perfect prevention: never echo secrets, embed them in URLs, or attach full headers/state files. Use protected/scoped variables or a secrets manager, least-privilege test accounts and approved environments. Fork/MR variable availability depends on project policy.
MR gates: critical smoke plus typecheck/lint and targeted API/contract tests. Main branch: broader integration/regression. Nightly: full matrix, slower performance/visual/data checks. “Targeted” needs an explicit risk mapping so changed shared services do not silently miss critical flows. Docker differences include fonts, locale/time zone, libraries, headless behavior and resource limits. Cloud runners add network/capacity/secret-management considerations, not automatic reliability.
Interview response#
30 seconds: “I make critical smoke and static checks blocking, retain reports on failure, and require successful pipelines for merge. I separate shards from workers and allocate data/accounts across all concurrent jobs. Retries provide diagnostics; I classify and fix flakes rather than hide them behind allow_failure.”
90-second senior answer: CI design from Jenkins experience
I translate Jenkins stages and agents into GitLab jobs and runners, preserving a reproducible lockfile install and explicit environment. MR pipelines should deliver fast confidence on business-critical flows, while main and scheduled pipelines broaden the matrix. I shard only after reducing redundant UI work and fixing shared-state failures. Each job authenticates with an independent account scope. I publish sanitized HTML/JUnit/trace evidence with retention and access controls. A required job must have allow_failure false, and project settings must enforce successful pipelines and protected review. On resource-related failures I compare CPU, memory, worker count and latency before changing timeouts. I distinguish product failures, automation defects and runner outages so retry policies don't duplicate risky mutations.
Memory hook: meaningful test → failing job → failing pipeline → enforced merge gate.
Quick practice · reveal answers#
Does allow_failure true block merge?
- The job may fail while pipeline succeeds.
- Critical checks need false and project settings requiring successful pipelines.
Pitfall: Thinking job YAML alone enforces every merge policy.
Shards versus workers?
- Shards partition across runs/jobs; workers execute within each run.
- Four by four gives up to sixteen slots.
Pitfall: Allocating accounts only for four total processes.
How should CI install Playwright?
- npm ci from lockfile plus matching browser installation, or approved version-matched official image.
- Keep OS/browser/package compatible.
Pitfall: Fake image tags or stale cached browsers.
What artifacts should be retained?
- Sanitized HTML/JUnit
- traces/screenshots when useful, always-on-failure availability with restricted access and expiry.
Pitfall: Publishing auth state or token-bearing traces broadly.
Official references and related topics#
Optional online further reading; all core study material is included above.