# CI and containers

> Run Retest in CI and in a Linux container, fail the job on the right exit codes, and feed a dashboard.

Source: https://rehearsal.dev/retest/scaling-up/ci-and-containers

Retest runs the same way in CI as on your machine. The exit code says whether to trust the run, and the run folder keeps the evidence.

## A GitHub workflow

```sh
npx retest init --ci github
```

This writes a workflow that installs your project, checks the tests' types, runs them and keeps the run folders, even when a test failed.

```text filename=".github/workflows/retest.yml"
name: Retest
on: [pull_request]
jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 24 }
      - run: npm ci
      - run: npm run typecheck:e2e
      - run: npm run test:e2e
      - uses: actions/upload-artifact@v4
        if: always()
        with: { name: retest-runs, path: .retest/runs }
```

The workflow uses npm. With another package manager, change its install step. A Linux runner needs a browser Retest can start, such as Chrome.

## What CI changes

- When the `CI` variable is set, a run with `test.only` stops before any test starts and names each one. `--allow-only` runs it anyway.
- A cancelled job sends SIGTERM. Retest stops the running test, writes the result, closes the browsers, stops the servers it started and exits with 143.
- To test a deployed preview, pass its address with `--base-url`.

## Exit codes in CI

Fail the job on any code but 0. A 1 means a check failed. A 2 means the run could not check everything, such as a missing secret or a lost browser, so it is never a pass.

## Events for dashboards

- `--reporter jsonl` prints every event as one JSON line, as it happens. The same lines are in the run folder's `events.jsonl`.
- `result.json` holds the whole result, once the run ends. Both files follow schema version 1, with JSON Schemas in the package.
- `readRunFolder(folder)` from `@rehearsal-labs/retest/runner` reads a folder back and checks it against the schemas. A folder without `result.json` is rebuilt from its events and marked incomplete.
- The HTML report also holds the outcome as JSON, in a script block with the id `retest-outcome`. A program that keeps only the report can read it there.

## Run in a container

On Linux, Retest runs the Chromium family: Chrome, Chromium and Chrome for Testing. Retest never turns Chrome's sandbox off, so a container needs three things and no extra capability:

- A user other than root. Chrome does not start its sandbox as root.
- A seccomp profile that lets the browser create user namespaces. Retest's repository has one, [`docker/linux/chromium-seccomp.json`](https://github.com/rehearsal-labs/retest/blob/main/docker/linux/chromium-seccomp.json): Docker's default profile with five rules added.
- An init process, from `docker run --init`, to reap the processes a browser leaves as it ends.

```sh
docker run --rm --init --cap-drop ALL --security-opt seccomp=docker/linux/chromium-seccomp.json --user node <image> npx retest run
```

Without the profile, the run exits with 2 and says the sandbox could not start. Docker gives a container 64 MB of `/dev/shm`. For Google Chrome and large pages, give it more with `--shm-size`.

> [!NOTE]
> Retest has run on Linux inside Docker, on arm64. Linux on x86-64, Linux outside a container and hosted CI runners have not been run yet. Windows does not work.
