From 87cdab5bc2b916b2bca3049e95eb36495c5926d0 Mon Sep 17 00:00:00 2001 From: Matthew Watkins Date: Tue, 1 Sep 2026 12:54:03 +0100 Subject: [PATCH] Feat: Add sbom_enabled and grype_enabled toggles The Maven and Gradle lanes ran SBOM generation and the Grype scan unconditionally, with no way for a caller to opt out. Every other workflow family exposes at least sbom_enabled, so a project moving between families met an inconsistent contract. Add sbom_enabled and grype_enabled (both boolean, default true). grype_enabled is independent of sbom_enabled, so the SBOM is still generated and uploaded when only the scan is dropped. The SBOM job's condition also guards the tests job, so the new clause is anchored on the SBOM job's own explanatory comment to leave the tests gate untouched. Co-authored-by: Claude Signed-off-by: Matthew Watkins --- .github/workflows/gradle-build-test.yaml | 25 ++++++++++++++++++++++-- .github/workflows/maven-build-test.yaml | 25 ++++++++++++++++++++++-- examples/gradle/build-test/github.yaml | 2 ++ examples/maven/build-test/github.yaml | 2 ++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle-build-test.yaml b/.github/workflows/gradle-build-test.yaml index a9a3a4a..412559b 100644 --- a/.github/workflows/gradle-build-test.yaml +++ b/.github/workflows/gradle-build-test.yaml @@ -75,7 +75,26 @@ on: type: boolean default: false + # --- SBOM --- + sbom_enabled: + description: >- + Generate an SBOM (set false to skip). The Grype scan reads + the SBOM, so skipping generation leaves it nothing to scan. + To keep the SBOM but drop the scan, use grype_enabled. + required: false + type: boolean + default: true + # --- Grype scan --- + grype_enabled: + description: >- + Run the Grype vulnerability scan over the generated SBOM (set + false to skip). Decoupling is one-way: disabling the scan + keeps the SBOM, but disabling the SBOM also stops the scan, + which has nothing to read. + required: false + type: boolean + default: true grype_fail_on: description: 'Minimum severity that fails the Grype scan' required: false @@ -528,7 +547,8 @@ jobs: # checkout and does not depend on the build's artefacts, so it keeps # producing the dependency-scan signal even when the build fails # (for example on a test failure). - if: ${{ !cancelled() && needs.build.result != 'skipped' }} + # yamllint disable-line rule:line-length + if: ${{ !cancelled() && needs.build.result != 'skipped' && inputs.sbom_enabled }} timeout-minutes: ${{ inputs.sbom_timeout_minutes }} permissions: contents: read @@ -607,7 +627,8 @@ jobs: name: 'Grype Audit SBOM' runs-on: ubuntu-latest needs: 'sbom' - if: ${{ !cancelled() && needs.sbom.result == 'success' }} + # yamllint disable-line rule:line-length + if: ${{ !cancelled() && needs.sbom.result == 'success' && inputs.grype_enabled }} timeout-minutes: ${{ inputs.grype_timeout_minutes }} permissions: contents: read diff --git a/.github/workflows/maven-build-test.yaml b/.github/workflows/maven-build-test.yaml index b5ff9d3..7d675fb 100644 --- a/.github/workflows/maven-build-test.yaml +++ b/.github/workflows/maven-build-test.yaml @@ -87,7 +87,26 @@ on: type: boolean default: false + # --- SBOM --- + sbom_enabled: + description: >- + Generate an SBOM (set false to skip). The Grype scan reads + the SBOM, so skipping generation leaves it nothing to scan. + To keep the SBOM but drop the scan, use grype_enabled. + required: false + type: boolean + default: true + # --- Grype scan --- + grype_enabled: + description: >- + Run the Grype vulnerability scan over the generated SBOM (set + false to skip). Decoupling is one-way: disabling the scan + keeps the SBOM, but disabling the SBOM also stops the scan, + which has nothing to read. + required: false + type: boolean + default: true grype_fail_on: description: 'Minimum severity that fails the Grype scan' required: false @@ -594,7 +613,8 @@ jobs: # checkout and does not depend on the build's artefacts, so it keeps # producing the dependency-scan signal even when the build fails # (for example on a test failure). - if: ${{ !cancelled() && needs.build.result != 'skipped' }} + # yamllint disable-line rule:line-length + if: ${{ !cancelled() && needs.build.result != 'skipped' && inputs.sbom_enabled }} timeout-minutes: ${{ inputs.sbom_timeout_minutes }} permissions: contents: read @@ -673,7 +693,8 @@ jobs: name: 'Grype Audit SBOM' runs-on: ubuntu-latest needs: 'sbom' - if: ${{ !cancelled() && needs.sbom.result == 'success' }} + # yamllint disable-line rule:line-length + if: ${{ !cancelled() && needs.sbom.result == 'success' && inputs.grype_enabled }} timeout-minutes: ${{ inputs.grype_timeout_minutes }} permissions: contents: read diff --git a/examples/gradle/build-test/github.yaml b/examples/gradle/build-test/github.yaml index 5472e87..d341461 100644 --- a/examples/gradle/build-test/github.yaml +++ b/examples/gradle/build-test/github.yaml @@ -50,6 +50,8 @@ jobs: # gradle_version: '8.10' # pin Gradle (empty uses the wrapper) # build_arguments: 'build' # arguments for the gradle invocation # test_permit_fail: false # soft-fail tests + # sbom_enabled: true # false skips SBOM generation + # grype_enabled: true # false skips the Grype scan only # grype_fail_on: 'medium' # Grype severity gate # harden_runner_egress: 'block' # 'block' (default) or 'audit' # build_timeout_minutes: 45 # raise for large reactors diff --git a/examples/maven/build-test/github.yaml b/examples/maven/build-test/github.yaml index 3532a0b..9de0a65 100644 --- a/examples/maven/build-test/github.yaml +++ b/examples/maven/build-test/github.yaml @@ -52,6 +52,8 @@ jobs: # mvn_profiles: '' # comma-separated Maven profiles # run_jacoco: true # produce JaCoCo coverage # test_permit_fail: false # soft-fail tests + # sbom_enabled: true # false skips SBOM generation + # grype_enabled: true # false skips the Grype scan only # grype_fail_on: 'medium' # Grype severity gate # harden_runner_egress: 'block' # 'block' (default) or 'audit' # build_timeout_minutes: 45 # raise for large reactors