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#

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#

bash
# 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.

Full explanation →

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.

Full explanation →

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.

Full explanation →

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.

Full explanation →

Official references and related topics#

Optional online further reading; all core study material is included above.

Back to library index

Prepared for both Senior automation roles. Hypothetical sandbox contracts; no employer systems or credentials. Content: 16 October 2026.