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
- A Gaffer account with a project
- Your project’s API key
- A CircleCI project with a
config.ymlfile
Setup
1. Add your API key as an environment variable
- Go to your CircleCI project settings
- Navigate to Environment Variables
- Click Add Environment Variable
- Name:
GAFFER_API_KEY - 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:
| Variable | Description | Example |
|---|---|---|
$CIRCLE_SHA1 | Full commit SHA | abc123def456... |
$CIRCLE_BRANCH | Branch name | main, feature/login |
$CIRCLE_PR_NUMBER | Pull request number (if applicable) | 42 |
$CIRCLE_PROJECT_REPONAME | Repository name | my-app |
$CIRCLE_BUILD_NUM | Build number | 123 |
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_KEYis set in project environment variables - Ensure
when: alwaysis 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
- CTRF Guide - Use the universal test format
- Upload API Reference - Full API documentation
- Slack Integration - Get test results in Slack
Other CI Providers: GitHub Actions · GitLab CI · Jenkins · Bitbucket · Azure DevOps