Azure DevOps
Azure DevOps Pipelines is Microsoft’s CI/CD solution for cloud and on-premises deployments. With Gaffer, you can automatically upload and share test reports from your Azure Pipelines.
Prerequisites
Section titled “Prerequisites”- A Gaffer account with a project
- Your project’s upload token
- An Azure DevOps project with a pipeline configured
1. Add your upload token as a pipeline variable
Section titled “1. Add your upload token as a pipeline variable”- Go to your Azure DevOps project
- Navigate to Pipelines → select your pipeline → Edit
- Click Variables → New variable
- Name:
GAFFER_UPLOAD_TOKEN - Value: Your Gaffer project upload token
- Check Keep this value secret
- Click OK and Save
2. Add the upload step to your pipeline
Section titled “2. Add the upload step to your pipeline”trigger: - main
pool: vmImage: 'ubuntu-latest'
steps: - task: NodeTool@0 inputs: versionSpec: '20.x'
- script: npm ci displayName: 'Install dependencies'
- script: npm test displayName: 'Run tests'
- script: | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@test-results/junit.xml" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"$(Build.SourceBranchName)"}' displayName: 'Upload to Gaffer' condition: always()Environment Variables
Section titled “Environment Variables”Azure DevOps provides these predefined variables:
| Variable | Description | Example |
|---|---|---|
$(Build.SourceVersion) | Full commit SHA | abc123def456... |
$(Build.SourceBranchName) | Branch name (short) | main, feature/login |
$(Build.SourceBranch) | Full branch ref | refs/heads/main |
$(System.PullRequest.SourceBranch) | PR source branch | refs/heads/feature/login |
$(Build.BuildNumber) | Build number | 20231215.1 |
$(Build.Repository.Name) | Repository name | my-app |
Examples
Section titled “Examples”Playwright
Section titled “Playwright”trigger: - main
pool: vmImage: 'ubuntu-latest'
steps: - task: NodeTool@0 inputs: versionSpec: '20.x'
- script: npm ci displayName: 'Install dependencies'
- script: npx playwright install --with-deps displayName: 'Install Playwright browsers'
- script: npx playwright test displayName: 'Run Playwright tests'
- script: | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@playwright-report/index.html" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"$(Build.SourceBranchName)","test_framework":"playwright","test_suite":"e2e"}' displayName: 'Upload to Gaffer' condition: always()
- publish: playwright-report artifact: playwright-report condition: always()Jest with JUnit Reporter
Section titled “Jest with JUnit Reporter”trigger: - main
pool: vmImage: 'ubuntu-latest'
steps: - task: NodeTool@0 inputs: versionSpec: '20.x'
- script: npm ci displayName: 'Install dependencies'
- script: npm test -- --reporters=default --reporters=jest-junit displayName: 'Run Jest tests' env: JEST_JUNIT_OUTPUT_DIR: ./test-results
- script: | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@test-results/junit.xml" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"$(Build.SourceBranchName)","test_framework":"jest"}' displayName: 'Upload to Gaffer' condition: always()
- task: PublishTestResults@2 inputs: testResultsFormat: 'JUnit' testResultsFiles: '**/junit.xml' condition: always()pytest
Section titled “pytest”trigger: - main
pool: vmImage: 'ubuntu-latest'
steps: - task: UsePythonVersion@0 inputs: versionSpec: '3.11'
- script: pip install pytest pytest-html displayName: 'Install dependencies'
- script: pytest --html=report.html --self-contained-html displayName: 'Run pytest'
- script: | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@report.html" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"$(Build.SourceBranchName)","test_framework":"pytest"}' displayName: 'Upload to Gaffer' condition: always()
- publish: report.html artifact: pytest-report condition: always()Using CTRF Format
Section titled “Using CTRF Format”For a standardized format across all your test frameworks, consider using CTRF:
# Install the CTRF 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- script: npm install --save-dev jest-ctrf-json-reporter displayName: 'Install CTRF reporter'
- script: npm test -- --reporter=jest-ctrf-json-reporter displayName: 'Run tests with CTRF'
- script: | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@ctrf-report.json" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"$(Build.SourceBranchName)"}' displayName: 'Upload CTRF to Gaffer' condition: always()Pull Request Pipelines
Section titled “Pull Request Pipelines”For PR pipelines, use the source branch:
trigger: none
pr: - main
steps: - script: npm ci && npm test displayName: 'Run tests'
- script: | # Extract clean branch name from PR source BRANCH_NAME=$(echo "$(System.PullRequest.SourceBranch)" | sed 's|refs/heads/||')
curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $(GAFFER_UPLOAD_TOKEN)" \ -F "files=@test-results/junit.xml" \ -F 'tags={"commitSha":"$(Build.SourceVersion)","branch":"'"$BRANCH_NAME"'"}' displayName: 'Upload to Gaffer' condition: always()Troubleshooting
Section titled “Troubleshooting”Report not uploading
Section titled “Report not uploading”- Verify
GAFFER_UPLOAD_TOKENis set as a secret variable - Ensure
condition: always()is set on the upload step - Check the file path is correct
401 Unauthorized
Section titled “401 Unauthorized”- Check your upload token starts with
gfr_ - Verify the variable name matches exactly (case-sensitive)
Variable syntax
Section titled “Variable syntax”Azure DevOps uses $(VariableName) syntax, not $VARIABLE_NAME. Make sure to use the correct format.
Branch name includes refs/heads/
Section titled “Branch name includes refs/heads/”Use $(Build.SourceBranchName) instead of $(Build.SourceBranch) for clean branch names.
Next Steps
Section titled “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 · CircleCI · Jenkins · Bitbucket