Skip to content

feat(ci): add fleet-wide charm security scan report workflow - #485

Merged
lucabello merged 9 commits into
mainfrom
feat/local-charm-scan-report
Aug 18, 2026
Merged

feat(ci): add fleet-wide charm security scan report workflow#485
lucabello merged 9 commits into
mainfrom
feat/local-charm-scan-report

Conversation

@lucabello

Copy link
Copy Markdown
Contributor

Summary

Adds _local-charm-scan.yaml, a prototype workflow (following the repo's existing _local-*.yaml staging convention) that walks every charm release in manifest.yaml, clones it at its release branch, runs just scan, and publishes a single grouped report to the run's job summary.

Changes

  • build-matrix job flattens manifest.yaml's charm releases into a matrix (charm, repo, path, branch, cycle, LTS).
  • scan job (one leg per charm release, fail-fast: false) clones the charm at its release branch and runs just scan, capturing output for the report.
  • report job aggregates all results into $GITHUB_STEP_SUMMARY, grouped by release cycle, with a collapsible details block per charm showing its LTS status and raw scan output.
  • A charm's branch not existing fails that leg and the overall run; vulnerabilities found by just scan are reported but do not fail the run.

Notes

Manual trigger only (workflow_dispatch), no schedule yet. Opened as a draft since this is a first pass at a _local- prototype, not yet promoted to a real workflow name.

Adds _local-charm-scan.yaml, a manually-triggered workflow that walks
every charm release in manifest.yaml, clones it at its release branch,
runs 'just scan', and publishes a report grouped by cycle to the run's
job summary. A charm's branch not existing fails the run; vulnerabilities
found by the scan itself are reported without failing it.
Groups the scan matrix by repo+branch instead of by charm, so repos
hosting several charms at the same track (litmus-operators,
loki-operators, mimir-operators, pyroscope-operators, tempo-operators)
are cloned once and just scan is run once per charm subdirectory
against that single clone. Cuts the matrix from 39 legs to 32 on the
current manifest, and the gap grows as those monorepos gain charms.
A shared clone failure is now recorded against every charm it backs,
each still reported individually.
Groups the scan matrix by repo alone instead of repo+branch. A single
'git clone --depth=1 --no-single-branch' fetches shallow history for
every branch of a repo in one network round trip; each release branch
is then just a local 'git checkout' against that same clone, run
sequentially, so repos gain multi-branch support at zero extra clone
cost. Leg count is unchanged today (32, since no charm currently has
more than one active branch), but a repo with several supported tracks
will no longer need one runner per track. A branch-level checkout
failure is now attributed only to the charms on that branch, and a
whole-repo clone failure is attributed to all of them.
Adds two justfile recipes, following the repo's existing pattern of
manifest-querying just recipes (list-charms, list-expired, ...) and
python-shebang recipes (charms.just's tracks/changelog):

- list-scan-matrix: the same repo-grouped manifest query that used to
  be inline jq in the build-matrix job.
- scan-repo <repo>: the clone/checkout/scan/record loop that used to be
  a ~60-line bash block in the scan job. Runs standalone for local
  debugging, e.g. 'just scan-repo canonical/litmus-operators'.

_local-charm-scan.yaml's scan job shrinks to checkout + install deps +
'just scan-repo ""' + upload. As a side effect, scan-repo exiting
non-zero on a real checkout failure now drives job failure directly,
so the any-failed output and the dedicated 'Fail on checkout error'
step are no longer needed.

Verified list-scan-matrix and scan-repo directly (not just via
actionlint): scan-repo against a real single-branch repo surfaced a
real uv audit finding end-to-end, and against a temporarily
multi-branched manifest entry it correctly scanned two real branches
from one clone and reported a fabricated bad branch as checkout-failed
without disturbing the other two results.
Splits the charm-scan recipes (scan-matrix, scan-repo, and the new
build-report) out of the root justfile into security.just, mod-imported
as 'mod security' - so they're invoked as just security::scan-repo etc.
build-report replaces the report job's inline Python heredoc in
_local-charm-scan.yaml: it reads a directory of result JSON files
(recursively, so both a flat local directory and the one-artifact-
per-repo layout download-artifact produces work) and prints the same
markdown report to stdout, redirected into $GITHUB_STEP_SUMMARY.

_local-charm-scan.yaml's three jobs now do essentially nothing but
checkout + install deps + one 'just security::<recipe>' call each.

Also gitignores charm-checkout/ and results/, the working directories
these recipes create when run locally outside CI.
Parallelizing the charm scan across one runner per repo (up to 33
matrix legs) bought little: each scan is just a shallow clone plus a
few lightweight `uv audit` runs, so most of the wall time was runner
startup and per-leg artifact upload/download rather than actual
scanning.

Replace the build-matrix/scan-matrix/report job split with a single
job that loops `scan-repo` over every repo sequentially via a new
scan-fleet recipe, then builds the report directly from the local
results directory. Drops the GitHub Actions matrix and all per-repo
artifacts.
scan-fleet -> scan-charms, scan-repo -> scan-charm-repo, both grouped
under "charms" instead of "security"; build-report grouped under
"report". Also calls out that scan-charms runs uv audit.
@lucabello
lucabello marked this pull request as ready for review August 18, 2026 08:23
@lucabello
lucabello requested a review from a team as a code owner August 18, 2026 08:23
@lucabello
lucabello merged commit 74e83ce into main Aug 18, 2026
1 check passed
@lucabello
lucabello deleted the feat/local-charm-scan-report branch August 18, 2026 08:36
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.

1 participant