SARIF is how Shipmoor findings become first-class citizens of your code-review surface: annotations on the PR diff, entries in the Security tab, and a history of what was found when. Shipmoor emits standard SARIF 2.1.0 from the same evidence as its human and JSON output.
Producing SARIF
shipmoor scan --diff origin/main...HEAD --sarif --output shipmoor.sarif
Every finding carries its rule ID (e.g. python.phantom_import), severity, location, message, and remediation text, plus a stable fingerprint — so code scanning can track a finding across pushes instead of re-opening it as new each time. Rule metadata links back to the rule’s documentation.
When --sarif writes to stdout instead of a file, stdout contains only the SARIF document (diagnostics go to stderr), so it pipes cleanly.
Uploading to GitHub code scanning
- name: Run Shipmoor
run: |
shipmoor scan --diff origin/main...HEAD \
--sarif --output shipmoor.sarif --fail-on high
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: shipmoor.sarif
Two details do the heavy lifting:
if: always()— the upload must run even when the scan step failed the job. The runs you most want in the Security tab are exactly the ones where the gate fired.security-events: write— the job needs this permission for the upload.
The full workflow (and the composite-action form) is in GitHub Actions.
Exit codes: gate signal vs. error
The scan’s exit code and the SARIF are designed to be consumed together:
| Code | What happened | Is the SARIF valid? |
|---|---|---|
0 | Clean | Yes — complete (and empty of findings) |
1 | Findings met the --fail-on gate | Yes — complete. This is the gate working, not an error. |
2 | Usage or config error | No report produced |
3 | Scan crashed | No report produced |
So the correct CI shape is: let exit 1 fail the check (that’s its job) while still uploading the report; reserve “tooling broke” alerts for 2 and 3, where no report exists.
If you want code-scanning evidence without a blocking check, run with --fail-on none — full SARIF, always exit 0 on a successful scan.
Beyond GitHub
The SARIF is standard: GitLab, Azure DevOps, and most code-quality dashboards ingest SARIF 2.1.0 directly. For systems that prefer raw data, the JSON contract (shipmoor.scan.v1) carries everything the SARIF does and more (subtypes, change_status, fingerprints).
Next
- GitHub Actions — the full workflow.
- CI overview — the recommended gate pattern.
- Output formats & exit codes — the complete output contract.