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

# CircleCI TestDino CLI Setup

> Upload Playwright results from CircleCI to TestDino using the tdpw CLI, with sharded parallel runs.

<Callout icon="book-open" color="#3B82F6">
  **What you'll learn**

  * How to upload Playwright results from CircleCI using the `tdpw` CLI
  * How to configure sharded test runs with merged reporting
</Callout>

Upload Playwright test results to TestDino using the `tdpw` CLI directly in your CircleCI config.

## Prerequisites

Before setting up, ensure you have:

* 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 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> for sample tests and ready-to-use CI configs
* A CircleCI account with access to your repository
* Playwright configured with JSON and HTML reporters in `playwright.config.js`:

```javascript playwright.config.js theme={null}
// ...existing config

reporter: [
  ['html', { outputDir: './playwright-report' }],  // Optional
  ['json', { outputFile: './playwright-report/report.json' }],  // ✅ Required
]
```

## Set Up Your API Key

1. Open your project in CircleCI
2. Go to **Project Settings → Environment Variables**
3. Click **Add Environment Variable**
4. Set the name to `TESTDINO_TOKEN`
5. Paste your TestDino API key as the value
6. Save the variable

<Warning>
  **Warning**

  Never commit your API key directly in config files. Always use environment variables.
</Warning>

## Basic Config

<Accordion title=".circleci/config.yml — Basic config">
  ```yaml .circleci/config.yml theme={null}
  version: 2.1

  jobs:
    test:
      docker:
        - image: mcr.microsoft.com/playwright:v1.59.1-noble
      working_directory: ~/project
      environment:
        CI: "true"
      steps:
        - checkout
        - run:
            name: Install dependencies
            command: npm ci
        - run:
            name: Run Playwright tests
            command: npx playwright test
        - run:
            name: Upload results to TestDino
            command: npx tdpw upload ./playwright-report --token="$TESTDINO_TOKEN"
            when: always

  workflows:
    test-and-upload:
      jobs:
        - test
  ```
</Accordion>

<Tip>
  **Tip**

  The `when: always` flag ensures the upload runs even if tests fail.
</Tip>

## Upload Options

| Flag                    | Description                                         | Default |
| :---------------------- | :-------------------------------------------------- | :------ |
| `--environment <value>` | Target environment tag (staging, production, qa)    | unknown |
| `--tag <values>`        | Comma-separated run tags for categorization (max 5) | None    |
| `--upload-images`       | Upload image attachments                            | false   |
| `--upload-videos`       | Upload video attachments                            | false   |
| `--upload-html`         | Upload HTML reports                                 | false   |
| `--upload-traces`       | Upload trace files                                  | false   |
| `--upload-files`        | Upload file attachments (.md, .pdf, .txt, .log)     | false   |
| `--upload-full-json`    | Upload all attachments                              | false   |
| `--json`                | Output results as JSON to stdout (for CI/CD)        | false   |
| `-v, --verbose`         | Enable verbose logging                              | false   |

## Sharded Test Runs

For larger test suites, CircleCI parallelism splits tests across multiple containers. Each shard produces a blob report that needs to be merged before uploading.

### How it works

1. CircleCI runs Playwright across 4 shards using `parallelism: 4`
2. Each shard saves its blob report to a workspace directory
3. A separate `merge-and-upload` job collects all blob reports, merges them, and uploads to TestDino
4. The merge job runs even if some shards fail

### Full sharded config

<Accordion title=".circleci/config.yml — Sharded config">
  ```yaml .circleci/config.yml theme={null}
  version: 2.1

  jobs:
    test:
      docker:
        - image: mcr.microsoft.com/playwright:v1.59.1-noble
      working_directory: ~/project
      parallelism: 4
      environment:
        CI: "true"
      steps:
        - checkout

        - run:
            name: Run Playwright shard
            command: |
              mkdir -p workspace/blob/$CIRCLE_NODE_INDEX
              npm ci

              set +e
              npx playwright test --shard=$((CIRCLE_NODE_INDEX + 1))/$CIRCLE_NODE_TOTAL
              TEST_EXIT_CODE=$?

              if [ -d blob-report ]; then
                cp -R blob-report/. workspace/blob/$CIRCLE_NODE_INDEX/
              fi

              echo $TEST_EXIT_CODE > /tmp/test-exit-code
              exit 0

        - persist_to_workspace:
            root: workspace
            paths:
              - blob

        - store_artifacts:
            path: test-results
            destination: test-results

        - store_test_results:
            path: test-results

        - run:
            name: Mark shard failed if tests failed
            when: always
            command: |
              exit $(cat /tmp/test-exit-code)

    merge-and-upload:
      docker:
        - image: mcr.microsoft.com/playwright:v1.59.1-noble
      working_directory: ~/project
      environment:
        CI: "true"
      steps:
        - checkout

        - attach_workspace:
            at: workspace

        - run:
            name: Install dependencies
            command: npm ci

        - run:
            name: Merge reports
            command: |
              mkdir -p merged-blob-reports playwright-report
              find workspace/blob -type f -name "*.zip" -exec cp {} merged-blob-reports/ \;
              npx playwright merge-reports --reporter=json merged-blob-reports > playwright-report/report.json

        - run:
            name: Upload to TestDino
            command: npx tdpw upload ./playwright-report --token="$TESTDINO_TOKEN"

        - store_artifacts:
            path: playwright-report
            destination: playwright-report

  workflows:
    test:
      jobs:
        - test
        - merge-and-upload:
            requires:
              - test:
                  - success
                  - failed
                  - canceled
  ```
</Accordion>

### Key details

| Config Block                                            | What It Does                                                |
| :------------------------------------------------------ | :---------------------------------------------------------- |
| `parallelism: 4`                                        | Runs 4 shard containers in parallel                         |
| `--shard=$((CIRCLE_NODE_INDEX + 1))/$CIRCLE_NODE_TOTAL` | CircleCI uses 0-based indexing, Playwright uses 1-based     |
| `set +e` / `exit 0`                                     | Prevents shard failure from stopping blob report collection |
| `persist_to_workspace` / `attach_workspace`             | Passes blob reports from shards to the merge job            |
| `requires: success, failed, canceled`                   | Merge job runs regardless of shard outcomes                 |

## Run Locally

```bash theme={null}
npm ci
npx playwright install --with-deps
npx playwright test
npx tdpw upload ./playwright-report --token="$TESTDINO_TOKEN"
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Upload step skipped after test failure">
    Add `when: always` to the upload step. For sharded runs, the `merge-and-upload` job must require the test job with `success`, `failed`, and `canceled` statuses.
  </Accordion>

  <Accordion title="No report found at ./playwright-report">
    Verify your `playwright.config.js` outputs to `playwright-report/`. For sharded runs, ensure `persist_to_workspace` includes `blob` and the merge step writes to `playwright-report/`.
  </Accordion>

  <Accordion title="TESTDINO_TOKEN not found">
    Confirm the environment variable is set in **CircleCI → Project Settings → Environment Variables**. Variable names are case-sensitive.
  </Accordion>

  <Accordion title="Sharded reports not merging correctly">
    Ensure all shards copy blob reports to `workspace/blob/$CIRCLE_NODE_INDEX/`. Verify blob reports are `.zip` files.
  </Accordion>
</AccordionGroup>

## Next Steps

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

  <Card title="Branch Mapping" icon="code-branch" href="/platform/organizations/settings">
    Map branches to environments for organized test runs
  </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>
