Skip to content

Sigil CI Integration for GitHub Actions

Sigil ships with a first-class GitHub integration via the sigil ci command. It evaluates a PR, posts a status check, optionally comments, and, in auto mode with earned trust, triggers the merge queue.

Terminal window
sigil ci owner/repo#42 --service api

This does, in order:

  1. sigil eval against the PR ref vs the merge-base baseline.
  2. sigil decide to resolve ALLOW/REVIEW/BLOCK.
  3. Posts a GitHub commit status with the decision and a link to the eval report.
  4. (Optional) Posts a PR comment with the lossy feedback.
  5. (Optional) Enqueues the PR in the merge queue on ALLOW.
.github/workflows/sigil.yml
name: sigil
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
evaluate:
runs-on: ubuntu-latest
permissions:
contents: read
statuses: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install sigil
run: curl -fsSL https://runsigil.com/install.sh | sh
- name: Evaluate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AGE_KEY: ${{ secrets.SIGIL_AGE_KEY }} # age identity that decrypts holdouts
run: |
sigil ci ${{ github.repository }}#${{ github.event.pull_request.number }} \
--service api \
--comment \
--auto-merge
[ci]
status_context = "sigil/api"
comment = true
auto_merge = true
  • status_context — the GitHub status check name. Protected branches match this to require the check.
  • comment — post the lossy feedback as a PR comment.
  • auto_merge — on ALLOW, enqueue the PR in the GitHub merge queue. ALLOW needs auto mode and earned MEDIUM trust.
sigil ci <pr-ref> --service <svc>
--github-api-url <url> # override — useful for testing with wraith digital twins
--dry-run # compute, report, but don't post status or comment
--comment # post PR comment with lossy feedback
--auto-merge # enqueue on ALLOW
--sha <sha> # override head SHA detection
--control-ref <ref> # trusted control ref (default origin/main)

If sigil decide fails for any reason (no ledger, git error, OPA error, ledger append error), sigil ci fails closed. The decision is REVIEW, or BLOCK when the eval shows behavioural failures with satisfaction below 0.5. It is never ALLOW, and auto-merge never runs. The status reads sigil: decide failed, needs review, and the JSON report carries decide_error. Before 0.36.0, a decide error fell back to the raw eval counts and could ALLOW.

Configure your protected branches (typically main) to require the sigil/<service> status check. Sigil will post success for ALLOW, failure for BLOCK, and pending→success/failure as the eval runs for REVIEW (the decision is surfaced in the description).

While a service is in shadow mode, leave the check non-required so you can see decisions without enforcing them. This is how you calibrate, and how the service earns its first trust level, before you turn the gate on.

A PR that changes Sigil’s own inputs (.sigil/ except .sigil/types/, scenarios/ or any [[scenarios]] root, .github/, action.yml, or a CODEOWNERS file) REVIEWs with governance_files_changed in every mode, because in CI Sigil reads its policy from the PR’s tree. Protect those paths with CODEOWNERS.

The policy mode caps the decision independently of findings: only auto can ever ALLOW, so a clean eval under shadow, advisory, or an unset mode returns REVIEW. sigil ci says which it is. A capped clean run posts sigil: REVIEW — clean (8/8 passed); capped by shadow mode (ceiling: review) and the PR comment carries the shadow_mode_cap rationale; a REVIEW with real findings keeps its failure/regression counts and carries no cap vocabulary. Exit codes and commit-status states are the same either way (a capped REVIEW is still exit 1 / failure). --format json exposes the same facts as policy_mode, mode_ceiling, mode_capped, and mode_cap_reason, so a job can branch on a cap without parsing prose.

For local or CI testing without hitting the real GitHub API, point --github-api-url at a wraith twin of the GitHub API. Sigil’s integration tests use exactly this pattern.