This is an automated email from the ASF dual-hosted git repository.

matrei pushed a commit to branch update-cyclonedx
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 6316a4c550de87bb2cac2b7678640a153c43cbfa
Author: Mattias Reichel <[email protected]>
AuthorDate: Thu Sep 25 18:24:56 2025 +0200

    fix(sbom): adapt to `2.4.1` and simplify
---
 gradle/sbom-config.gradle | 103 +++++++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 48 deletions(-)

diff --git a/gradle/sbom-config.gradle b/gradle/sbom-config.gradle
index d856d99e16..89aaef58f2 100644
--- a/gradle/sbom-config.gradle
+++ b/gradle/sbom-config.gradle
@@ -33,53 +33,62 @@ import java.time.temporal.ChronoUnit
 
 apply plugin: 'org.cyclonedx.bom'
 
-project.ext.setProperty('sbomOutputLocation', 
project.layout.buildDirectory.file("${findProperty('pomArtifactId') ?: 
project.name}-${projectVersion}-sbom.json"))
+ext {
+    sbomOutputLocation = layout.buildDirectory.file(
+            "${findProperty('pomArtifactId') ?: 
name}-$projectVersion-sbom.json"
+    )
+}
 
-def sbomTask = tasks.named('cyclonedxBom', CycloneDxTask)
-sbomTask.configure { CycloneDxTask it ->
+tasks.withType(CycloneDxTask).configureEach {
     // the 2.x version of Cyclonedx uses a legacy syntax & helpers for setting 
inputs so the syntax below
     // is required until the 3.x version is GA
-    it.setProjectType(findProperty('sbomProjectType')?.toString() ?: 
Component.Type.FRAMEWORK.name())
-    [email protected](findProperty('pomArtifactId')?.toString() ?: 
project.name)
-    [email protected](new OrganizationalEntity().tap {
-        name = 'Apache Software Foundation'
-        urls = ['https://www.apache.org/', 'https://security.apache.org/']
-        addContact(new OrganizationalContact().tap {
-            name = 'Apache Grails Development Team'
-            email = '[email protected]'
-        })
-    })
-    [email protected](new LicenseChoice().tap {
-        addLicense(new License().tap {
-            name = 'Apache-2.0'
-            url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
-        })
-    })
-
+    projectType = 
Component.Type.valueOf(findProperty('sbomProjectType')?.toString() ?: 
'FRAMEWORK')
+    componentName = findProperty('pomArtifactId')?.toString() ?: project.name
+    [email protected](new OrganizationalEntity(
+            name: 'Apache Software Foundation',
+            urls: [
+                    'https://www.apache.org/',
+                    'https://security.apache.org/'
+            ],
+            contacts: [
+                    new OrganizationalContact(
+                            name: 'Apache Grails Development Team',
+                            email: '[email protected]'
+                    )
+            ]
+    ))
+    [email protected](new LicenseChoice(
+            licenses: [
+                    new License(
+                        name: 'Apache-2.0',
+                        url: 'https://www.apache.org/licenses/LICENSE-2.0.txt'
+                    )
+            ]
+    ))
     [email protected]([
-            new ExternalReference().tap {
-                url = 'https://grails.apache.org/'
-                type = ExternalReference.Type.WEBSITE
-            }
+            new ExternalReference(
+                    url: 'https://grails.apache.org/',
+                    type: ExternalReference.Type.WEBSITE
+            )
     ])
 
     // sboms are published for the purposes of vulnerability analysis so only 
include the runtime classpath
-    [email protected](['runtimeClasspath'])
-    [email protected](['compileClasspath', 'testRuntimeClasspath'])
+    includeConfigs = ['runtimeClasspath']
+    skipConfigs = ['compileClasspath', 'testRuntimeClasspath']
 
     // turn off license text since it's base64 encoded & will inflate the jar 
sizes
-    [email protected](false)
+    includeLicenseText = false
 
     // disable xml output
-    it.xmlOutput.unsetConvention()
+    xmlOutput.unsetConvention()
 
-    def sbomOutputLocation = findProperty('sbomOutputLocation')
-    it.jsonOutput.set(sbomOutputLocation.get())
-    it.outputs.file(sbomOutputLocation)
+    def sbomOutputLocation = findProperty('sbomOutputLocation') as 
Provider<RegularFile>
+    jsonOutput = sbomOutputLocation.get()
+    outputs.file(sbomOutputLocation)
 
     // cyclonedx does not support "choosing" the license placed in the sbom
     // see: https://github.com/CycloneDX/cyclonedx-gradle-plugin/issues/16
-    it.doLast {
+    doLast {
         // ordered so that first value is the most preferred, this list is 
from https://www.apache.org/legal/resolved.html
         def preferredLicenses = ['Apache-2.0', 'EPL-1.0', 'BSD-3-Clause', 
'EPL-2.0', 'MIT', 'MIT-0', '0BSD', 'UPL-1.0',
                                  'CC0-1.0', 'ICU', 'Xnet', 'NCSA', 'W3C', 
'Zlib', 'AFL-3.0', 'MS-PL', 'PSF-2.0', 'APAFML',
@@ -87,17 +96,17 @@ sbomTask.configure { CycloneDxTask it ->
 
         // licenses are standardized @ https://spdx.org/licenses/
         def licenses = [
-                'Apache-2.0'  : [
-                        id  : 'Apache-2.0',
-                        url : 'https://www.apache.org/licenses/LICENSE-2.0'
+                'Apache-2.0': [
+                        id: 'Apache-2.0',
+                        url: 'https://www.apache.org/licenses/LICENSE-2.0'
                 ],
                 'BSD-2-Clause': [
-                        id  : 'BSD-2-Clause',
-                        url : 'https://opensource.org/license/bsd-3-clause/'
+                        id: 'BSD-2-Clause',
+                        url: 'https://opensource.org/license/bsd-3-clause/'
                 ],
                 'BSD-3-Clause': [
-                        id  : 'BSD-3-Clause',
-                        url : 'https://opensource.org/license/bsd-3-clause/'
+                        id: 'BSD-3-Clause',
+                        url: 'https://opensource.org/license/bsd-3-clause/'
                 ],
                 // Variant of Apache 1.1 license. Approved by legal LEGAL-707
                 'OpenSymphony' : [
@@ -105,11 +114,10 @@ sbomTask.configure { CycloneDxTask it ->
                         name: 'The OpenSymphony Software License, Version 1.1',
                         url: 
'https://raw.githubusercontent.com/sitemesh/sitemesh2/refs/heads/master/LICENSE.txt'
                 ],
-                'UPL-1.0' : [
+                'UPL-1.0': [
                         id: 'UPL-1.0',
                         url: 'https://oss.oracle.com/licenses/upl/'
                 ],
-
         ]
 
         def licenseMapping = [
@@ -127,11 +135,11 @@ sbomTask.configure { CycloneDxTask it ->
         // Require a whitelist of any case of category X licenses to prevent 
accidental inclusion in a distributed artifact
         // this list will need to be updated anytime we change versions so we 
can revise the licenses
         def licenseExceptions = [
-                'grails-data-hibernate5-core'       : [
+                'grails-data-hibernate5-core': [
                         
'pkg:maven/org.hibernate.common/[email protected]?type=jar':
 'LGPL-2.1-only', // hibernate 5 is LGPL, we are migrating to ASF license in 
hibernate 7
                         
'pkg:maven/org.hibernate/[email protected]?type=jar': 
'LGPL-2.1-only', // hibernate 5 is LGPL, we are migrating to ASF license in 
hibernate 7
                 ],
-                'grails-data-hibernate5'            : [
+                'grails-data-hibernate5': [
                         
'pkg:maven/org.hibernate.common/[email protected]?type=jar':
 'LGPL-2.1-only', // hibernate 5 is LGPL, we are migrating to ASF license in 
hibernate 7
                         
'pkg:maven/org.hibernate/[email protected]?type=jar': 
'LGPL-2.1-only', // hibernate 5 is LGPL, we are migrating to ASF license in 
hibernate 7
                 ],
@@ -195,12 +203,12 @@ sbomTask.configure { CycloneDxTask it ->
             def bom = new JsonSlurper().parse(f)
 
             // timestamp is not reproducible: 
https://github.com/CycloneDX/cyclonedx-gradle-plugin/issues/292
-            bom.metadata.timestamp = 
DateTimeFormatter.ISO_INSTANT.format(buildDate.truncatedTo(ChronoUnit.SECONDS))
+            bom['metadata']['timestamp'] = 
DateTimeFormatter.ISO_INSTANT.format(buildDate.truncatedTo(ChronoUnit.SECONDS))
 
             // components[*].licenses
             def comps = (bom instanceof Map && bom.components instanceof List) 
? bom.components : []
             comps.each { c ->
-                if (c instanceof Map && c.licenses instanceof List && 
!c.licenses.isEmpty()) {
+                if (c instanceof Map && c.licenses instanceof List && 
!(c.licenses as List).isEmpty()) {
                     def chosen = pickLicense(c['bom-ref'] as String, 
c.licenses as List)
                     if (chosen != null) {
                         c.licenses = [chosen]
@@ -209,11 +217,10 @@ sbomTask.configure { CycloneDxTask it ->
             }
 
             // force the serialNumber to be reproducible by removing it & 
recalculating
-            bom.serialNumber = ''
+            bom['serialNumber'] = ''
             String withOutSerial = 
JsonOutput.prettyPrint(JsonOutput.toJson(bom))
             def uuid = 
UUID.nameUUIDFromBytes(withOutSerial.getBytes(StandardCharsets.UTF_8.name()))
-            def urn = "urn:uuid:${uuid.toString()}" as String
-            bom.serialNumber = urn
+            bom['serialNumber'] = "urn:uuid:$uuid".toString()
 
             f.setText(JsonOutput.prettyPrint(JsonOutput.toJson(bom)), 
StandardCharsets.UTF_8.name())
 

Reply via email to