Wire a Pipeline to the Passport
Make a deployment wait for a valid signed passport: mint the deploy token, add the secret, choose enforce or warn for each environment, and read what the Studio says about your pipelines afterwards.
Set it up, once per repository
- Generate the pipelines.Repositories → DevOps → Create → Propose pipelines. Under Artefact Passport check, choose Enforce or Warn only for each environment. Review the pull request on GitHub and merge it yourself; its description says what you chose.
- Mint the deploy token. On Repositories, in the repository’s Deploy token section, choose Create. Only the studio’s owner can. The token is shown once: copy it now.
- Add it to GitHub. In the repository: Settings → Secrets and variables → Actions → New repository secret. Name it
PW_DEPLOY_TOKEN. - Optional: pin the signing key. Add a repository variable named
PW_PASSPORT_KEY_IDSholding the key id shown beside Signed by on a signed passport. The check then refuses a passport signed by any other key.
Enforce or warn
| Mode | When the check does not pass | Proposed for |
|---|---|---|
| Enforce | The deploy does not start | Production |
| Warn only | The job says what is wrong and the deploy continues | Dev, where a merge usually deploys before its release is approved |
The choice is written into the workflow. To change it, generate the pipelines again with the other choice and merge the new pull request. Do not edit the check by hand — see Passport check changed below.
What happens on a deploy
- A passport-check job runs first, before the deploy job and before the environment’s approval. It finds the release that covers the commit, fetches its signed passport and verifies it on GitHub’s runner: the signature, that the commit is one the passport covers, that nothing is unmet, and that no exception has run out. An approver sees this answer before approving.
- The deploy job runs the same check again as its first step. This is the answer that counts: it is taken as the deploy starts, so an approval that waited a day never rides on yesterday’s answer.
- The deploy runs, if the check passed or the environment is warn only.
- The last step reports the deployment to the release. A deploy that fails is not reported.
The verifier is written into the workflow file and compared with its hash before it runs. Nothing is downloaded at run time.
What the deploy token can do
Read the signed passport of a release that carries one of this repository’s commits, and report a deployment or a bill of materials for one. That is all. It cannot read or change the repository, your cloud, or anything else in the studio, and it is not the repository connection’s access token. The Studio keeps only a hash of it. Minting again replaces it and the old one stops at once; revoke it from the same section.
What DevOps → Pipelines tells you
The Studio reads your workflow files on the default branch and says, for each environment, where its deploys stand. The words are always shown with the state, never as a colour alone.
| It says | Meaning | What to do |
|---|---|---|
| Passport enforced | Every deploy to this environment waits for the Studio’s own check, and a failed check holds it | Nothing |
| Passport warn only | The check runs and reports; the deploy continues either way | Generate again with Enforce when you are ready |
| Passport check changed | A check is there, but the job differs from what the Studio generates — so the Studio no longer vouches for it | Generate the pipelines again, or undo the edit |
| No passport check | A deploy to this environment has no check | Generate the pipelines, or add the job |
| Pipelines not read | A workflow file could not be read. The page names the file and the reason. The Studio then vouches for no environment of the repository, because the unread file may deploy anywhere | Rewrite the part named, as below |
| (environment not read) | A deploy job names its environment in a form the Studio cannot read. It counts against every environment | Write the name as one plain line |
| (no environment) | A deploy job names no environment. It has its own row and does not count against the named ones | Name the environment |
| Calls a workflow elsewhere | A job calls a reusable workflow in another repository, which the Studio does not read. What the page says about each environment does not cover it | Check that workflow yourself |
Why a file reads “not read”
The Studio reads workflow files with one YAML parser and GitHub runs them with another. Where the two could read a file differently, the Studio does not guess: it reads nothing from that file rather than risk vouching for a deploy that GitHub would run another way. The common causes:
| In the file | Write instead |
|---|---|
| A quoted value that runs over more than one line | The value on one line, or as a block (run: |, if: >-) |
| An unquoted value whose next line looks like a key or a list entry | The value on one line, or as a block |
Anchors, aliases or merge keys (&x, *x, <<:) | The repeated text written out |
An unquoted if: !cancelled(), which YAML reads as a tag | if: ${{ !cancelled() }} |
A job or key named yes, no, on, off, true, null or a number | The name in quotes |
| A repeated key, or two jobs whose ids differ only by case | One of each |
| A tab outside a script or quoted text; more than one YAML document | Spaces; one document per file |
| An environment named by an expression, an empty value, or over several lines | environment: production, or environment: with a name: |
An unquoted value that simply continues on the next line — a long if: condition, or run: npm ci with --no-audit beneath it — is read. A deploy job whose own if:, environment:, runs-on: or needs: runs over lines is read but never vouched for.
Why a check reads “changed”
The Studio compares the check job and the deploy job’s first step character for character with what it generates. You may add, remove and reorder your own run: steps after the check, add comments, name the job, and move a generated action to another version tag. Anything else reads as changed. The ones that matter:
if: or continue-on-error — a step with if: always() runs even when the check failed. Put such a step in another job.A pipeline generated before the check’s wording was last revised still holds a deploy exactly as a new one does and still reads as enforced or warn only. The page lists the improvement Generate the pipeline again for the current passport check; do it when convenient.
What DevOps → Runs tells you
For a run, the panel shows what the check printed: whether it passed, what is unmet, and which exceptions are no longer in force. Treat it as the job’s own account. Anyone who can change a workflow can print those lines, so the panel decides nothing: whether the job passed is GitHub’s conclusion, and whether a release is cleared is its signed passport. Where the two disagree the panel says so.
When the check does not pass
| It says | What to do |
|---|---|
The repository secret PW_DEPLOY_TOKEN is not set | Add it as a repository secret |
| Product Workbench refused the deploy token | Mint a new one and update the secret |
| No release covers this commit | Usual in dev. In production: release from the Studio, which tags the release’s own commit, or approve a release that covers the commit |
| The release has no signed passport | Issue one from the release page |
| The release is not approved | Approve it again |
| The signed passport does not verify | Stop. Tell Productivity Workbench support; do not deploy |
| The passport records something not met | Open the release’s passport, put it right, then issue the passport again |
| An exception is no longer in force | Renew it on the gate or meet the item, then issue the passport again |
| Product Workbench could not be reached | Run the job again. An enforced deploy is held meanwhile — that is what enforced means |
Reporting deployments from your own pipeline
A generated pipeline reports each successful deploy itself. From any other pipeline, the Deploy token section on Repositories gives the command to run after a deploy: it sends the environment, the commit, the workflow run and the time. Each report is listed on the release and recorded in its evidence ledger. A report for a commit the release’s signed passport does not cover is refused. Reports are evidence: they do not change the release’s status.
Reporting a software bill of materials
A pipeline can also tell the Studio that a bill of materials exists for a commit. The pipelines the Studio generates do not carry this step: you add it to your own build job, which does not affect how the passport check reads.
- Produce the bill of materials in your build as you already do, in CycloneDX or SPDX, and keep it as a build artefact or a release asset.
- Copy
scripts/report-sbom.mjsinto the repository and run it after the file is written, withPW_DEPLOY_TOKENavailable to the step. - Put the work package on a release first — a draft is enough. A report is recorded against a release.
push, not pull_request. On a pull-request workflow GitHub reports a temporary merge commit, which is not one the release delivers.What the check is not
It sits beside branch protection, tag protection and required reviewers on an environment, and does not replace them. Whoever can change a workflow can remove the check — which is why the Studio shows you where it is missing or changed. Protect v* tags and the default branch.