CI workflow
What the Greenroom job does, which parts you control, and why it is a reusable workflow.
The quickstarts give complete workflows for web and iOS. Both have one job, and that job is Greenroom's reusable workflow:
jobs:
greenroom:
permissions:
contents: read
id-token: write
uses: justindc100/greenroom-action/.github/workflows/pass.yml@3b2754eafa6ed5f4d122a0bb3ea7dee7005f65b8
with:
platform: web
app-id: my-app
prepare: |
npm ci && npm run build
npx --yes serve@14 -l 4173 -s dist > serve.log 2>&1 &
target-url: http://127.0.0.1:4173/
artifact-path: distThe uses: line above pins runner 0.3.17 (commit 3b2754eafa6ed5f4d122a0bb3ea7dee7005f65b8, trusted since 2026-09-09). The SHA is the identity Greenroom trusts and the value to record; the release name is for matching changelogs and issues written in release numbers.
Why a reusable workflow
Greenroom identifies a run by the workflow identity in the job's GitHub OIDC token: which workflow file ran, at which commit. Only Greenroom's own published commits are trusted. If the job were defined in your repository, its identity would change with every pull request and Greenroom could not tell a reviewed workflow from one a pull request rewrote. Defining the job in Greenroom's repository at a pinned commit means a pull request can change what gets built, but never what happens to the build afterwards.
What the job does
- Checks out the pull request, and fetches the Greenroom runner at the same commit as the workflow file.
- Reads
.greenroom/environment.jsonand.greenroom/state-contract.jsonfrom the PR's base commit. A PR that edits.greenroom/still runs under the old policy; the new policy takes effect once it merges. This is what prevents a careless or malicious PR from allowlisting a production host or deleting the oracle that would catch its bug. - Runs your
preparescript, which builds and (for web) serves the preview. - Computes a content digest of
artifact-path, so the report can say exactly which build was walked. - Runs the pass and posts the handoff as a Check run.
Inputs
| Input | Meaning |
|---|---|
platform | web or ios. Determines which networkControl values the manifest may declare. |
app-id | Stable slug for this app in Greenroom. |
prepare | Shell that builds and, for web, serves the preview. Background the server with &. |
target-url (web) | The preview URL to walk. Its host must be in the manifest allowlist. |
artifact-path | The served directory (web) or the .app bundle (iOS). Digested for the report. |
app, device (iOS) | Bundle id and the simulator device name to create. |
runs-on | ubuntu-latest (default) or macos-15 for iOS. |
goal | Optional bounded validation goal. |
allowed-hosts | Optional comma-separated allowlist override; must match the manifest. |
environment-manifest, state-contract | Paths inside your repository (defaults under .greenroom/), read from the base revision. |
source-upload-allowed | Off by default. Includes bounded patches and a source index so the code locator can attach a source pointer to each finding; Greenroom's workspace policy must also allow it. |
fail-on-infra-error | Off by default. Fails the job when Greenroom cannot complete a run it started (an aborted walk, a workflow failure); the Check reads "Not completed" either way. It does not govern a rejection before a run exists: a manifest, contract, session or input the runner refuses is your repository's setup, always fails the job, and ends the log with the file to edit, since no Check can be posted for a run that was never started. |
Hygiene the examples bake in
- The
uses:line pins Greenroom's workflow to a full commit SHA. Pin a release you have reviewed; Greenroom accepts only published commits. permissionsare minimal:contents: read, andid-token: writeso the job can mint the OIDC token that identifies it to Greenroom. There is no Greenroom secret to store.prepareexecutes repository code inside the CI job. Keep production secrets out of this test job; the reusable workflow authenticates with GitHub OIDC.