Description
When cargo budget-report --check finds that a function has blown its budget, the only place that shows up is the job log and the exit code. A reviewer looking at the pull request sees a red X and has to open the log to find out which function and by how much.
SARIF is how GitHub ingests findings from a tool. Upload a SARIF file and the findings appear in the Security tab, and — when the finding carries a file and line — as annotations on the diff. For a budget check, that turns "CI failed" into "transfer is 12% over its CPU limit" in the place the reviewer is already looking.
The sibling project soroban-cost-linter already emits SARIF 2.1.0. Matching its shape means anyone running both tools gets a consistent experience, and there is a working implementation to read.
What "done" looks like
- A flag emits a valid SARIF 2.1.0 document. Validity is checkable — the schema is published, and GitHub rejects malformed uploads, so validate rather than eyeballing it.
- One result per budget breach in
--check mode. A run with no breaches produces a valid SARIF document with an empty results array, not an empty file — GitHub treats a missing file as an upload failure.
- Each result carries the package, the function, the metric, the measured value and the configured limit, in a message a reviewer can act on without opening anything else.
- Results have a stable
ruleId per metric, so GitHub can track a finding across runs rather than reporting it as new every time.
- Where a source location for the function can be determined, include it so the finding annotates the diff. Where it cannot, say so in the PR and emit the result without a location rather than inventing one — a wrong line number is worse than none.
- The tool's exit code is unchanged. SARIF is an additional output, not a replacement for the failure signal.
- Documented in
docs/src/ci_cd_integration.md with the github/codeql-action/upload-sarif step needed to actually get it into the Security tab.
Implementation guidelines
-
Create a branch: git checkout -b feat/report-sarif-output
-
Key files: cargo-budget-report/src/cli.rs, main.rs for where --check results are assembled.
-
Reference implementation: cargo-cost-lint/src/output_formatters.rs in soroban-cost-linter — the emit_sarif function and the structs around it. Borrow the shape; you do not need to share code across repositories.
-
Add a new module rather than extending an existing one, and append your #[arg] to the end of BudgetReportArgs. Several open issues add flags to that struct.
-
Prefer building the JSON with serde_json structs over hand-writing the document. The existing implementation in the sibling repo does this.
-
Test the upload path end to end if you can — a fork with the upload step wired up is the only way to be sure GitHub accepts the document. If you cannot, say so and show schema validation instead.
-
Out of scope: reporting anything other than --check breaches. Measurements that are within budget are not findings.
PR guidelines
- Get assigned before starting.
- Show the SARIF validating, and a screenshot of the Security tab if you managed the upload.
- PR description must include:
Closes #[this issue].
Contact & Support
📋 Before you start
Please read our Code Quality Standards in CONTRIBUTING.md. Before submitting a PR, ensure you run:
- cargo fmt --all -- --check
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
Description
When
cargo budget-report --checkfinds that a function has blown its budget, the only place that shows up is the job log and the exit code. A reviewer looking at the pull request sees a red X and has to open the log to find out which function and by how much.SARIF is how GitHub ingests findings from a tool. Upload a SARIF file and the findings appear in the Security tab, and — when the finding carries a file and line — as annotations on the diff. For a budget check, that turns "CI failed" into "
transferis 12% over its CPU limit" in the place the reviewer is already looking.The sibling project
soroban-cost-linteralready emits SARIF 2.1.0. Matching its shape means anyone running both tools gets a consistent experience, and there is a working implementation to read.What "done" looks like
--checkmode. A run with no breaches produces a valid SARIF document with an emptyresultsarray, not an empty file — GitHub treats a missing file as an upload failure.ruleIdper metric, so GitHub can track a finding across runs rather than reporting it as new every time.docs/src/ci_cd_integration.mdwith thegithub/codeql-action/upload-sarifstep needed to actually get it into the Security tab.Implementation guidelines
Create a branch:
git checkout -b feat/report-sarif-outputKey files:
cargo-budget-report/src/cli.rs,main.rsfor where--checkresults are assembled.Reference implementation:
cargo-cost-lint/src/output_formatters.rsinsoroban-cost-linter— theemit_sariffunction and the structs around it. Borrow the shape; you do not need to share code across repositories.Add a new module rather than extending an existing one, and append your
#[arg]to the end ofBudgetReportArgs. Several open issues add flags to that struct.Prefer building the JSON with
serde_jsonstructs over hand-writing the document. The existing implementation in the sibling repo does this.Test the upload path end to end if you can — a fork with the upload step wired up is the only way to be sure GitHub accepts the document. If you cannot, say so and show schema validation instead.
Out of scope: reporting anything other than
--checkbreaches. Measurements that are within budget are not findings.PR guidelines
Closes #[this issue].Contact & Support
📋 Before you start
Please read our Code Quality Standards in
CONTRIBUTING.md. Before submitting a PR, ensure you run: