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

Reply via email to