CircleCI

Upload test reports to Gaffer from CircleCI pipelines.

CircleCI is a popular CI/CD platform with powerful caching and parallelism features. With Gaffer, you can automatically upload and share test reports from your CircleCI pipelines.

Prerequisites

Setup

1. Add your API key as an environment variable

  1. Go to your CircleCI project settings
  2. Navigate to Environment Variables
  3. Click Add Environment Variable
  4. Name: GAFFER_API_KEY
  5. Value: Your Gaffer project API key

2. Add the upload step to your config

version: 2.1

jobs:
  test:
    docker:
      - image: cimg/node:20.0
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm ci
      - run:
          name: Run tests
          command: npm test
      - run:
          name: Upload to Gaffer
          when: always
          command: |
            curl -X POST https://app.gaffer.sh/api/upload \
              -H "X-API-Key: $GAFFER_API_KEY" \
              -F "files=@test-results/junit.xml" \
              -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'"}'
      - store_test_results:
          path: test-results

workflows:
  test:
    jobs:
      - test

Environment Variables

CircleCI provides these variables for your jobs:

VariableDescriptionExample
$CIRCLE_SHA1Full commit SHAabc123def456...
$CIRCLE_BRANCHBranch namemain, feature/login
$CIRCLE_PR_NUMBERPull request number (if applicable)42
$CIRCLE_PROJECT_REPONAMERepository namemy-app
$CIRCLE_BUILD_NUMBuild number123

Examples

Playwright

version: 2.1

jobs:
  playwright:
    docker:
      - image: mcr.microsoft.com/playwright:v1.40.0-jammy
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm ci
      - run:
          name: Run Playwright tests
          command: npx playwright test
      - run:
          name: Upload to Gaffer
          when: always
          command: |
            curl -X POST https://app.gaffer.sh/api/upload \
              -H "X-API-Key: $GAFFER_API_KEY" \
              -F "files=@playwright-report/index.html" \
              -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'","test_framework":"playwright","test_suite":"e2e"}'
      - store_artifacts:
          path: playwright-report

Jest with JUnit Reporter

version: 2.1

jobs:
  test:
    docker:
      - image: cimg/node:20.0
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm ci
      - run:
          name: Run Jest tests
          command: npm test -- --reporters=default --reporters=jest-junit
          environment:
            JEST_JUNIT_OUTPUT_DIR: ./test-results
      - run:
          name: Upload to Gaffer
          when: always
          command: |
            curl -X POST https://app.gaffer.sh/api/upload \
              -H "X-API-Key: $GAFFER_API_KEY" \
              -F "files=@test-results/junit.xml" \
              -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'","test_framework":"jest"}'
      - store_test_results:
          path: test-results

pytest

version: 2.1

jobs:
  pytest:
    docker:
      - image: cimg/python:3.11
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: pip install pytest pytest-html
      - run:
          name: Run pytest
          command: pytest --html=report.html --self-contained-html
      - run:
          name: Upload to Gaffer
          when: always
          command: |
            curl -X POST https://app.gaffer.sh/api/upload \
              -H "X-API-Key: $GAFFER_API_KEY" \
              -F "[email protected]" \
              -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'","test_framework":"pytest"}'
      - store_artifacts:
          path: report.html

Using CTRF Format

For a standardized format across all your test frameworks, consider using CTRF:

- run:
    name: Install CTRF reporter
    # Choose the reporter for your framework:
    # npm install --save-dev jest-ctrf-json-reporter
    # npm install --save-dev playwright-ctrf-json-reporter
    # npm install --save-dev vitest-ctrf-json-reporter
    command: npm install --save-dev jest-ctrf-json-reporter
- run:
    name: Run tests with CTRF
    command: npm test -- --reporter=jest-ctrf-json-reporter
- run:
    name: Upload CTRF to Gaffer
    when: always
    command: |
      curl -X POST https://app.gaffer.sh/api/upload \
        -H "X-API-Key: $GAFFER_API_KEY" \
        -F "[email protected]" \
        -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'"}'

Tip: The when: always condition ensures the upload runs even when tests fail — which is usually when you need the report the most.

Parallel Test Runs

When using CircleCI’s parallelism feature, you can upload from each container:

jobs:
  test:
    parallelism: 4
    steps:
      - run:
          name: Run tests
          command: |
            circleci tests glob "**/*.spec.js" | circleci tests split | xargs npm test --
      - run:
          name: Upload to Gaffer
          when: always
          command: |
            curl -X POST https://app.gaffer.sh/api/upload \
              -H "X-API-Key: $GAFFER_API_KEY" \
              -F "files=@test-results/junit.xml" \
              -F 'tags={"commitSha":"'"$CIRCLE_SHA1"'","branch":"'"$CIRCLE_BRANCH"'","container":"'"$CIRCLE_NODE_INDEX"'"}'

Troubleshooting

Report not uploading

  • Verify GAFFER_API_KEY is set in project environment variables
  • Ensure when: always is set so the step runs even when tests fail
  • Check the file path is correct relative to the working directory

401 Unauthorized

  • Check your API key starts with gfr_
  • Verify the key is correctly copied (no extra spaces)

Missing branch name

  • Make sure you’re using $CIRCLE_BRANCH (not $CIRCLE_PR_BRANCH)
  • For forks, the branch may be available in different variables

Next Steps

Other CI Providers: GitHub Actions · GitLab CI · Jenkins · Bitbucket · Azure DevOps