ProdgatorDocs
Pipelines

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

InputDefaultDescription
(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 useOIDC 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.json

Make 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

InputDefaultDescription
(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 nameName 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:

  1. In the agent job settings, turn on Allow scripts to access the OAuth token.

  2. Add a Command line task with this script:

    npx --yes @prodgator/report --junit "test-results/**/*.xml"
  3. Under the task's Environment Variables, add with the value .

  4. 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.sh

    The 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 testsany 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/CODEOWNERS

The 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

FreeTeamBusinessEnterprise
Reports per run251002501,000
Largest artifact file25 MB250 MB1 GB5 GB
Artifact bytes per run100 MB1 GB5 GB20 GB
Upload bytes per organization per month2 GB50 GB250 GBunlimited

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

On this page