运行

CI and GitHub

Run danwo in GitHub Actions and get a check on every pull request, with each failing line annotated.

本页还没有中文版,下面是英文原文。

Run your tests and a fault matrix on every pull request. danwo reports back as a GitHub check, with an annotation on each failing test line, and keeps one comment on the pull request up to date.

The workflow

.github/workflows/danwo.yml
name: danwo
on: [pull_request]

permissions:
  checks: write
  pull-requests: write
  contents: read

jobs:
  danwo:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 24 }
      - run: npm ci
      - run: npx @danwo/cli install-browser --with-deps --only-shell
      - run: npx @danwo/cli test --reporter github
        env:
          GITHUB_TOKEN: ${{ github.token }}
      - run: npx @danwo/cli matrix tests/checkout.danwo.ts --reporter github
        if: ${{ !cancelled() }}
        env:
          GITHUB_TOKEN: ${{ github.token }}
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: danwo-runs
          path: .danwo/runs

--reporter github turns on the check, the pull request comment and the job summary. The last step uploads the flight records, so you can open a failure's recording.

What the check shows

  • pass and fail counts, and a row per failing test or fault;
  • an annotation on each failing test line, in the pull request's Files changed tab;
  • each failure's flight record, by its path in the uploaded artifact.

The same summary goes to the job summary page.

Several suites in one repository

A repository can hold more than one suite, such as an app's and its admin's. Give each a name, and GitHub reports each one on its own:

admin/e2e/danwo.config.ts · the suite's name
export default defineConfig({
  name: "admin",
  // …
})
WhatOne suiteA suite named admin
check rundanwodanwo · admin
pull request comment sectionsharedits own
job summary headingdanwo testdanwo test · admin
artifact the summary namesdanwo-runsdanwo-runs-admin

--name admin on the command line does the same for one run. Upload each suite's runs under its artifact's name:

.github/workflows/e2e.yml · one suite's records
- uses: actions/upload-artifact@v4
  if: ${{ !cancelled() }}
  with:
    name: danwo-runs-admin
    path: admin/e2e/.danwo/runs

When git tracks more than one danwo config and a suite has no name, danwo names it after its config's folder, skipping folders such as e2e and tests. A repository with one suite reports as before.

Permissions

PermissionNeeded forWithout it
checks: writethe check run and its annotationsthe reporter says so; the exit code is unchanged
pull-requests: writethe pull request commentthe reporter says so once; the check still runs
contents: readchecking out the codethe job can't start

CI defaults

With CI set (every hosted CI sets it), or with --ci, danwo test:

  • retries a failing test once;
  • reads the replay cache without writing to it;
  • refuses .only, with exit code 2 naming the file and line.

Your config's retries and --retries still win.

A danwo test that a test or fixture starts inherits the job's CI=true too. When that run is test data rather than a CI run of its own, pass --no-ci to give it the local defaults:

npx @danwo/cli test --no-ci

Setting CI=false in the child's environment does the same.

Make no model calls

A read-only cache still calls the model when a step has no recording. To make sure CI spends nothing, run with --replay-only:

npx @danwo/cli test --replay-only

Each agent step must then replay from the cache. A step that can't fails the test instead of calling the model:

✗ tests/checkout.danwo.ts › pays for an order  [Undecided]
  REPLAY_MISSING: agent.act("pay for the order") has no recording that replays (none was recorded), and replay-only runs no model. Run the test without --replay-only to record it, check it, and commit the cache.

4 passed, 1 failed (1 undecided)
cache: 11 replayed · 0 relocated · 0 handed off · 1 missed
model: 0 calls (replay-only)
A step withUnder --replay-only
a recording that replaysreplays, as always
no recordingfails with REPLAY_MISSING
a stale recordingfails, naming what changed
a recording that no longer matchesfails, saying what stopped matching

To make every run replay-only, set it in the config:

danwo.config.ts · the cache
cache: { dir: ".danwo-cache", replayOnly: true },

Record a failing step by running it locally without the flag, then commit the cache.

Bound the run

Two flags stop a run from starting new test files. Files already running finish:

FlagStops starting filesExit code
--max-failures <n>once n tests failed1, from the failures
--max-duration <t>once the run has taken t, e.g. 20m1: files were left out

Run npx @danwo/cli doctor as a first step to see what a run would trip on: Node, Chromium, the config, the model's key. --json prints the checks for a script.

For a config that runs its tests on devices, the doctor also checks each platform's toolchain. It finds them from the @danwo/mobile helpers the config calls:

The project hasThe doctor checks
withIosDevice or buildIos in its configXcode, simctl, an iOS runtime and CocoaPods
withAndroidDevice or buildAndroid in its configthe Android SDK, adb, the emulator, an AVD on a rootable image and a JDK
a pubspec.yaml too, at its root or a folder downFlutter on PATH

Each failure says how to fix it. A config that runs on both platforms passes when one is ready, and the other's failures show as warnings.

Exit codes

CodeMeaning
0everything passed
1a test failed, or a run could not be judged
2configuration problem
3infrastructure: the browser, environment or model provider
130interrupted

Keep CI cheap

Commit the replay cache (cache.dir). CI then replays recorded agent steps with no model calls, so it needs a model key only when a recording is missing. With --replay-only it never needs one.

Run a narrowed matrix on pull requests with --faults, and the full matrix on a schedule.

Next

本页内容

在每个 Pull Request 上运行

每个 Pull Request 一个 GitHub Check 和一条评论,并附上完整的运行记录。

配置 CI