tamash-playwright

Running in CI

Runtime healing works unattended — a broken locator in CI is recovered from the live page and the run stays green, with every heal in the artifacts. Two things are worth setting up beyond that.

1. A provider that authenticates in CI

Provider CI auth
ollama / openai / anthropic / gemini the API key as a secret
claude-subscription CLAUDE_CODE_OAUTH_TOKEN secret (claude setup-token)
copilot-subscription on GitHub Actions: permissions: copilot-requests: write if the repo owner has Copilot, otherwise a COPILOT_GITHUB_TOKEN PAT — see Claude / Copilot subscription
tamash nothing — no key, no network
kiro / codex / cursor subscription not supported in CI — local development only
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      HEALER_ENABLED: true
      HEALER_PROVIDER: ollama
      OLLAMA_MODEL: gpt-oss:120b
      OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: lts/* }
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with: { name: playwright-report, path: playwright-report/ }
      - uses: actions/upload-artifact@v4          # the heal log — apply-heals reads this
        if: ${{ !cancelled() }}
        with:
          name: heals-log
          path: .tamash-playwright/heals.jsonl
          if-no-files-found: ignore

2. apply-heals in CI (heals become a reviewed PR)

Add a job after test that downloads the heal-log artifact, applies the fixes to source, verifies them with healing off, and opens a PR. A cache hit within one CI run is free, but only apply-heals landing the real fix stops the repeat AI calls across runs.

  apply-heals:
    needs: test
    if: ${{ !cancelled() && github.event_name == 'push' }}
    runs-on: ubuntu-latest
    permissions: { contents: write, pull-requests: write }
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: lts/* }
      - run: npm ci
      - uses: actions/download-artifact@v4
        with: { name: heals-log, path: shard-logs }
        continue-on-error: true                    # no artifact = nothing healed this run
      - run: npx tamash-playwright apply-heals --logs-dir shard-logs
      # ... git diff check -> install browsers -> re-run affected tests with HEALER_ENABLED=false
      #     -> open a PR with the verified diff

--logs-dir <path> merges every heals.jsonl found under <path> (any nesting), so it scales to sharded suites. A full working example lives in the TypeScript sample repo's .github/workflows/playwright.yml. See Making heals permanent for how apply-heals decides what to change.

Non-Playwright runners

copilot-subscription keeps a shared subprocess open across calls for performance. Playwright's own runner force-exits regardless — invisible there — but a runner that doesn't (Cucumber, a plain script) will hang after your tests finish. Call this from its teardown hook (a no-op if copilot-subscription was never used):

import { closeCopilotSubscriptionClient } from 'tamash-playwright';
// Cucumber AfterAll, Jest afterAll, your script's cleanup, …
await closeCopilotSubscriptionClient();
Questions or bugs? Open an issue  ·  Built from tamash-playwright-support/docs.