Skip to main content
What you’ll learn
  • How to upload Playwright test results from GitHub Actions to TestDino
  • How to configure sharded test runs with smart reruns
Set up a GitHub Actions workflow to upload Playwright test results to TestDino and view aggregated analytics, failure analysis, and flaky test detection on your dashboard. This guide covers a basic workflow, sharded workflow for parallel test execution across multiple shards, and rerunning only failed tests.

Prerequisites

Before setting up, ensure you have:
playwright.config.js
// ...existing config
reporter: [
  ['html', { outputDir: './playwright-report' }],  // Optional
  ['json', { outputFile: './playwright-report/report.json' }],  // ✅ Required
]
WarningThe HTML reporter must be listed before the JSON reporter. Playwright’s HTML reporter clears its output directory on each run, so placing it first ensures report.json is not deleted.

Store the API Key

  1. Go to your GitHub repository
  2. Open Settings → Secrets and variables → Actions
  3. Click New repository secret
  4. Name: TESTDINO_TOKEN
  5. Value: Your TestDino API key
  6. Click Add secret

Basic Workflow

Add the upload step after your Playwright tests:
.github/workflows/test.yml
name: Playwright Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright
        run: npx playwright install --with-deps

      - name: Run tests
        run: npx playwright test

      - name: Upload to TestDino
        if: always()
        run: npx tdpw upload ./playwright-report --token="${{ secrets.TESTDINO_TOKEN }}" --upload-html
The if: always() condition ensures results upload even when tests fail.

Upload Options

FlagDescriptionDefault
--environment <value>Target environment tag (staging, production, qa)unknown
--tag <values>Comma-separated run tags for categorization (max 5)None
--upload-imagesUpload image attachmentsfalse
--upload-videosUpload video attachmentsfalse
--upload-htmlUpload HTML reportsfalse
--upload-tracesUpload trace filesfalse
--upload-filesUpload file attachments (.md, .pdf, .txt, .log)false
--upload-full-jsonUpload all attachmentsfalse
--jsonOutput results as JSON to stdout (for CI/CD)false
-v, --verboseEnable verbose loggingfalse

Sharded Tests with Smart Reruns

Run tests in parallel shards with automatic failed test detection:
.github/workflows/test.yml
name: Playwright Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4]
        shardTotal: [4]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright
        run: npx playwright install --with-deps

      - name: Run Playwright Tests
        shell: bash
        env:
          TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
        run: |
          if [[ "${{ github.run_attempt }}" -gt 1 ]]; then
            npx tdpw last-failed --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} > last-failed-flags.txt
            EXTRA_PW_FLAGS="$(cat last-failed-flags.txt)"

            if [[ -z "$EXTRA_PW_FLAGS" ]]; then
              echo "No failed tests found. Exiting."
              exit 0
            fi

            eval "npx playwright test $EXTRA_PW_FLAGS"
            exit 0
          fi

          npx playwright test \
            --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}

      - name: Cache rerun metadata
        if: always()
        run: npx tdpw cache --token="${{ secrets.TESTDINO_TOKEN }}"

      - name: Upload test reports
        if: always()
        run: npx tdpw upload ./playwright-report --token="${{ secrets.TESTDINO_TOKEN }}" --upload-full-json

Environment Tagging

Tag uploads with an environment to organize results:
- name: Upload to TestDino
  if: always()
  run: |
    npx tdpw upload ./playwright-report \
      --token="${{ secrets.TESTDINO_TOKEN }}" \
      --upload-full-json \
      --environment="staging"
Environment tags appear in TestDino dashboards and can be used for filtering.

Rerun Failed Tests

Cache test metadata to enable selective reruns:
- name: Run tests
  run: npx playwright test

- name: Cache metadata
  if: always()
  run: npx tdpw cache --token="${{ secrets.TESTDINO_TOKEN }}"

- name: Upload reports
  if: always()
  run: npx tdpw upload ./playwright-report --token="${{ secrets.TESTDINO_TOKEN }}" --upload-full-json
Rerun only failed tests on the next run:
- name: Get failed tests
  id: failed
  run: |
    npx tdpw last-failed --token="${{ secrets.TESTDINO_TOKEN }}" > failed.txt
    echo "tests=$(cat failed.txt)" >> $GITHUB_OUTPUT

- name: Rerun failed tests
  if: steps.failed.outputs.tests != ''
  run: npx playwright test ${{ steps.failed.outputs.tests }}
For advanced rerun strategies, caching patterns, and CI optimization techniques, see CI Optimization.

Troubleshooting

Add if: always() to the upload step so it runs regardless of test exit code. For sharded runs, use fail-fast: false in the matrix strategy.
Ensure playwright.config.js includes both HTML and JSON reporters with HTML listed first. Confirm the output directory matches the path passed to tdpw upload.
Confirm the secret is set in Settings → Secrets and variables → Actions. Secret names are case-sensitive.

Next Steps

CI Optimization

Reduce CI time with smart reruns

Branch Mapping

Map branches to environments for organized test runs

Integrations

Connect Slack, Jira, Linear, Asana, and more

GitHub App Integration

PR comments, CI checks, and pull request sync