Run reports
Send job summaries, test results, attestations and artifacts from GitHub Actions, GitLab CI, Bitbucket Pipelines and Azure Pipelines to Prodgator
The Prodgator report action for GitHub Actions, the Prodgator component for GitLab CI, the Prodgator pipe for Bitbucket Pipelines and the Prodgator task for Azure Pipelines each send a job's summary, test results, coverage, SBOMs, scan results, custom evidence and artifacts to Prodgator. The first three authenticate with their CI system's OIDC token; Azure Pipelines uses the pipeline's job token. No API key to create or rotate.
Why
GitHub does not expose a job's through any API. The only way to get it, or test results and other evidence, into Prodgator is a step in the workflow that sends them directly. The action does that.
GitHub Actions
Add and a step that runs after your tests and build:
permissions:
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
- run: npm run build
- uses: prodgator/prodgator-action@v1
if: always()
with:
junit: 'reports/**/*.xml'
artifacts: 'dist/**'Action inputs
| Input | Default | Description |
|---|---|---|
| (none) | Markdown to send. Default: what earlier steps of the job wrote to . | |
| (none) | Path to a markdown file in the workspace to send instead. | |
| Report name within the job. Give each step its own name to send several reports from one job. | ||
| Job identifier. | ||
| (none) | In matrix jobs, pass so each leg keeps its own report. | |
| (none) | Globs of JUnit XML files, summed into one attestation. | |
| (none) | Globs of files to upload, newline or comma separated. | |
| (none) | One attestation or an array, as inline JSON or the path of a JSON file. See Attestation kinds and status and Send a custom attestation. | |
| (none) | Path of a file or a Prodgator ownership JSON file. See Ownership reports. | |
| Prodgator API URL. | ||
| the origin of the URL in use | OIDC audience. Set it only if you need something other than the API origin. | |
| Fail the step when the report cannot be sent, instead of warning and continuing. |
Outputs: (the Prodgator report id) and (a link to the run in Prodgator). These are the only inputs: an attestation's kind, name, status and data go in the JSON.
sends the report even when an earlier step fails, so a broken build still shows its test results. A or attestation can also name the scanner's own output file (for example a SARIF file); the action uploads it with the report and links it from the attestation. See the action README for every input, all six attestation kinds, matrix jobs and troubleshooting.
GitLab CI
Include the Prodgator component. It adds a job that runs after every other stage, even when a job fails, with the artifacts of the earlier jobs:
include:
- component: gitlab.com/prodgator/prodgator-component/report@1
inputs:
junit: test-results/**/*.xml
artifacts: dist/*.tgz
attestations: attestations.jsonMake the files you report job artifacts (). For a summary, append Markdown to in a job and keep it as an artifact. The project's top-level group must be connected to Prodgator. See the component README for every input and for reporting from inside a job with .
Bitbucket Pipelines
Give the step an OIDC token for the Prodgator API and run the pipe in , which also runs when the step fails:
- step:
name: Test
oidc:
audiences:
- https://api.prodgator.io
script:
- npm test
after-script:
- pipe: prodgator/prodgator-pipe:1.0.0
variables:
JUNIT: 'test-results/**/*.xml'The workspace must be connected to Prodgator. Prodgator names the report after the step. See the pipe README for every variable.
Both the GitLab component and the Bitbucket pipe run the public image at their own version. Each version is tagged , and . The image holds the same CLI as the npm package . If your runners can only pull from an internal registry, mirror that image there, or run inside a job instead.
Azure Pipelines
Azure DevOps has no OIDC token Prodgator can verify, so the report is authenticated with the pipeline's own job token (). Prodgator checks the token with Azure DevOps once to confirm which organization, project and build it belongs to, and discards it. The organization must be connected to Prodgator.
Install the Prodgator report extension from the Visual Studio Marketplace into your organization, then add the task after your tests. sends the report even when an earlier step fails:
# azure-pipelines.yml
- task: ProdgatorReport@1
condition: always()
inputs:
junit: 'test-results/**/*.xml'
artifacts: 'dist/*.tgz'Without the extension, run the CLI in a script step and map the job token yourself. The token is not in the step's environment unless you add it:
- script: npx --yes @prodgator/report --junit 'test-results/**/*.xml'
condition: always()
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)If the token is not mapped, the CLI stops and tells you to add the line. The public image holds the same CLI, for agents that cannot reach npm.
Do not use that image as an Azure Pipelines container job ( on a job). It is Alpine with an , which Azure DevOps cannot run its agent steps in. Run it from a script step on the agent instead, with the sources mounted and the variables the CLI reads passed through:
- script: |
docker run --rm \
-v "$(Build.SourcesDirectory):/work" -w /work \
-e TF_BUILD -e SYSTEM_ACCESSTOKEN -e SYSTEM_COLLECTIONURI -e SYSTEM_TEAMPROJECTID \
-e SYSTEM_JOBID -e SYSTEM_JOBATTEMPT -e SYSTEM_JOBDISPLAYNAME \
-e BUILD_BUILDID -e BUILD_SOURCEVERSION -e AGENT_NAME -e BUILD_SOURCESDIRECTORY=/work \
--entrypoint prodgator-report \
ghcr.io/prodgator/report:1.2.3 --junit 'test-results/**/*.xml'
condition: always()
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)Use a version tag from the image's tags (, or ). passes a variable from the step's environment into the container; is how the CLI knows it runs in Azure Pipelines.
Task inputs
| Input | Default | Description |
|---|---|---|
| (none) | Markdown to send. | |
| (none) | Path to a markdown file in the workspace to send instead. | |
| Report name within the job. Give each report from one job its own name. | ||
| the pipeline's job name | Name shown for the job. | |
| (none) | JSON object that tells matrix legs apart, for example . | |
| (none) | Globs of JUnit XML files, one per line, relative to the sources directory. | |
| (none) | Globs of files to upload with the report, one per line. | |
| (none) | Path to a JSON file with extra attestations. See Send a custom attestation. | |
| (none) | Comma separated variable names whose values become in the report. | |
| Prodgator API URL. | ||
| Off by default: the job token is only sent to and addresses. Turn it on only if your Prodgator runs on its own https address. | ||
| Fail the task when the report cannot be sent, instead of warning and continuing. |
The run's page in Prodgator shows the Summary and attestations once the report arrives.
Classic pipelines
A classic (designer) build pipeline sends the same report from one Command line task after your test tasks:
-
In the agent job settings, turn on Allow scripts to access the OAuth token.
-
Add a Command line task with this script:
npx --yes @prodgator/report --junit "test-results/**/*.xml" -
Under the task's Environment Variables, add with the value .
-
Under Control Options, set Run this task to Even if a previous task has failed.
Classic release pipelines are not supported: Prodgator does not read them, and a report from a release does not map to a run. Use YAML pipelines with environments for deployments.
If your pipeline has approvals
Send the report before the first step that waits for a person, so the run in Prodgator shows the summary and attestations while the approval is pending, and the AI release risk can read them. If the pipeline has no manual or approval-gated steps, the end of the pipeline is the right place and the examples above already do that. A report cannot include results of steps that run after the approval, such as the deployment itself.
Your CI system, not Prodgator, knows which steps wait, so you place the report yourself:
-
GitHub Actions: a job that uses an environment with required reviewers does not start until someone approves. Report from the build or test job, or from a job that the build and test jobs, never the deploy job.
jobs: build: runs-on: ubuntu-latest steps: - run: npm test - uses: prodgator/prodgator-action@v1 if: always() with: junit: 'reports/**/*.xml' deploy: needs: build runs-on: ubuntu-latest environment: production # required reviewers steps: - run: ./deploy.sh -
GitLab CI: the component's job runs in , which does not start while a manual or protected-environment job is blocking the pipeline. Add to the report job so it starts as soon as the jobs that make your files finish:
include: - component: gitlab.com/prodgator/prodgator-component/report@1 inputs: junit: test-results/**/*.xml prodgator-report: needs: [build, test] # not the gated deploy job deploy: stage: deploy environment: production # protected environment with approvers script: ./deploy.shThe job gets artifacts only from the jobs in . As an alternative, set the input to a stage that sits before the deploy stage in your list. The default stays because it is valid in every pipeline.
-
Bitbucket Pipelines: run the pipe in the of a step before the or permissioned deployment step, not in the gated step or after it.
- step: name: Build and test oidc: audiences: - https://api.prodgator.io script: - npm test after-script: - pipe: prodgator/prodgator-pipe:1.0.0 variables: JUNIT: 'test-results/**/*.xml' - step: name: Deploy deployment: production trigger: manual script: - ./deploy.sh -
Azure Pipelines: put the report in a job of a stage before the stage that deploys to a gated environment, not in the deployment job. A stage waits for the environment's approvals and checks, the Prodgator gate included, before it starts.
stages: - stage: Build jobs: - job: Test steps: - script: npm test - task: ProdgatorReport@1 condition: always() inputs: junit: 'test-results/**/*.xml' - stage: Deploy dependsOn: Build jobs: - deployment: Production environment: production strategy: runOnce: deploy: steps: - script: ./deploy.sh
Secrets in summaries
GitHub masks secrets in the step summaries it stores, and the action sends those masked copies. GitLab masked variables and Bitbucket secured variables are masked in job logs only: a file a job writes keeps what was written to it. The GitLab component and the Bitbucket pipe replace the values of the OIDC token, the GitLab job token family and every variable you list in (GitLab) or (Bitbucket) with in the summary and in attestations. Azure Pipelines secret variables are masked in logs only, the same way. The Prodgator task and CLI replace the job token and every variable you list in with . Artifact files are sent as they are: do not upload files that contain secrets.
Files outside the workspace
The action, component, pipe, task and CLI read files only from the job's workspace (the checkout directory): the summary file, the attestations file, JUnit files, scanner files, the ownership file and artifacts. A file whose real path is somewhere else, such as a symlink in the repository that points at a file on the runner, is skipped with a warning and the report is sent without it. An attestations file that is skipped stops the report the same way a missing one does. Nothing under a directory is read. Write a summary file inside the workspace, not in the runner's temp directory: an absolute path outside the workspace is skipped too.
What appears where
- The pipeline card and the pipeline detail page show a Summary section with the job's markdown summary and its attestations.
- A deployment's approval card shows the same attestations, plus any recorded for the release's commit from other runs, in an evidence row.
Attestation kinds and status
Prodgator derives the status of every attestation kind except and , so a report can't claim while its own numbers say otherwise:
| Kind | when | when |
|---|---|---|
| no failed or errored tests | any failed or errored test | |
| , or with no threshold set | ||
| always, unless the input says | the input says | |
| no count at or above (default ) is greater than zero, or when is | a count at or above is greater than zero | |
| the input's own | the input's own | |
| the input's own | the input's own | |
| always | never |
Each attestation is . is required for and ignored for the kinds Prodgator derives. To bring an outside check such as a ServiceNow change ticket into a release policy, see Send a custom attestation.
Ownership reports
Code owners rules on pull requests read your file from an ownership report. Send it with the input of the GitHub Action, from a workflow that runs on pushes to your base branches:
on:
push:
branches: [main]
jobs:
ownership:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: prodgator/prodgator-action@v1
with:
ownership: .github/CODEOWNERSThe action uploads the file as an artifact of the report and adds an attestation with (, or for a file) and (the file's path). Once the upload completes, Prodgator reads the file and stores it for the commit. For a push to a branch it also becomes the branch's latest report, and open pull requests into that branch are evaluated again (up to 20, most recently updated first).
The file can be at most 256 KB with 5,000 rules. Owners are or ; email owners are skipped. When the file cannot be read, the report shows a warning such as and nothing is stored. A file uses this format:
{ "version": 1, "rules": [{ "pattern": "infra/**", "owners": ["@acme/platform"] }] }Untrusted sources
A report from a or event, or from a whose head repository is a fork, is stored but marked untrusted. These contexts run with the base repository's identity while commonly processing fork-supplied data. On GitLab, a merge request pipeline whose source project is a fork, and external pull request pipelines, are marked untrusted. Bitbucket does not run pull request pipelines for forks in the target repository, so Bitbucket reports are trusted. The attestations rule of a release policy counts only trusted attestations by default; whoever edits the policy can turn that off per rule.
Limits by plan
| Free | Team | Business | Enterprise | |
|---|---|---|---|---|
| Reports per run | 25 | 100 | 250 | 1,000 |
| Largest artifact file | 25 MB | 250 MB | 1 GB | 5 GB |
| Artifact bytes per run | 100 MB | 1 GB | 5 GB | 20 GB |
| Upload bytes per organization per month | 2 GB | 50 GB | 250 GB | unlimited |
Every plan is also capped at 20 attestations and 50 artifacts per report, and 300 report requests per minute per organization.
Retention
Reports, attestations and artifacts follow your plan's data retention, the same as pipeline runs: 7 days on Free, 30 on Team, 90 on Business, 365 on Enterprise. Moving to a shorter retention does not shorten data already written; it expires on the old schedule.
Learn more
- Action README: every input, all attestation kinds with examples, matrix jobs and troubleshooting.
- Component README: every input for GitLab CI.
- Pipe README: every variable for Bitbucket Pipelines.
- Send a custom attestation: check ServiceNow, Jira or a release window in CI and require the result in a policy.
- Deployment Approvals: where attestations show up on a pending deployment.
- Release Policies: require passing attestations before a deployment is approved.