Skip to content

fix(ci): make the cargo-audit gate fail on a report it cannot parse - #741

Merged
EVWorth merged 3 commits into
mainfrom
claude/fix-729-audit-gate
Oct 5, 2026
Merged

EVWorth merged 3 commits into
mainfrom
claude/fix-729-audit-gate

Conversation

@EVWorth

@EVWorth EVWorth commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Closes #729.

#730 already made scripts/cargo-audit-check.sh exit 2 when jq or cargo-audit is missing, or when cargo audit returns no report. This PR closes the gaps that were left.

Changes

  • Parse failure is now fatal. The findings table still ended in || echo "(parse failed)" and went on to pass. The findings are now parsed first, and the script exits 2 if that fails. Printing happens separately, so head -50 closing the pipe on a long list isn't mistaken for a parse failure (under pipefail it would have been).
  • The advisory DB's age is reported. The script prints the database's last-updated from the JSON report and raises a ::warning:: when it's more than 7 days old. cargo audit fetches before every run, but --no-fetch or fetch = false answers from the copy on disk, and an old copy reports clean. That's the second thing the issue says hid RUSTSEC-2026-0285. This is a warning rather than a failure because the gate's verdict is still right for the data it read. BSD date has no -d, so macOS shows the timestamp without the age.
  • New scripts/test-cargo-audit-check.sh. It plays canned reports through a fake cargo on PATH and covers 10 cases: clean, a real vulnerability, warnings only, more findings than the display shows, jq missing, no report, non-JSON output, findings that don't parse, a stale DB, and the age being shown. It runs in the Lint (workflows) job (which already triggers on scripts/**) and in just lint-workflows, next to the other script tests.
  • The other jq scripts were checked, as the issue asked. issues-review.sh already requires jq up front. check-action-pins.sh and doc-keeper-sweep.sh use gh's built-in --jq, not the jq binary, so none of them has this problem.

Verification

  • scripts/test-cargo-audit-check.sh: 10/10 pass. Against the previous script, 3 fail: unparseable findings, the stale DB and the age display.
  • A real run against src-tauri with cargo-audit 0.22.2 exits 0: "0 real vulnerabilities, 9 non-blocking advisory warning(s)", DB updated yesterday.
  • dprint check and check-documented-commands.sh: clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SCNjpC4VgppHSFs7P6rkZg


Generated by Claude Code

#730 made the gate fail when jq is missing or cargo audit returns no
report. One "could not look" path was left: the findings table still
ended in `|| echo "(parse failed)"` and carried on to a pass. Parse the
findings first and exit 2 if that fails, then print them, so `head`
closing the pipe on a long list is not mistaken for a parse failure.

The gate also now prints when the advisory database was last updated,
and warns when it is over 7 days old. cargo audit fetches before each
run, but --no-fetch or `fetch = false` answers from the copy on disk,
and an old copy reports clean (the second thing that hid
RUSTSEC-2026-0285).

scripts/test-cargo-audit-check.sh plays canned reports through a fake
cargo: clean, a vulnerability, warnings only, more findings than the
display shows, jq missing, no report, non-JSON output, findings that do
not parse, and a stale database. Against the previous script the last
three cases fail. Runs in the workflows lint job and `just
lint-workflows`, beside the other script tests.

The other jq users in scripts/ were checked: issues-review.sh already
requires jq up front, and check-action-pins.sh and doc-keeper-sweep.sh
use gh's built-in --jq, not the jq binary.

Closes #729.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCNjpC4VgppHSFs7P6rkZg

EVWorth commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

Lint (workflows) is red, but not because of this PR's change. The "Check action pins" step fails on:

MISMATCH  dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de — the comment says v1, which is 7e38f4b43b4d

Upstream moved its v1 tag to 7e38f4b43b4db5c8dd498af069a4f6196df1d067, which is also master. The only change is dtolnay/rust-toolchain#186, which retries release-server checksum failures (16 lines in action.yml). The job runs whenever scripts/** or a workflow changes, so every such PR fails here until the pin moves. This PR's own new step never ran, because the job stopped at the pin check. Locally, scripts/test-cargo-audit-check.sh passes 10/10.

Proposed fix: bump all 5 pins of dtolnay/rust-toolchain in .github/workflows/ from 02cb101ec7c40f2c49e1d9714d64511d8e1b74de to 7e38f4b43b4db5c8dd498af069a4f6196df1d067 # v1. It's a supply-chain pin, so I've left the decision to the maintainer rather than pushing it here.


Generated by Claude Code

claude added 2 commits October 5, 2026 02:27
Every job that needs Rust ran two steps: a bash one-liner pulling the
channel out of rust-toolchain.toml, then dtolnay/rust-toolchain to
install it. rustup ships on every GitHub-hosted runner and reads
rust-toolchain.toml itself, so one step does both:

    rustup toolchain install --profile minimal --no-self-update

installs the pinned channel plus the file's components (rustfmt,
clippy), and every later cargo call in the checkout, src-tauri/
included, resolves to it. The release build adds
`rustup target add "$RUST_TARGET"` for its matrix target.

This drops a third-party action from the build path, which is also
what was turning Lint (workflows) red: upstream moved its v1 tag, so
the pin's version comment stopped matching (#741). With no pin there is
nothing to drift or to re-review on each upstream push. Quantco/pixi-pack
made the same change (Quantco/pixi-pack#340).

Given up: the action's new retry on release-server checksum failures.
That only bites while a Rust release is mid-publish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCNjpC4VgppHSFs7P6rkZg
(cherry picked from commit 4a6fb4f)
EVWorth added a commit that referenced this pull request Oct 5, 2026
Every job that needs Rust ran two steps: a bash one-liner pulling the
channel out of rust-toolchain.toml, then dtolnay/rust-toolchain to
install it. rustup ships on every GitHub-hosted runner and reads
rust-toolchain.toml itself, so one step does both:

    rustup toolchain install --profile minimal --no-self-update

installs the pinned channel plus the file's components (rustfmt,
clippy), and every later cargo call in the checkout, src-tauri/
included, resolves to it. The release build adds
`rustup target add "$RUST_TARGET"` for its matrix target.

This drops a third-party action from the build path, which is also
what was turning Lint (workflows) red: upstream moved its v1 tag, so
the pin's version comment stopped matching (#741). With no pin there is
nothing to drift or to re-review on each upstream push. Quantco/pixi-pack
made the same change (Quantco/pixi-pack#340).

Given up: the action's new retry on release-server checksum failures.
That only bites while a Rust release is mid-publish.


Claude-Session: https://claude.ai/code/session_01SCNjpC4VgppHSFs7P6rkZg

Co-authored-by: Claude <noreply@anthropic.com>
@EVWorth
EVWorth merged commit 0afd252 into main Oct 5, 2026
12 checks passed
@EVWorth
EVWorth deleted the claude/fix-729-audit-gate branch October 5, 2026 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P2][bug] cargo-audit-check.sh exits 0 when jq is missing

2 participants