Skip to content

ci: test gate, cargo-deny, Trivy scan, multi-arch, reproducible build, releases - #21

Merged
onelrian merged 3 commits into
mainfrom
ci/9-ci-hardening
Aug 7, 2026
Merged

ci: test gate, cargo-deny, Trivy scan, multi-arch, reproducible build, releases#21
onelrian merged 3 commits into
mainfrom
ci/9-ci-hardening

Conversation

@onelrian

@onelrian onelrian commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Overview

The old pipeline only built and pushed a Docker image: no tests, no lint, no dependency audit, no image scan, single-arch, and a Dockerfile that couldn't build standalone (COPY target/release/signal required CI to have already run cargo build outside the container). This closes all of those gaps.

Closes #9

Key Changes

  • Test job (gates the build job): cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test, cargo-deny (advisories, licenses, bans, sources via deny.toml)
  • Real finding from cargo-deny: caught two current RUSTSEC advisories already in the dependency tree, RUSTSEC-2026-0007 (integer overflow / UB in bytes 1.11.0's BytesMut::reserve) and RUSTSEC-2026-0190 (unsoundness in anyhow's downcast_mut). Bumped both (bytes 1.11.0 to 1.12.1, anyhow 1.0.100 to 1.0.104) in this PR.
  • Dockerfile rewritten as a real multi-stage build: compiles inside a rust:1-slim-bookworm builder stage (dependency-compile layer cached separately from source changes), copies only the binary into the debian:bookworm-slim runtime stage. docker build . now works standalone, verified locally.
  • Both base images pinned to a digest, not a floating tag
  • Trivy scan gates every push/PR on HIGH/CRITICAL, with ignore-unfixed: true. Verified locally that debian:bookworm-slim carries several HIGH/CRITICAL OS-package CVEs with no upstream fix (will_not_fix/fix_deferred, e.g. zlib1g CVE-2023-45853). Gating on those unconditionally would leave CI permanently red for nothing this project can act on. Anything with an actual available fix still fails the build.
  • Publishing only happens on a vX.Y.Z tag push, not on every main merge. PRs and main-branch pushes build and Trivy-scan a single-arch image for fast feedback, but nothing gets pushed and no QEMU/multi-arch build runs for an image that would just get thrown away. latest only ever moves when a real version tag is pushed, so it always points at something actually released, not just "whatever's on main right now."
  • Multi-arch (linux/amd64, linux/arm64) via buildx + QEMU, only on the publish path
  • v*.*.* tag pushes now cut a GitHub Release (softprops/action-gh-release, auto-generated notes). The trigger existed before but nothing consumed it.
  • Bumped all Docker-related actions to their current major versions (checkout v4 to v7, login-action v3 to v4, metadata-action v5 to v6, setup-buildx-action v3 to v4, build-push-action v5 to v7), verified against each action's own docs, not assumed
  • Renamed the workflow file docker-publish.yml to ci.yml to match what it now actually does
  • Also fixed a real bug this PR's own -D warnings gate exposed: tests.rs had a redundant mod tests { ... } wrapper inside a file already included via mod tests;, harmless before, a hard clippy failure now that module_inception is a fatal warning instead of a note

Verification

cargo test/clippy -D warnings/fmt all clean (28 tests, zero warnings after the tests.rs fix).

cargo deny check after the dependency bumps:

advisories ok, bans ok, licenses ok, sources ok

Built the new Dockerfile locally end to end:

$ docker build -t auditbridge:local-test .
...
#21 naming to docker.io/library/auditbridge:local-test done
$ docker run --rm auditbridge:local-test
ERROR signal: Configuration error: NETBIRD_API_TOKEN or NETBIRD_API_TOKEN_FILE is required

(exits cleanly on missing config, confirming the binary itself runs correctly, not just that the image built)

Trivy against that same local image:

$ trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 auditbridge:local-test
...
Vulnerabilities: 0

Out of Scope

No version tag is being pushed as part of this PR or issue. The first real v1.0.0 release happens only once every remaining issue (Helm chart, docs rewrite) is done and verified, this PR only makes sure the pipeline behaves correctly whenever that happens.

Closes #9

Reproducible multi-stage Dockerfile (docker build . now works
standalone), digest-pinned base images, and a test job gating the
build. Bumped bytes/anyhow to clear two real RUSTSEC advisories
cargo-deny caught. Tag pushes now cut a GitHub Release.
@onelrian onelrian self-assigned this Aug 7, 2026
Fixes the module_inception warning clippy -D warnings now gates on
in CI (added in this same PR), harmless before but a hard build
failure now that the lint is enforced instead of just noted.
Building and pushing a multi-arch manifest on every merge (and every
PR, unpublished) wasted CI time on QEMU arm64 compiles nobody used.
Now PRs/main only build+scan single-arch; publishing (and latest)
only happens on a real vX.Y.Z tag.
@onelrian
onelrian merged commit af314eb into main Aug 7, 2026
3 checks passed
@onelrian
onelrian deleted the ci/9-ci-hardening branch August 7, 2026 11:05
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.

ci: harden pipeline, tests, lint, dependency audit, image scan, multi-arch, reproducible build

1 participant