The GitHub Actions job "CI - Groovy Joint Validation Build" on grails-core.git/fix/sbom-uuid-collision-gradle-9 has failed. Run started by GitHub user jamesfredley (triggered by jamesfredley).
Head commit for run: 4d1a78f1e2b77329dc2b0b354bb5dd46d8354d99 / James Fredley <[email protected]> fix(sbom): also fix UUID collisions in com.gradleup.shadow fat jars Discovered while running the verify-cli/verify-wrapper smoke tests against the build outputs of :grails-cli, :grails-cli-shadow, :grails-shell-cli, :grails-forge-cli and :grails-wrapper. Both :grails-cli (-all.jar) and :grails-cli-shadow (-all.jar) bundled grails-shell-cli as a transitive dep, and com.gradleup.shadow's first-wins merge of META-INF/sbom.json ended up putting grails-shell-cli's SBOM into both fat jars. Result: two distinct fat jars shared a single serialNumber and both reported metadata.component.name="grails-shell-cli" - a CycloneDX 1.6 violation that the previous projectPath-seed fix did not catch because that fix only changed how each project's own SBOM JSON is generated, not how shadow merges other modules' SBOMs into a fat jar. This commit applies a fix symmetrical to publishSbomForJarProjects: * SbomPlugin gains publishSbomForShadowJarProjects, which, for any project that applies com.gradleup.shadow, excludes incoming META-INF/sbom.json from the shadow merge and re-introduces the project's own SBOM (whose serialNumber is now project-path-seeded and unique). Manifest gets the same Sbom-Location / Sbom-Format attributes the regular jar already has. Uses Task + cast to Jar so build-logic does not need a compile-time dependency on the shadow plugin types. * grails-forge/grails-cli-shadow does not apply org.apache.grails.buildsrc.sbom (it is an intermediate build artifact, not published), so the SbomPlugin hook does not fire for it. Its shadowJar exclude list now drops META-INF/sbom.json directly so the intermediate fat jar - which feeds :grails-cli's shadowCombined configuration - cannot smuggle a wrong SBOM back in. Verified on Gradle 9.4.1 with SOURCE_DATE_EPOCH set, --no-build-cache, --rerun-tasks (the same flags test-reproducible-builds.sh uses): jar serialNumber :grails-shell-cli (regular) 631bbcd5... :grails-wrapper (regular) 9c5f6980... :grails-cli (regular) 3e4ea827... :grails-cli (-all FAT) 3e4ea827... * :grails-cli-shadow (regular) (no SBOM - empty) :grails-cli-shadow (-all FAT) (no SBOM - excluded) :grails-forge-cli (regular) 890372ec... *) :grails-cli's regular and FAT jar share a serialNumber by design: they ship the same project's SBOM, the FAT jar just adds bundled classes. The CycloneDX uniqueness constraint applies across BOMs describing different artifacts, not across two jars whose embedded BOM happens to describe the same project. Smoke-tested both fat-jar CLIs against verify-cli-distribution.sh flow: apache-grails-8.0.0-SNAPSHOT-bin.zip extracts cleanly with LICENSE and NOTICE present, bin/grails-shell-cli --version and bin/grails-forge-cli --version both return version + JVM info, bin/grails-shell-cli create-app ShellApp generates a complete Grails app, bin/grails-forge-cli create-app -x -g mongodb -f gradle-settings-file ForgeApp generates a complete Grails app, java -jar grails-cli-8.0.0-SNAPSHOT-all.jar --version still works with the new SBOM in place. Assisted-by: claude-code:claude-opus-4 Report URL: https://github.com/apache/grails-core/actions/runs/25197034434 With regards, GitHub Actions via GitBox
