Add comprehensive test coverage for scanner, enrichment, and CLI#2
Merged
Conversation
…sion, CI - pkg/kev: add kev_test.go (13 tests) covering Load, cache TTL, concurrent safety, IsKnownExploited case normalisation, GetInfo, HTTP errors, and malformed JSON. Change cisaKEVURL from const to var so tests can inject a mock server (same pattern as pkg/osv). - pkg/scanner: add oracle fixture (testdata/trivy-fixture.json) pinned to alpine:3.10 with 5 known CVEs across severity levels. Add parse_test.go (9 tests) exercising JSON parsing, severity distribution, FilePath resolution (PkgPath vs target fallback), remediation links, severity filtering, and boundary error cases (rootfs-not-dir, rootfs-nonexistent, SBOM-requires-image) — all without needing Trivy. - pkg/runc: extend runc_test.go with 5 HostVersion tests using the fake-binary-in-PATH pattern — covers Server.Components JSON, top-level Components JSON, runc fallback, malformed docker JSON fallback, and the neither-available graceful empty-return path. - .github/workflows/ci.yml: add CI pipeline — go vet + race-detected unit tests + build on every push/PR; integration scan on push to main. All 8 pkg/* test packages pass with -race -count=1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
… pipeline pkg/kev: export SetURLForTest and ResetForTest so cross-package tests can inject a mock KEV server and clear cache state without duplicating package internals. pkg/report/report_test.go: add 10 new tests — SARIF structural validation (required fields: $schema, version, runs, tool.driver name/version/informationUri, result ruleId/level/message), location inclusion/omission based on FilePath, rule deduplication with multi-finding same CVE, empty-findings SARIF validity. WriteFindingsCSVWithImage: header row, image-as-first-column, RFC 4180 quote escaping for embedded quotes/commas, empty-input guard. pkg/remediate/enrich_integration_test.go: new file with 9 tests wiring real Enrich() against a mock KEV HTTP server — KEV hit → Exploitable="yes" and ExploitInfo populated from shortDesc, KEV hit → severity upgraded to CRITICAL regardless of original severity, KEV miss → Exploitable="no", ransomware=Known → ExploitInfo contains "ransomware" text, offline=true → Exploitable="unknown" without touching KEV. Policy+enrichment pipeline: CRITICAL findings trigger fail-on-severity, zero findings do not trigger, fail-on-count threshold arithmetic, combined severity+count policy evaluated correctly. All 8 pkg/* packages pass with -race -count=1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
…ng docs cmd/cli/main.go: refactor runScan to return int exit code instead of calling os.Exit directly. main() now calls os.Exit(runScan(...)). This minimal change makes the entire CLI orchestration layer testable without subprocess overhead or exec.Command tricks. cmd/cli/main_test.go: 7 new tests using a fake trivy binary in PATH — fail-on-severity=CRITICAL + CRITICAL finding → exit 1 fail-on-severity=CRITICAL + no findings → exit 0 Trivy exits non-zero → exit 1 fail-on-count=CRITICAL:1 with 1 finding → exit 1 fail-on-count=CRITICAL:5 with 1 finding → exit 0 reports written to disk (sarif, markdown, html) validLXCName path-traversal rejection docs/architecture-diagrams.md: full rewrite — Architecture diagram: adds runc advisory, KEV/OSV enrichment nodes, CSV/SBOM outputs, MCP server topology, air-gapped topology. Scan workflow sequence diagram: adds runc advisory, KEV/OSV calls, offline mode branch, severity upgrade in enricher. NEW Network diagram: external services (registry, Trivy DB, CISA KEV, OSV.dev, NVD) with online vs offline annotation. Deployment topologies: adds MCP/AI assistant and air-gapped topologies. NEW Test coverage map: diagrams which test tier covers which component and what remains untested (server, mcp-server, baseline, IDE). docs/testing.md: full rewrite — documents all test types (including new CLI exit-code and enrichment integration tiers), oracle fixture, race detector usage, per-package test coverage table, complete command reference, CI pipeline details. docs/sanity.md: updated — adds CLI test step (7), build server step (5), CI check note, SARIF import / Web UI / MCP manual steps. docs/LESSONS-LEARNED.md: appends testing strategy session entry. All 9 test packages (8 pkg/* + cmd/cli) pass with -race -count=1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
…r mcp-sdk - cmd/server/main_test.go: 8 tests covering handleHealth, buildSummary (empty + count accuracy), SSE input validation (missing params, both image+fs, invalid image ref, relative fs path, concurrency guard), and SSE Content-Type header — all via httptest.NewRecorder, no network. - cmd/mcp-server/main_test.go: 6 tests for parseSeverities (empty default, custom input, case normalisation) and formatSummary (empty, count accuracy, severity order, unknown/empty severity bucket). Tests pure helper functions only — no MCP SDK import in test file. - cmd/baseline/main_test.go: 7 tests for loadImages (strips comments and blanks, missing file, empty file), csvEscape (RFC-4180 quoting), writeFindingsMarkdown (content + empty case), writeDashboardHTML (HTML output + image name present). All use t.TempDir() — no leftover files. - go.mod / go.sum: run `go get github.com/modelcontextprotocol/go-sdk/mcp` to resolve pre-existing missing go.sum entry; upgrades Go toolchain requirement to 1.25 (SDK minimum). All existing tests remain green. - docs: update test-coverage map in architecture-diagrams.md (three "not yet" nodes promoted to "tested"), add three new rows to testing.md test-types table, append lessons-learned entry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
1. Add ./cmd/... to the unit-test step so cmd/cli, cmd/server, cmd/mcp-server, and cmd/baseline tests actually run in CI. Previously only ./pkg/... was covered, leaving all new cmd/* test files unexecuted in automation. 2. Fix integration job's if: condition — github.event.pull_request .changed_files is an integer count, not a path list, so contains(..., 'pkg/scanner') always evaluated false on PRs. Simplified to push-to-main only; a path-scoped PR trigger requires tj-actions/changed-files. 3. Pin Trivy install script URL to the tagged release (v0.69.1) instead of the floating main branch, so the script version matches the pinned binary version. Also adds a clarifying comment on SetURLForTest/ResetForTest in pkg/kev/kev.go explaining the ForTest naming convention for cross-package test injection (these can't move to _test.go since pkg/remediate's integration tests call them externally). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
…coverage - README: bump Go badge and version references from 1.21+ to 1.25+; add CI status badge; note cmd/* test coverage in testing table - docs/getting-started.md, docs/HELP.md: Go 1.21 → 1.25 - docs/sanity.md: consolidate pkg/... and cmd/... into a single test step; update CI check note to match - docs/testing.md: update all test commands to include ./cmd/...; fix CI pipeline code block to match actual ci.yml - docs/architecture-diagrams.md: update integration job label to "push-to-main" (was "nightly"); promote cmd/server, cmd/mcp-server, cmd/baseline from "not yet" to tested subgraph - docs/LESSONS-LEARNED.md: append code-review entry (PR #2 CI bugs) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
Phase 1 tests (cmd/cli/main_test.go): - TestRunScan_dockerfileFindingsMerged: verifies --dockerfile scan path merges DS002 misconfig into report.md (was completely untested) - TestRunScan_sbomWritten: verifies --sbom produces report.cdx.json with CycloneDX content (was untested) - TestRunScan_offlineSkipsKEV: verifies --offline=true produces zero HTTP hits to the CISA KEV endpoint (uses httptest recording server + kev.SetURLForTest injection) CI/CD integrations (ci/ + docs/ci/): - CircleCI: two-job workflow (build → scan), workspace file passing, artifacts; docs with variable table and PR comment tip - AWS CodeBuild: four-phase buildspec.yml with ECR push/pull, S3 artifact upload, Security Hub SARIF import snippet; docs with IAM policy - Google Cloud Build: cloudbuild.yaml with Artifact Registry, GCS artifact upload, substitution variable reference; docs with API enablement steps - Bitbucket Pipelines: Docker service, default + custom on-demand pipeline, artifacts; docs with Repository Variables table and manual trigger curl - Tekton: v1 Task + Pipeline CRDs (Kaniko build → scan → notify), PVC workspace, registry Secret injection; docs with tkn CLI log commands docs/ci/README.md updated with all 9 platforms grouped by type. docs/architecture-diagrams.md gains CI/CD ecosystem flowchart showing all supported platforms feeding into the scanner and report outputs. All 12 packages pass: go test -race -count=1 ./pkg/... ./cmd/... Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
pkg/runc: pre-release versions like 1.2.8-rc1 are now correctly flagged as vulnerable. Per semver, X.Y.Z-pre < X.Y.Z, so a host on an RC of the fixed version still needs patching. Detected by checking for '-' immediately after the semver match in the version string. cmd/cli: remove custom min() helper — shadowed the built-in added in Go 1.21; redundant since go.mod now requires Go 1.25. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
COMPARISON.md: three places that said "Azure, GitHub, GitLab, Jenkins" now list all nine supported platforms (added CircleCI, AWS CodeBuild, GCB, Bitbucket Pipelines, Tekton). Feature table row, Strengths section, and Summary table all updated. README.md: Added "More platforms" table in the CI/CD Integration section linking to all five new templates and guides. Updated repo directory listing to include all nine platforms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds extensive test coverage across the scanner, enrichment, report generation, and CLI components. The changes include unit tests, integration tests, and end-to-end tests that verify core functionality without requiring external services (via mocking).
Key Changes
New Test Files
pkg/kev/kev_test.go: Unit tests for CISA KEV catalog loading, caching, HTTP error handling, concurrent safety, and case normalizationpkg/remediate/enrich_integration_test.go: Integration tests for enrichment pipeline with mocked KEV server, verifying exploit flagging, severity upgrades, and ransomware detectionpkg/report/report_test.go(additions): SARIF 2.1 structural validation tests covering required fields, tool driver metadata, result formatting, and rule deduplicationpkg/scanner/parse_test.go: Fixture-based tests for Trivy JSON parsing, finding conversion, severity distribution, and remediation link populationcmd/cli/main_test.go: CLI exit-code tests using fake Trivy binary, verifying policy enforcement (--fail-on-severity,--fail-on-count), and error handlingcmd/server/main_test.go: HTTP handler tests for/health,/api/scan, and summary building logiccmd/baseline/main_test.go: Tests for image loading, CSV escaping, and markdown report generationcmd/mcp-server/main_test.go: Tests for severity parsing and summary formattingpkg/runc/runc_test.go(additions): Tests forHostVersion()with mocked Docker/runc binariesTest Infrastructure
pkg/scanner/testdata/trivy-fixture.json: Minimal Trivy JSON fixture (5 vulnerabilities across severity levels) for reproducible parsing testsDocumentation Updates
docs/testing.md: Reorganized test matrix with current status; added CLI exit-code, enrichment integration, and server testsdocs/architecture-diagrams.md: Updated flowcharts to include rootfs/LXC scanning, runc advisory, KEV/OSV enrichment, and new output formats (CSV, SBOM).github/workflows/ci.yml: New CI pipeline withgo vet, race-detector unit tests, and conditional integration testsSource Code Modifications
pkg/kev/kev.go: ChangedcisaKEVURLfrom const to var to allow test mocking; addedSetURLForTest()andResetForTest()helper functionscmd/cli/main.go: FixedrunScan()to return exit code (was discarded); now properly propagates policy violations toos.Exit()go.mod: Updated Go version to 1.25.0 and MCP SDK to v1.6.1Notable Implementation Details
httptest.NewServer()to mock external APIs without network calls-racedetectorTesting Strategy
https://claude.ai/code/session_0189QVFiKNFT5MEsskeEi19t
Greptile Summary
This PR adds comprehensive test coverage across all
pkg/*andcmd/*packages, refactorsrunScan()to return an exit code instead of callingos.Exit()directly, and introduces a new GitHub Actions CI pipeline along with CI templates for CircleCI, AWS CodeBuild, Google Cloud Build, Bitbucket Pipelines, and Tekton. The Go module is bumped to 1.25.0 to satisfy the MCP SDK dependency.pkg/kev,pkg/runc,pkg/scanner,pkg/remediate,pkg/report,cmd/cli,cmd/server,cmd/mcp-server, andcmd/baseline; all use mock HTTP servers or fake binaries and avoid live network dependencies.runScan()now returns anintinstead of callingos.Exit(), making exit-code behavior fully testable and correctly propagating policy violations.set -e, and the CodeBuild spec pins Go 1.21 whilego.modrequires 1.25.0.Confidence Score: 4/5
Safe to merge for the Go source and test changes; two new CI templates for CircleCI and AWS CodeBuild have defects that would affect any team adopting them.
The core Go changes (runScan refactor, kev test helpers, test files) are correct and well-tested. The CodeBuild template fails to compile on the first run due to a Go version mismatch, and the CircleCI template silently loses the security gate if a user works around the failing step.
ci/circleci/config.example.yml (broken exit-code capture) and ci/aws-codebuild/buildspec.yml (Go version mismatch with go.mod).
Important Files Changed
runScan()to return anintexit code instead of callingos.Exit()directly, making the function testable and correctly propagating policy violations.cisaKEVURLfromconsttovarand added exportedSetURLForTest/ResetForTesthelpers for cross-package mock injection; HTTP status check is still absent (previously flagged).go vet, race-detector tests for./pkg/... ./cmd/..., and a conditional integration job; previously flagged bugs (cmd/... missing, changed_files integer) are both fixed here.echo $?afterdocker runis dead code under CircleCI's defaultset -e, so the propagation step always exits 0 if users work around the failing step.golang: 1.21butgo.modnow requires1.25.0; the from-source build path fails immediately with a toolchain version error.Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Test as Test participant CLI as runScan() participant Scanner as pkg/scanner participant KEV as pkg/kev participant Enricher as pkg/remediate participant Policy as pkg/policy participant Report as pkg/report Test->>CLI: runScan(ctx, opts) CLI->>Scanner: Scan(ctx, ScanOptions) Scanner-->>CLI: []Finding alt "offline=false" CLI->>Enricher: Enrich(findings, false) Enricher->>KEV: Load() mock HTTP KEV-->>Enricher: CVE map Enricher-->>CLI: enriched else "offline=true" CLI->>Enricher: Enrich(findings, true) Enricher-->>CLI: enriched end CLI->>Report: Generate(enriched) Report-->>CLI: files written CLI->>Policy: EvaluateFailPolicy alt violated Policy-->>CLI: "shouldFail=true" CLI-->>Test: return 1 else ok Policy-->>CLI: "shouldFail=false" CLI-->>Test: return 0 end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Test as Test participant CLI as runScan() participant Scanner as pkg/scanner participant KEV as pkg/kev participant Enricher as pkg/remediate participant Policy as pkg/policy participant Report as pkg/report Test->>CLI: runScan(ctx, opts) CLI->>Scanner: Scan(ctx, ScanOptions) Scanner-->>CLI: []Finding alt "offline=false" CLI->>Enricher: Enrich(findings, false) Enricher->>KEV: Load() mock HTTP KEV-->>Enricher: CVE map Enricher-->>CLI: enriched else "offline=true" CLI->>Enricher: Enrich(findings, true) Enricher-->>CLI: enriched end CLI->>Report: Generate(enriched) Report-->>CLI: files written CLI->>Policy: EvaluateFailPolicy alt violated Policy-->>CLI: "shouldFail=true" CLI-->>Test: return 1 else ok Policy-->>CLI: "shouldFail=false" CLI-->>Test: return 0 endComments Outside Diff (3)
.github/workflows/ci.yml, line 49-51 (link)mainbranchThe install script URL uses
main/contrib/install.sh, which is a moving target — any future commit to that branch can change the script's behavior. Only the Trivy binary version (v0.69.1) is pinned. Pinning the script to a specific release tag or commit hash (e.g.https://raw.githubusercontent.com/aquasecurity/trivy/v0.69.1/contrib/install.sh) is a simple safeguard against unexpected upstream changes.pkg/kev/kev.go, line 72-79 (link)Load()never inspectsresp.StatusCode. If the CISA endpoint returns a 4xx/5xx with a parseable JSON body — e.g. a CDN that returns{}or{"vulnerabilities":[]}on error —json.Decodesucceeds,knownExploitedis set to a non-nil empty map, andlastFetchis stamped. On every subsequent call for the next 24 hours the cache-hit guard (knownExploited != nil && …) returns immediately, so all CVEs are silently treated as "not exploited" with no error surfaced to the caller.Add a status check immediately after
resp.Body.Closedeferral:ci/aws-codebuild/buildspec.yml, line 183-186 (link)1.21is incompatible withgo.modrequiring1.25.0go.modwas bumped togo 1.25.0in this PR (required by the MCP SDK). When CodeBuild provisionsgolang: 1.21and then runsgo build ./cmd/scanner, the toolchain rejects the module with an error likenote: module requires Go >= 1.25.0. The build fails immediately. This line should be updated to match the minimum version ingo.mod.Reviews (6): Last reviewed commit: "Update COMPARISON and README to reflect ..." | Re-trigger Greptile