ProdgatorDocs
Pipelines

Send a custom attestation

Check an outside system such as ServiceNow or Jira from CI, send the result to Prodgator as a custom attestation, and require it in a release policy

Policies read only their input document. They cannot call ServiceNow, Jira or any other system. To gate a release on an outside check, such as an approved change ticket or an open release window, a CI job does the check and sends the result to Prodgator as a attestation. A release policy then requires that attestation.

  1. A CI job runs on the commit you will deploy, checks the outside system, and writes the result as an attestation.
  2. The Prodgator report action (GitHub Actions), component (GitLab CI), pipe (Bitbucket Pipelines) or task (Azure Pipelines) sends it.
  3. A release policy requires a trusted attestation with that name and status , with the Attestations form rule or in Rego.

The attestation

A custom attestation is a JSON object. Pass one object or an array of up to 20:

{ "kind": "custom", "name": "change-ticket", "status": "pass", "data": { "title": "Change ticket", "details": { "id": "CHG0031337", "approval": "approved" } } }
FieldMeaning
.
1 to 100 characters. The policy matches on it, so keep it stable, for example or .
, , or . Required for : Prodgator does not derive it. Only satisfies a policy.
Any JSON object, up to 32 KiB for the whole attestation. Policies read it as . and are shown on the run and on the approval card.

Prodgator stores the attestation for the job's commit. A deployment of that commit sees it in , whichever workflow run sent it.

GitHub Actions

The action's input takes inline JSON or the path of a JSON file. This job asks the ServiceNow Table API whether a change request is approved and sends the answer. Store the ServiceNow credentials as secrets and pass the change number however your team tracks it (here, a repository variable):

jobs:
  change-ticket:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - name: Check the change request in ServiceNow
        env:
          SN_INSTANCE: ${{ vars.SN_INSTANCE }}
          SN_USER: ${{ secrets.SN_USER }}
          SN_PASSWORD: ${{ secrets.SN_PASSWORD }}
          CHANGE: ${{ vars.CHANGE_NUMBER }}
        run: |
          approval=$(curl -sf -u "$SN_USER:$SN_PASSWORD" \
            "https://$SN_INSTANCE.service-now.com/api/now/table/change_request?sysparm_query=number=$CHANGE&sysparm_fields=approval" \
            | jq -r '.result[0].approval // "missing"')
          if [ "$approval" = "approved" ]; then status=pass; else status=fail; fi
          jq -n --arg status "$status" --arg id "$CHANGE" --arg approval "$approval" \
            '{kind: "custom", name: "change-ticket", status: $status, data: {title: "Change ticket", details: {id: $id, approval: $approval}}}' \
            > change-ticket.json

      - uses: prodgator/prodgator-action@v1
        with:
          attestations: change-ticket.json

lets the action authenticate with GitHub OIDC; there is no API key. The action has no inputs for a check name, status or message: everything about the attestation goes in the JSON. See Run reports for every input.

Run this job before the job that waits for approval. A job that uses an environment with required reviewers does not start until someone approves, so an attestation sent from it, or from a job that needs it, arrives too late. See If your pipeline has approvals.

GitLab CI

Write the file in a job, keep it as an artifact, and pass its path to the component's input:

include:
  - component: gitlab.com/prodgator/prodgator-component/report@1
    inputs:
      attestations: change-ticket.json

change-ticket:
  stage: test
  script:
    - ./check-change-ticket.sh > change-ticket.json
  artifacts:
    when: always
    paths:
      - change-ticket.json

Bitbucket Pipelines

Write the file in the step and pass its path to the pipe's variable:

- step:
    name: Change ticket
    oidc:
      audiences:
        - https://api.prodgator.io
    script:
      - ./check-change-ticket.sh > change-ticket.json
    after-script:
      - pipe: prodgator/prodgator-pipe:1.0.0
        variables:
          ATTESTATIONS: change-ticket.json

Azure Pipelines

Write the file in a job and add the task after it, with its path in :

- script: ./check-change-ticket.sh > change-ticket.json
- task: ProdgatorReport@1
  inputs:
    attestations: change-ticket.json

For a classic pipeline, see Run reports.

Require it in a policy

Without Rego, add an Attestations rule with kind Custom and name , and leave Only count trusted sources on.

In a Rego policy, the module is and defines , a list of objects with , , and (see the result contract). Policies use Rego v1 syntax (, ) with no :

package prodgator.policy

approved := [a |
	some a in input.attestations
	a.kind == "custom"
	a.name == "change-ticket"
	a.trusted
	a.status == "pass"
]

ticket_status := "pass" if count(approved) > 0
else := "fail"

results := [{
	"rule": "change_ticket",
	"status": ticket_status,
	"blocking": true,
	"reason": "needs a trusted, passing change-ticket attestation for this commit",
}]

In a mixed policy, the same check is a custom rule in that defines ; see the example on the Rego page.

Do not check times in Rego. For a release window or a freeze, the CI job checks the window and sends a attestation the same way.

Examples written here or by Ask Prodgator are not compiled. Draft with AI in the policy editor compiles, tests and loads a draft; see Draft a policy with AI.

On this page