> ## Documentation Index
> Fetch the complete documentation index at: https://docs.testdino.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Playwright Harness CI Setup

> Stream Playwright results from Harness CI to TestDino live, with sharded parallel steps grouped into one run.

Harness CI runs your pipeline from a YAML definition, stored in `.harness/` in your repository or inline in the Harness UI. This guide covers a sharded setup that streams results to TestDino during the run.

## Prerequisites

* A <a href="https://app.testdino.com" target="_blank" rel="noopener noreferrer">TestDino account <Icon icon="arrow-up-right-from-square" size={12} /></a> with a project created
* A TestDino API key ([Generate API Keys](/guides/generate-api-keys))
* A Harness CI project with a Git connector to your repository
* A Playwright test project (or clone the <a href="https://github.com/testdino-hq/TestDino-Example" target="_blank" rel="noopener noreferrer">TestDino Example Repository <Icon icon="arrow-up-right-from-square" size={12} /></a> to get started)
* `@testdino/playwright` installed and configured in `playwright.config.ts|js|mjs`:

```bash theme={null}
npm install @testdino/playwright
```

```typescript playwright.config.ts theme={null}
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['@testdino/playwright', {
      token: process.env.TESTDINO_TOKEN,
    }],
  ],
});
```

## Set Up Your API Key

Store your TestDino API key as a Harness secret so the pipeline reads it by reference instead of holding the value in YAML.

1. In Harness, open **Project Settings** (or **Organization Settings** to share it across projects)
2. Go to **Secrets**
3. Click **New Secret**, then **Text**
4. Set the **Secret Name** to `TESTDINO_TOKEN`
5. Paste your TestDino API key into the value
6. Save the secret

Reference it in the pipeline with `<+secrets.getValue("TESTDINO_TOKEN")>`. Harness masks secret values in build logs.

## Basic Pipeline Config

For a simple setup without sharding, run your tests in one `Run` step with `TESTDINO_TOKEN` set. Results stream to TestDino during the run, so no separate upload step is needed.

Replace `<ORG_ID>`, `<PROJECT_ID>`, `<GIT_CONNECTOR_ID>`, and `<YOUR_REPO>` with your Harness values. This example targets Harness Cloud runners; self-hosted (Docker or Kubernetes) runners use the same step with a different `platform` and `runtime`.

<Accordion title=".harness/playwright.yaml: Basic pipeline">
  ```yaml .harness/playwright.yaml theme={null}
  pipeline:
    name: playwright-testdino
    identifier: playwright_testdino
    projectIdentifier: <PROJECT_ID>
    orgIdentifier: <ORG_ID>
    properties:
      ci:
        codebase:
          connectorRef: <GIT_CONNECTOR_ID>
          repoName: <YOUR_REPO>
          build: <+input>
    stages:
      - stage:
          name: test
          identifier: test
          type: CI
          spec:
            cloneCodebase: true
            platform:
              os: Linux
              arch: Amd64
            runtime:
              type: Cloud
              spec: {}
            execution:
              steps:
                - step:
                    type: Run
                    name: playwright tests
                    identifier: playwright_tests
                    spec:
                      image: mcr.microsoft.com/playwright:v1.61.1-jammy
                      shell: Sh
                      envVariables:
                        TESTDINO_TOKEN: <+secrets.getValue("TESTDINO_TOKEN")>
                      command: |
                        npm ci
                        npx playwright install
                        npx playwright test
  ```
</Accordion>

<Tip>
  **Tip**

  `TESTDINO_TOKEN` is resolved from the Harness secret you added earlier. Results stream live even when tests fail, so failures land on the dashboard without a separate upload step.
</Tip>

## Sharded Test Runs

For large test suites, run shards in parallel. Each shard streams its own results, and TestDino groups them into one run when they share a `ci-run-id`.

### How it works

1. A `Run` step installs dependencies once, then a second `Run` step uses `strategy.parallelism` to fan out into shards
2. Each shard runs Playwright with `--shard=<n>/<total>` from its iteration index
3. Each shard streams its results to TestDino during the run
4. Every shard sets the same `TESTDINO_CI_RUN_ID` so TestDino merges them into a single run
5. No merge or upload step runs after the shards finish

### Full sharded config

Replace `<ORG_ID>`, `<PROJECT_ID>`, `<GIT_CONNECTOR_ID>`, and `<YOUR_REPO>` with your Harness values. This example targets Harness Cloud runners; self-hosted (Docker or Kubernetes) runners use the same steps with a different `platform` and `runtime`.

<Accordion title=".harness/playwright.yaml: Sharded pipeline">
  ```yaml .harness/playwright.yaml theme={null}
  pipeline:
    name: playwright-testdino
    identifier: playwright_testdino
    projectIdentifier: <PROJECT_ID>
    orgIdentifier: <ORG_ID>
    properties:
      ci:
        codebase:
          connectorRef: <GIT_CONNECTOR_ID>
          repoName: <YOUR_REPO>
          build: <+input>
    stages:
      - stage:
          name: test
          identifier: test
          type: CI
          spec:
            cloneCodebase: true
            platform:
              os: Linux
              arch: Amd64
            runtime:
              type: Cloud
              spec: {}
            execution:
              steps:
                # Install dependencies once. Steps in a CI stage share the workspace,
                # so a single install serves every shard.
                - step:
                    type: Run
                    name: install deps
                    identifier: install_deps
                    spec:
                      image: mcr.microsoft.com/playwright:v1.61.1-jammy
                      shell: Sh
                      command: |
                        npm ci
                - step:
                    type: Run
                    name: playwright shard
                    identifier: playwright_shard
                    strategy:
                      parallelism: 4
                    spec:
                      image: mcr.microsoft.com/playwright:v1.61.1-jammy
                      shell: Sh
                      envVariables:
                        TESTDINO_TOKEN: <+secrets.getValue("TESTDINO_TOKEN")>
                        # Same run id across all shards groups them into one run in TestDino.
                        TESTDINO_CI_RUN_ID: <+pipeline.sequenceId>
                      command: |
                        # strategy.iteration is 0-based; Playwright shards are 1-based.
                        export SHARD=$((<+strategy.iteration> + 1))
                        export TOTAL=<+strategy.iterations>
                        npx playwright install
                        npx playwright test --shard=$SHARD/$TOTAL
  ```
</Accordion>

### Key details

| Detail                    | Notes                                                                         |
| :------------------------ | :---------------------------------------------------------------------------- |
| `strategy.parallelism: 4` | Harness runs 4 copies of the step as parallel shards.                         |
| `<+strategy.iteration>`   | 0-based index of the current shard. Add 1 for Playwright's 1-based `--shard`. |
| `<+strategy.iterations>`  | Total shard count, passed as the denominator of `--shard`.                    |
| `<+pipeline.sequenceId>`  | Build number for this pipeline. Used as `TESTDINO_CI_RUN_ID` to group shards. |
| `TESTDINO_CI_RUN_ID`      | Read by `@testdino/playwright` to merge all shards into one run.              |
| `TESTDINO_TOKEN`          | Resolved from the Harness secret and masked in logs.                          |

Set the `ciRunId` reporter option in `playwright.config` to `process.env.TESTDINO_CI_RUN_ID` if you prefer to pass it through the config instead of relying on the environment variable.

### Pipeline execution

After the pipeline starts, Harness shows the parallel shards under the `playwright shard` step. Each shard streams its results, and TestDino merges them into one run as they complete.

### Results in TestDino

The test run appears in your TestDino dashboard with full failure details, flaky detection, and trend data as tests complete.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Results not appearing on the dashboard">
    Confirm `@testdino/playwright` is in your `playwright.config` `reporter` array and `TESTDINO_TOKEN` resolves in the step's `envVariables`. Results stream during the run, so no separate upload step is required.
  </Accordion>

  <Accordion title="Sharded runs show up as separate runs">
    Confirm every shard sets `TESTDINO_CI_RUN_ID` to `<+pipeline.sequenceId>`. A per-shard value creates one run per shard.
  </Accordion>

  <Accordion title="Shards overwrite the same node_modules">
    On runners that share one workspace across steps, run `npm ci` once in a separate step before the sharded step, as shown above. Concurrent installs in the sharded step race on the shared `node_modules`.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="CI Optimization" icon="gauge-high" href="/guides/playwright-ci-optimization">
    Reduce CI time with smart reruns
  </Card>

  <Card title="Environment Mapping" icon="code-branch" href="/guides/environment-mapping">
    Route test results to Dev, Staging, or Production by branch
  </Card>

  <Card title="Integrations" icon="puzzle-piece" href="/integrations/overview">
    Connect Slack, Jira, Linear, Asana, and more
  </Card>

  <Card title="TestDino MCP" icon="plug" href="/mcp/overview">
    Access test results and fix issues with AI agents
  </Card>
</CardGroup>
