What you’ll get
One comment on every pull request, one fold per job, each outbound destination under the process that opened it. Adding one dependency looks like this:
The comment on reference#29, folded. Open the fold for the tree; from the second recorded commit on, the tree is a comparison.
Install the GitHub App
Install Garnet Runtime Review
Pick the repos you want recorded. The App is what posts the comment.
Add the Action to your workflow
Workflow files live in Token: app.garnet.ai → Settings → API Tokens. Save it in the repository under Settings → Secrets and variables → Actions → New repository secret, named
.github/workflows/ in your repository. Add the step to the file that already builds your pull requests, or create .github/workflows/ci.yml if you have none.GARNET_API_TOKEN, and pass it as api_token. When it is set, the action uses it as-is and requests no OIDC token. It is the only repository secret you provision on this path. GitHub supplies github_token itself. See What Garnet sees.Pin the sensor. jibril_version defaults to v2.17.0, the current latest stable Jibril release. Setting it explicitly keeps the sensor pinned in the workflow file where Dependabot and reviewers can see it. The action verifies the release bundle’s checksums and its Sigstore attestation before the sensor runs.One step per job, first among your steps. The sensor has to be running before your workload does, so nothing earlier in the job is recorded. Adding the step twice in one job records nothing extra. A checkout above it is recommended: without one the step resolves your workflow file through the GitHub API instead.The action posts no comment. contents: read is the only grant it needs. The comment on the pull request is the GitHub App’s, posted under its own installation; without the App you get the job summary and the profile in app.garnet.ai, and no comment.Runners. Linux x86_64 runners with systemd and sudo. GitHub-hosted ubuntu-latest is the tested path, and self-hosted Linux x86_64 works on the same terms. On any other platform or architecture, including arm64 and macOS and Windows runners, the action logs a warning, skips, and the job records nothing. Errors the action catches are logged as warnings and do not fail the job. Runner-by-runner: Coverage.Fork pull requests. Repository secrets are not exposed to workflows triggered from a fork, so api_token arrives empty and no id-token: write is granted. The action skips recording with a warning that names the missing credential, writes the same explanation to the job summary, and the job continues unrecorded.Without a token (GitHub OIDC). Order of precedence: a non-empty
api_token is optional. Leave it out and grant id-token: write; the action requests a GitHub OIDC token in the job and exchanges it with Garnet, so there is no secret to store or rotate. The run log confirms the path with Using OIDC workflow token for control-plane requests.api_token wins and no OIDC token is requested; OIDC is tried only when api_token is empty and the job has id-token: write. Already on GARNET_API_TOKEN? Keep it — upgrading changes no permissions.Open a pull request
The GitHub App posts one Runtime Review comment per pull request; it appears while jobs are still running and fills in as each finishes, with one collapsed fold per recorded job. Each recorded job also gets a Garnet Execution Summary in its Actions job summary, written by the action itself.
Read it
A clean
npm install of registry dependencies reaches registry.npmjs.org. Git or tarball dependencies and install scripts that fetch binaries add destinations of their own, so read the tree against what your dependencies explain. A destination that nothing in the job accounts for is what you are looking for. The comment records; whether it matters is your call.How to read the Execution Profile in full: The Execution Profile.See it live
One real recorded pull request. It is a separately verified exhibit, not a replay of the snippet above. Its own workflow and sensor version are not the ones pinned here. Both links open without an account.The pull request
garnet-runtime-review-reference#29 adds one npm dependency. The comment on it records one job at head
23bbd88, compared with 5a6561f.Its Execution Profile
The public report the comment links to: 12 destinations, with the addresses, ports, and steps the comment leaves out.
Action reference
Inputs
Inputs
This is v2.3.0, the pinned release above.
Outputs
Outputs
The Runtime Review pull request comment and Actions job summary present views of the Execution Profile. Some profiles also have a separately published, logged-out public run report on
app.garnet.ai. The action itself posts no comment, no GitHub Check, and sets no commit status.Errors the action catches are logged as warnings. This does not guarantee that every sensor or runtime failure leaves the job unaffected.Permissions
Permissions
The action never needs
pull-requests: write: the pull request comment is posted by the GitHub App under its own installation. It does not require contents: write, actions: write, or access to any repository secrets beyond the token you pass. Full model: Security and permissions.Pinning
Pinning
Floating tags like
@v2 can move after you adopt them. For supply-chain hygiene, pin to the commit SHA of the latest release.The canonical SHA is always available at garnet.ai/pins (human-readable) and garnet.ai/pins.txt (machine-readable). Both auto-update when a new release ships.The Actions job summary
The Actions job summary
The post step appends the job’s record to the GitHub Actions job summary as the Garnet Execution Summary, headed by that title. It is the per-job surface and does not depend on the GitHub App. What it carries:
- Workload Summary — a table of the recorded context: the profile ID linking to the run’s public run report, workflow, repository, branch, pull request, commit, who triggered it, run and job, and the matrix job index where there is one.
- Network Egress Summary — a table keyed by execution chain, one row per recorded chain with the destinations it reached; repeated destination names within a chain are collapsed. A collapsed Full recorded tree underneath renders the job’s whole tree in the comment’s grammar, with canonical (never defanged) names.
- Telemetry — where the sensor’s own counts agree with the profile, one sentence:
Network telemetry observed N unique domains, M destinations, C connections, and F flows. - The permalink — View this job’s Execution Profile in Garnet →, last.
preview: true adds a recorded-context preview and Garnet-managed assertions. That shape is unstable and can change without a major version bump.The PR comment is the cross-job conversation surface; the job summary is the per-job record.Troubleshooting
Troubleshooting
Start from the Garnet step’s own log — it names which of these you are in, and the answers below differ.The step logs
Garnet skipped this Runtime Review because no authentication mechanism was available — api_token was empty and no OIDC token could be requested. Common on fork pull_request and Dependabot runs. Pass api_token from a secret or grant id-token: write; the job continues either way. Dependabot runs read secrets.* from the Dependabot secrets store, so add the same token under Settings → Secrets and variables → Dependabot to record them.The step logs Garnet action encountered an unexpected error and will continue without runtime monitoring — this is the action’s general error handler. Read the specific error logged just before it.The step skips with a warning about the platform — the runner is not Linux x86_64, or systemd or sudo is missing. The log says which. Runner by runner: Coverage.Permission denied — Jibril attaches eBPF programs at the kernel level, which requires sudo during install. ubuntu-latest runners include it by default.No Garnet Execution Summary in the Actions run — set debug: true to upload Jibril’s logs as artifacts, then read jibril.log and jibril.err. If the sensor failed to start, the job summary carries a “not recorded” block with startup diagnostics instead of the record.No PR comment at all — the comment is posted by the GitHub App; install it on the repository. The job summary and the profile in app.garnet.ai do not depend on the App, and no workflow permission changes this.The comment exists but stays in the waiting state — check the Garnet step’s log for the sensor’s install and start lines and whether the job summary was written. The record can be complete while the comment is not: open the run’s public run report or the dashboard to see it. If the comment never fills in, check that the repository is one the App is installed on and that the token you passed belongs to an organization authorized for it.The post step takes minutes — the sensor is flushing its Execution Profile before it stops; on busy jobs this has been observed at 1–3 minutes (about 150 s on pnpm’s test job). Lower stop_timeout_seconds to bound it, at the cost of a possibly incomplete flush.(step: "<unknown>") labels, or a chain under the wrong step — step attribution is best effort. The chain was recorded; only its step is uncertain. See Coverage.The headline names a commit that is not your PR head — on pull_request runs the comment and profile label the synthetic merge commit GitHub checked out. The other limits of the record (no completeness claim, short-lived activity missed by sensor startup or cadence, matrix undercount) are listed in Coverage.Debug mode: