Skip to content

feat(sbom): add --warnings-non-fatal flag to sbom validate - #331

Draft
reyreavman wants to merge 1 commit into
mainfrom
fix/sbom/validate-warnings-non-fatal
Draft

reyreavman wants to merge 1 commit into
mainfrom
fix/sbom/validate-warnings-non-fatal

Conversation

@reyreavman

@reyreavman reyreavman commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

werf sbom validate now separates sbom-checker findings into errors and warnings, shows both counts in the summary, and adds an opt-in --warnings-non-fatal flag that keeps warnings from failing the run. The strict default is unchanged: by default any error or warning still exits 1, exactly as before — so no existing pipeline changes behavior without opting in.

What

  • Checker output is split into errors and warnings; the summary line reports both: Result: N passed, M failed; X error(s), Y warning(s).
  • Per-file status is OK, OK (M warning(s)), or FAILED; warning lines are written to stderr, error lines and the status header to stdout.
  • New flag --warnings-non-fatal (default false, env WERF_WARNINGS_NON_FATAL): when set, files whose only findings are warnings pass (exit 0); errors still fail.
  • Default behavior is unchanged and NOT breaking: without the flag, a file with any warning is FAILED and the run exits 1, as on the current release.
  • The error returned for a failed file (validation failed for <file>: followed by the finding lines) is unchanged.
  • CLI reference and the usage pages (EN and RU) document the flag, the env var, and that warnings go to stderr.

Why

parseResult appended warnings to the same list as errors, so the error/warning distinction the checker already makes (--errors 0) was collapsed in the summary and there was no way to accept warnings without also accepting errors. The upcoming ISPRAS checker image bump starts emitting purl-case warnings on otherwise conforming production SBOMs; a pipeline that wants to keep shipping through those warnings can now pass --warnings-non-fatal instead of losing error gating entirely.

The default was deliberately kept strict rather than flipped to lenient: flipping it would turn an existing red CI gate green with no config change, which the repository's compatibility policy disallows without an explicit exception. Leniency is therefore opt-in. A boolean --warnings-non-fatal was chosen over --strictness=errors|all because the checker emits exactly two finding classes; the enum can be added later if a third appears.

@reyreavman

Copy link
Copy Markdown
Collaborator Author

Verification

  • Hand-run on macOS with Docker Desktop against test/e2e/sbom/_fixtures/validate: oss_multiple_vcs_urls.json alone → OK (1 warning(s)), exit 0; same file with --fail-on-warningsFAILED, exit 1; mixed run with missing_bom_format.jsonResult: 2 passed, 1 failed; 2 error(s), 1 warning(s), exit 1.
  • task test:e2e paths="./test/e2e/sbom" labelFilter="validate" parallel=1 on macOS/Docker: 31/31 passed.
  • Mutation: failed reverted to errs > 0 || warnings > 0 → unit fileResult.report / warnings alone pass by default failed.
  • Mutation: failOnWarnings ignored in fileResult.report → unit warnings alone fail with failOnWarnings failed.
  • Mutation: --fail-on-warnings not wired into checker.RunOptions → e2e should fail validation / warnings with --fail-on-warnings failed.
  • Not run: the card's acceptance check against the new upstream checker image (34 purl warnings on a real merged OSS SBOM) — that image is not pinned in this branch; covered by the fixture-based warning case instead.

Review focus

  • fileResult.report in pkg/sbom/checker/checker.go: the single condition deciding pass/fail.
  • Warning lines now go to logboek ... Warn(); confirm this stream is captured the way CI consumers expect (e2e asserts on combined output).

Follow-up

  • Merge before the checker image bump, otherwise the bump turns sbom validate red on purl-case warnings.

@reyreavman

Copy link
Copy Markdown
Collaborator Author

Verification

  • Hand-run on macOS with Docker Desktop against test/e2e/sbom/_fixtures/validate: oss_multiple_vcs_urls.json alone → OK (1 warning(s)), exit 0; same file with --fail-on-warningsFAILED, exit 1; mixed run with missing_bom_format.jsonResult: 2 passed, 1 failed; 2 error(s), 1 warning(s), exit 1.
  • Stream split: 2>/dev/null drops the WARNING lines and keeps the OK (1 warning(s)) header; 2>&1 keeps them in order.
  • task test:e2e paths="./test/e2e/sbom" labelFilter="validate" parallel=1 on macOS/Docker: 31/31 passed.
  • Mutation: failed reverted to errs > 0 || warnings > 0 → unit fileResult.report / warnings alone pass by default failed.
  • Mutation: failOnWarnings ignored in fileResult.report → unit warnings alone fail with failOnWarnings failed.
  • Mutation: --fail-on-warnings not wired into checker.RunOptions → e2e should fail validation / warnings with --fail-on-warnings failed.
  • Mutation: per-file line printed as plain OK without the warning count → e2e should pass validation / warnings only pass by default failed.
  • Not run: the card's acceptance check against the new upstream checker image (34 purl warnings on a real merged OSS SBOM) — that image is not pinned in this branch; covered by the fixture-based warning case instead.

Review focus

  • fileResult.report in pkg/sbom/checker/checker.go: the single condition deciding pass/fail.
  • qlty reports "1 blocking issue" on the PR while the status is green and golangci-lint is clean locally; the dashboard needs a login — someone with access should read what it flags before merge.

Follow-up

  • Merge before the checker image bump, otherwise the bump turns sbom validate red on purl-case warnings.
  • Decide whether the strict→lenient default flip warrants a BREAKING CHANGE: footer (major bump) or ships as fix — the description currently argues for fix.

@Fral738 Fral738 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strict-to-lenient default flip is explicitly intentional, but it still changes existing CI acceptance gates from failure to success without any configuration change. --fail-on-warnings is an opt-back, not an opt-in feature flag for the new behavior, so it does not satisfy the repository's rule for breaking user-facing changes. Preserve the strict default and make lenient behavior opt-in, or obtain an explicit compatibility-policy exception before merging this as a fix.

The description also understates the affected population: the pinned checker produces warnings without --check-vcs. For example, werf sbom validate --path=test/e2e/sbom/_fixtures/validate/oss_multiple_vcs_urls.json --ispras-format=oss emits a multiple-VCS-URLs WARNING and exits 0 on this head; the same invocation with --fail-on-warnings exits 1. The new warning-only e2e case also passes no --check-vcs. Please correct both the parenthetical in What and the release rationale: affected pipelines are not limited to those using --check-vcs.

The inline comments cover the missing environment-variable counterpart and the unprotected stdout/stderr contract.

Comment thread cmd/werf/sbom/validate/validate.go Outdated
cmd.Flags().StringArrayVar(&pathFlags, "path", nil, "Path to CycloneDX JSON SBOM file (repeatable)")
cmd.Flags().StringVar(&isprasFormatFlag, "ispras-format", "", "ISPRAS SBOM format: oss or container")
cmd.Flags().BoolVar(&checkVCSFlag, "check-vcs", false, "Enable VCS URL validation")
cmd.Flags().BoolVar(&failOnWarningsFlag, "fail-on-warnings", false, "Treat checker warnings as failures (by default only errors fail validation)")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new flag has no WERF_* environment-variable counterpart, contrary to the CLI convention. With the warning-only fixture, WERF_FAIL_ON_WARNINGS=true werf sbom validate --path=test/e2e/sbom/_fixtures/validate/oss_multiple_vcs_urls.json --ispras-format=oss still exits 0, while adding --fail-on-warnings exits 1.

Use the existing environment-default helper, add the pkg/util import, regenerate the CLI reference, and cover env=true plus an explicit --fail-on-warnings=false override:

cmd.Flags().BoolVar(&failOnWarningsFlag, "fail-on-warnings", util.GetBoolEnvironmentDefaultFalse("WERF_FAIL_ON_WARNINGS"), "Treat checker warnings as failures (default $WERF_FAIL_ON_WARNINGS or false)")

})
Expect(out).To(ContainSubstring("OK"))
if expectedSubstring != "" {
Expect(out).To(ContainSubstring(expectedSubstring))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The combined-output assertion does not protect the newly documented stderr contract. Changing the warning logger in fileResult.report from Warn() back to Default() leaves all 21 checker unit specs and all 31 validate e2e specs passing, even though WARNING lines are then written to stdout.

Capture stdout and stderr separately for the warning-only fixture and assert the stream contents explicitly; retain the exit-code assertion and use the same logger mutation to verify the test fails:

Expect(stdout).To(ContainSubstring("OK (1 warning(s))"))
Expect(stdout).NotTo(ContainSubstring("WARNING:"))
Expect(stderr).To(ContainSubstring("WARNING:"))

sbom validate now reports checker findings split into errors and
warnings, printing both counts in the summary ("N error(s), M
warning(s)"), and warnings are written to stderr instead of stdout.

By default any error or warning still fails validation with exit 1, as
before — the strict default is unchanged. The new --warnings-non-fatal
flag (env WERF_WARNINGS_NON_FATAL) keeps warnings informational so only
errors set a non-zero exit code. This lets a pipeline opt into lenient
acceptance ahead of the ISPRAS checker image bump, which starts emitting
purl-case warnings on otherwise conforming SBOMs.

Signed-off-by: Radmir Khurum <radmir.khurum@flant.com>
@reyreavman
reyreavman force-pushed the fix/sbom/validate-warnings-non-fatal branch from b850186 to a84ecde Compare September 21, 2026 23:01
@reyreavman reyreavman changed the title fix(sbom): stop sbom validate failing on checker warnings feat(sbom): add --warnings-non-fatal flag to sbom validate Sep 21, 2026
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.

2 participants