Browse docs
Docs /install/github-action
Install

GitHub Action

The Action installs @izri/cli, runs the scope check, optionally triggers a test run, and reports the result. It is a composite action — no JavaScript bundle, just bash — so it adds a few seconds to a workflow, not a build step.

name: izri
on:
  pull_request:
    branches: [main]

jobs:
  izri:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: legendify-dev/izri/apps/github-action@v1
        with:
          api-token: ${{ secrets.IZRI_API_TOKEN }}

fetch-depth: 0 is required

The scope check diffs your head against origin/<base>. A shallow clone — the actions/checkout default — has no base ref to resolve, so the check fails before it starts. Either set fetch-depth: 0 or fetch the base ref explicitly.

Inputs

Input Required Default What it does
api-token yes — Your Izri API token with the tests:run and tests:read scopes. Starts with izri_. Store it as a repository secret, never inline.
api-url no https://api.izri.ai Override for self-hosted installs.
project-id no (auto) Project ULID. When omitted the CLI resolves it from your git origin remote.
mode no both scope, tests, both, upload, or verify.
junit-file with upload — JUnit XML your test step produced.
coverage-file no — LCOV or Cobertura report, for diff coverage.
coverage-format no (from extension) lcov or cobertura.
skipped-reason no — With upload, records an explicit empty run instead of results.
test-command with verify — Shell command that runs {files} (the selected test files, shell-quoted) and writes JUnit XML to {junit}.
max-test-files no 50 With verify: budget. Over it only the PR's changed test files run; still over, a budget skip is recorded.
base-ref no (auto) Git base to diff against. Resolves to origin/${{ github.base_ref }} on pull requests and origin/<default-branch> on pushes.
wait-for-results no true When mode includes tests, block until the run reaches a terminal status.
fail-on-finding no true Exit non-zero on hard scope findings or a non-passing test run.
cli-version no latest Version range for @izri/cli. Pin to a tag for reproducible CI.

Choosing a mode

  • scope is deterministic and fast. No test run, no waiting. Good as a required check on every PR.

  • tests triggers a run on Izri's runner and (by default) waits for it. Playwright projects only.

  • upload sends the JUnit and coverage your own test step produced. This is the usual choice: most teams already run tests in CI, and Izri judges that run instead of repeating it. Give the job permissions: id-token: write (and contents: read, since naming any permission drops the defaults): the CLI sends the job's id-token with the upload, and that is what lets Izri trust the evidence. Without it the upload is recorded as untrusted. See izri/tests.

    jobs:
      tests:
        runs-on: ubuntu-latest
        permissions:
          contents: read
          id-token: write
        steps:
          - uses: actions/checkout@v4
            with:
              fetch-depth: 0
          - run: pnpm test -- --reporter=junit --outputFile=junit.xml
            continue-on-error: true
          - uses: legendify-dev/izri/apps/github-action@v1
            with:
              api-token: ${{ secrets.IZRI_API_TOKEN }}
              mode: upload
              junit-file: junit.xml
  • verify runs the revert check with izri verify. It runs the test files that depend on the change at head, and again with the changed source files restored to the merge base, each in a throwaway git worktree. Then it uploads both results for izri/hallucination. They are judged against the izri/tests evidence for the same commit, so add it next to an upload step (or keep the Izri runner). Install dependencies first, and give the job the same id-token: write permission.

          - run: pnpm install --frozen-lockfile
          - uses: legendify-dev/izri/apps/github-action@v1
            with:
              api-token: ${{ secrets.IZRI_API_TOKEN }}
              mode: verify
              test-command: pnpm vitest run {files} --reporter=junit --outputFile={junit}
  • both is the default and what you want unless you have a reason otherwise.

Pin cli-version for reproducibility

latest means a CLI release can change your CI behavior without a commit in your repository. Pin it once you're past evaluation:

with:
  api-token: ${{ secrets.IZRI_API_TOKEN }}
  cli-version: '0.1.0'

Outputs

Output Value
scope-alignment-score Alignment score 0–100. Empty string when mode=tests.
scope-findings-count Total scope findings, all severities. Empty string when mode=tests.
scope-hard-findings-count Findings at severity: error — the only category that blocks by default.
test-run-id The Izri test-run identifier. Empty string when mode=scope.
verification-run-id With verify: the recorded revert check. Empty string otherwise, or when it was not recorded.

Outputs are empty strings, not zeros, when their mode didn't run. Test for emptiness before doing arithmetic:

      - uses: legendify-dev/izri/apps/github-action@v1
        id: izri
        with:
          api-token: ${{ secrets.IZRI_API_TOKEN }}

      - name: Comment when alignment is low
        if: steps.izri.outputs.scope-alignment-score != '' &&
            fromJSON(steps.izri.outputs.scope-alignment-score) < 60
        run: echo "Scope alignment is ${{ steps.izri.outputs.scope-alignment-score }}"

Making the verdict binding

Until you require it, the check reports but enforces nothing.

Settings → Branches → Branch protection rules → Require status checks to pass, then add Izri (the single check run whose conclusion is the izri/quality verdict).

There is only one check to require. Izri carries the aggregated izri/quality verdict, which already handles skipped signals — visual legitimately skips when no UI route changed, and the verdict accounts for that. If you previously required izri/quality (or any izri/… child check), replace it with Izri; those contexts are no longer reported and a rule pinning them would block every merge.

Non-blocking evaluation mode

To surface findings without failing anyone's build while you evaluate:

with:
  api-token: ${{ secrets.IZRI_API_TOKEN }}
  fail-on-finding: false

The check still publishes and the sticky comment still appears — the workflow just won't go red.

Reading this with an agent? /docs/install/github-action.md serves the raw markdown.

Edit this page on GitHub →All docs