ProdgatorDocs
Pipelines

Any CI

Record runs, send reports and attestations, and hold a release for approval from CircleCI, Buildkite, Jenkins or any other CI system, with the prodgator-report command line.

GitHub Actions, GitLab CI, Bitbucket Pipelines and Azure Pipelines have their own report steps. Any other CI system uses the command line (or the API directly) to tell Prodgator about a run, send its reports and, before a deployment, ask a Prodgator gate for approval.

Everything sent this way is self-reported. Prodgator cannot check it against the CI system, so it is labeled that way everywhere and is kept apart from verified data. See What self-reported means.

What you can do

  • Record a run: its repository, commit, status and link.
  • Send a job's summary, test results, coverage, SBOMs, scan results, custom attestations and artifacts.
  • Hold a deployment until a Prodgator gate approves it.

Runs from other CI systems appear on the Pipelines page as Other CI, followed by the CI system's name, for example "Other CI · CircleCI". They count toward your plan's monthly run and pipeline limits, counted apart from the runs your connected providers send, so other CI can never use up the runs your providers need. A pipeline counts once per CI system.

Credentials

A pipeline signs in with one of two credentials. Both work on every plan.

OIDC trust (recommended)API key
What the pipeline holdsA short-lived token the CI system signs for each jobA secret you store in the CI system
Where you set it upOrganization > Integrations > Other CIOrganization > API keys, scope
Leak riskA token expires within the age you set and only matches the claims you bound it toWorks until it expires or you revoke it
Set in the pipeline as

The CLI reads a key only from an environment variable. There is no flag that takes the key itself, so it never appears in a command line or a process list. Name a different variable with (or for a token). When both are set, the token is used.

OIDC trust

A trust tells Prodgator which tokens to accept. An Org admin adds one under Organization > Integrations > Other CI. A preset fills in CircleCI, Buildkite, Jenkins (OIDC provider plugin) or self-managed GitLab; replace the parts in angle brackets with your own values. A preset maps only the claims that match what sends from that CI system: CircleCI maps the repository and ref, Buildkite the commit and the run id (), self-managed GitLab the repository, ref, commit, pipeline id and actor, and Jenkins nothing. If you add a claim map entry, make sure it gives the same value the command line sends, or every request is refused.

FieldWhat it holds
IssuerThe claim of your tokens, written exactly as the CI system writes it. Must be an https URL.
AudienceThe claim the pipeline asks for. Use , which the presets fill in. An issuer and audience pair can belong to only one organization. An audience on a Prodgator host must name your own organization id.
Bound claimsAt least one claim that a token must carry, written as an exact value or a pattern with . A token must match every row.
Claim mapOptional. Which claim gives the repository, branch or tag, commit, run id, attempt and actor. A value in a request that disagrees with the token is refused. A template such as builds the repository from two claims.
Longest token ageHow old a token may be, in seconds. Default 3600, at most 86,400.
Signing keysOptional. Paste a JWKS (up to 10 keys) only when Prodgator cannot reach the issuer, such as a Jenkins server on a private network. Otherwise Prodgator fetches the keys from the issuer.

Why a bound claim is required: some issuers, such as Buildkite's, sign tokens for every customer, and anyone can ask for a token with any audience. A bound claim such as is what ties a token to your account. Choose one that names your tenant, with an exact value.

On these shared issuers Prodgator requires at least one of the listed claims with an exact value (no ), and a saved trust without one accepts no tokens:

IssuerClaims that name your tenant
, ,
, , ,
, , ,
, ,
, , ,

For any other issuer Prodgator cannot tell whether it is shared, so the dialog reminds you to bind a claim that names your organization, project or repository.

Prodgator accepts tokens signed with RS256, RS384, RS512, ES256 or ES384, with , and set. Test on the trust loads the issuer's signing keys and reports the result. It never accepts a token. You can have up to 10 trusts. Deleting a trust stops its tokens right away.

API key

Create a key under Organization > API keys with the scope. A key holds no other scope, cannot read data and cannot approve a deployment, so a leaked key can only send CI data. It is available on every plan, including those without API access. See API keys.

Limit what a key can report to: add a repository allowlist of patterns, such as , and use a 90-day expiry or shorter. Rotate the key when someone who could read the CI secrets leaves.

Fork builds

A pull request from a fork can run your pipeline with a modified script. Do not give fork builds the key. The CLI refuses to send an API key from a pull request build it detects as a fork, unless you pass . Set the key in a context or environment that fork builds cannot read, and prefer an OIDC trust with a bound claim that fork builds do not have.

Detection fails closed: a pull request build counts as a fork unless the CI names the source repository and it is this one.

  • CircleCI: a build with a variable, on a branch, or a pull request build with no branch.
  • Woodpecker and Drone: every event ( included) without a source repository variable that matches.
  • TeamCity and a CI the CLI does not know: the environment does not say where a pull request comes from, so a pull request build is always treated as a fork. Mark one with , (for example ) or a ref.

The run model

Each command creates the run in Prodgator or finds it when it already exists, so no state passes between steps and a retried step does no harm. A run is identified by the CI system, the CI's run id and the attempt.

CommandWhat it does
Records the run as (or with ). A run still open after (5 to 4320, default 360) is settled as .
Sends the summary, JUnit results, attestations and artifacts. This is the default when no command is given.
Settles the run as , , , or .
Opens a deployment request and waits for the decision. See Release gates.

A run started with moves to running when a later command of the same attempt (, or ) reaches Prodgator. A finished attempt cannot go back to running. A higher attempt number adds an attempt to the same run, and a lower one is refused.

, and print a warning and exit 0 when Prodgator cannot be reached, so a Prodgator outage does not fail your build. Add to fail the step instead. Write the value: with no value means false. A usage error (an unknown command, an extra argument, without or , a missing or ) always exits 1, whatever says, so a typo in a gate step cannot let a deployment through.

Flags

The CLI reads the run from the CI system's own variables where it knows them (CircleCI, Buildkite, Jenkins, Drone, Woodpecker and TeamCity). These flags, or their variables, set or override them, and are required in a CI system the CLI does not recognize.

FlagMeaning
Short id of the CI system, for example
Repository URL, or . A URL that carries a user name or password is refused.
Full commit hash
Branch or tag
The CI system's id for the run
Attempt number, 1 to 999
https link to the run in your CI system
Pipeline name shown in Prodgator
What started the run: , , , , or (env ). A pull request this way counts as a fork build
Job id for the report; for , keeps two deploying jobs apart
Use this mode even where GitLab, Bitbucket or Azure is detected

On GitHub Actions, GitLab CI, Bitbucket Pipelines and Azure Pipelines the CLI keeps its provider behavior. Report options (, , , and the rest) are the same as in Run reports. The package README lists every option.

CircleCI

Put in a context or project environment variable.

jobs:
  test:
    docker: [{ image: cimg/node:22.11 }]
    steps:
      - checkout
      - run: npx --yes @prodgator/report@1 run start
      - run: npm ci && npm test
      - run:
          when: always
          command: npx --yes @prodgator/report@1 report --junit 'test-results/*.xml'
  deploy:
    docker: [{ image: cimg/node:22.11 }]
    steps:
      - checkout
      - run: npx --yes @prodgator/report@1 gate --environment production
      - run: ./deploy.sh
      - run: npx --yes @prodgator/report@1 run finish --status success

To use an OIDC trust, mint a token with your Prodgator audience: .

Buildkite

Buildkite's token issuer is shared by every customer, so bind the trust to your (the Buildkite preset does).

steps:
  - label: test
    command: npm ci && npm test
    artifact_paths: "test-results/*.xml"
  - wait: ~
    continue_on_failure: true
  - label: report
    command:
      - buildkite-agent artifact download 'test-results/*.xml' .
      - export PRODGATOR_OIDC_TOKEN="$$(buildkite-agent oidc request-token --audience https://app.prodgator.io/ci/<organization-id>)"
      - npx --yes @prodgator/report@1 report --junit 'test-results/*.xml'
  - wait
  - label: deploy
    command:
      - export PRODGATOR_OIDC_TOKEN="$$(buildkite-agent oidc request-token --audience https://app.prodgator.io/ci/<organization-id>)"
      - npx --yes @prodgator/report@1 gate --environment production
      - ./deploy.sh

keeps Buildkite from expanding the command when the pipeline is uploaded. A Buildkite build is one run, with the run id .

Jenkins

pipeline {
  agent any
  environment { PRODGATOR_API_KEY = credentials('prodgator-api-key') }
  stages {
    stage('Test') {
      steps { sh 'npm ci && npm test' }
      post { always { sh "npx --yes @prodgator/report@1 report --junit 'test-results/*.xml'" } }
    }
    stage('Deploy') {
      steps {
        sh 'npx --yes @prodgator/report@1 gate --environment production'
        sh './deploy.sh'
      }
    }
  }
  post {
    success { sh 'npx --yes @prodgator/report@1 run finish --status success' }
    failure { sh 'npx --yes @prodgator/report@1 run finish --status failure' }
  }
}

Jenkins gives the repository and commit through the Git plugin (, ). In a pull request build the CLI refuses the API key unless the build is known not to come from a fork (), or you pass . This is separate from the older Jenkins integration, which sends signed build events.

Any other shell

Name the CI system and the run yourself.

export PRODGATOR_API_KEY="$SECRET_FROM_YOUR_CI"
pg() {
  npx --yes @prodgator/report@1 "$@" \
    --ci-system mybuild \
    --repository https://git.example.com/acme/api \
    --commit "$(git rev-parse HEAD)" \
    --ref "$BRANCH" \
    --run-id "$BUILD_ID" \
    --run-url "https://build.example.com/runs/$BUILD_ID"
}
pg run start
if make test; then status=success; else status=failure; fi
pg report --junit 'build/test-results/*.xml'
pg run finish --status "$status"

Release gates from any CI

A pipeline can hold a deployment until a Prodgator gate approves it. The step is . It opens a deployment request, notifies the gate's approvers, and polls until someone decides. It exits 0 only when the request is approved. A rejection, an expired request, the timeout (, 1 to 720 minutes, default 60) or any error exits 1, so the deploy step after it does not run. It fails closed.

Gates need a plan that includes them (Business and above, see Plans). For the request to find a gate, a gate must cover the environment:

  1. On the Gates page, open the gate and choose to link a deployment environment, then pick Other CI as the source.
  2. Enter the repository as the CI system reports it, as , for example , and the environment name, for example . A repository URL works too. Environment names cannot contain , or .
  3. Optionally enter the CI system id, for example . A link with no CI system covers every CI system for that repository and environment.

Auto-include patterns can cover these environments as well, but only a pattern that starts with , for example . The rest is matched against with the same wildcards. Other patterns, such as , never pull in an environment from other CI. See Set up a gate.

If no gate covers the environment, the step exits 1 and says so. Prodgator records the refused environment so it is offered when you link one.

Approvers decide in Prodgator exactly as for other deployments, under the gate's approvers and policies. A key cannot approve. Prodgator cannot enforce self-approval rules or flag a self override for these deployments: the actor the pipeline names is self-reported, and Prodgator cannot tie it to a person. When that matters, require approvers from a group that does not hold the CI credential. The decision the CLI sees is one of:

DecisionMeaningCLI
A person or policy approved itExits 0
RejectedExits 1
Nobody decided in timeExits 1
A later attempt of the run opened its own requestExits 1
WaitingKeeps polling

Only means deploy. If you call the API yourself, treat any other answer, and any error, as a refusal.

Job logs can be public, so the answer never names who decided or carries their note: and are always null. Open the request link to see them in Prodgator.

The request has its own poll token, valid for 12 hours, that can read that one gate and nothing else. The CLI uses it for polling, so a leaked job log cannot be used to record runs. When a request is old, open it again: returns the same request with a new token. Finishing the run with a final status settles its approved deployments.

What self-reported means

Prodgator labels a run, report or attestation from another CI system as self-reported, with a dashed Self-reported badge that names the credential (a key or an OIDC trust) that sent it. The CI system's own claims are the only evidence, so Prodgator treats the data with less trust than a provider's:

  • Policies ignore self-reported results by default.
  • A policy counts them only when its rule sets Count self-reported results from other CI (not verified). This option exists on the Attestations, Code coverage, Test results and SBOM rules.
  • A self-reported result is used only when the commit has no matching result from your connected provider. Provider results come first, and only the policy whose own rule opts in sees it.
  • It never satisfies build provenance. The and attestation kinds are refused from other CI. The build provenance rule has no option to accept it.
  • It never counts as GitHub, GitLab, Bitbucket or Azure provenance, never joins a change's lineage and never binds to a run a provider webhook reported.
  • Default and seeded policies do not change. A person who edits a policy turns the option on, rule by rule.
  • A person named as the actor in a self-reported run is not counted as a contributor for billing.
  • Deployments from other CI never count toward deployment metrics: SPACE metrics, AI impact and the compliance deploy frequency SLA leave them out, even when a gate covers the environment.
  • Runs from other CI never count toward run metrics: the dashboard and DORA metrics, SPACE pipeline runs, success rate and CI duration, the AI impact CI failure rate, and the compliance and checks leave them out. They still show on the Pipelines page and the dashboard's recent runs.

Limits

  • Self-reported results are re-checked by a policy at the usual times: when a report arrives for the same run, repository and commit, when someone approves, and on the scheduled re-check. A result filed for a repository that is linked to a provider repository counts at that repository's next evaluation and does not wake its deployments or pull request gates.
  • No pull requests: other CI systems send no pull request events, so Prodgator posts no status or comment on a pull request for them and cannot require their check on a branch.
  • No actions in the CI system: Prodgator cannot cancel a run, re-run a job or roll back a deployment in a CI system it cannot reach. Do that in your CI system.
  • Metrics: runs and deployments from other CI are left out of every metric (see What self-reported means), so an organization that only uses other CI sees empty pipeline and deployment metrics.
  • Request limits: 120 requests per minute per credential, and 300 requests per minute for the organization across every request (apart from the run reports your connected providers send). Polling a gate is limited to 12 requests a minute. Expect with a header and retry with backoff.
  • Each key or OIDC trust can create up to 2,000 new runs a day (UTC). Updates, resends and new attempts of a run do not count. Over the limit, creating a run answers with a header until the next day. waits out a of up to 60 seconds and stops at once on a longer one, so a job is never held until the next day.
  • Reports use the same per-plan limits as other run reports, and the same retention as pipeline runs.
  • A request body can be up to 2 MiB.

Learn more

On this page