Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ client-license-check: client-setup-env ## Run license compliance check
@$(ACTIVATE_AND_CD) && pip-licenses
@echo "--- License compliance check complete ---"

.PHONY: client-license-check
client-sbom: client-setup-env ## Generate SBOM
@echo "--- Starting SBOM gernation ---"
@$(ACTIVATE_AND_CD) && mkdir -p dist; \
cyclonedx-py poetry --only main --output-reproducible --validate --output-format JSON --output-file dist/bom.json --verbose; \
cyclonedx-py poetry --only main --output-reproducible --validate --output-format XML --output-file dist/bom.xml --verbose
@echo "--- SBOM gernation complete ---"

.PHONY: client-build
client-build: client-setup-env ## Build client distribution. Pass FORMAT=sdist or FORMAT=wheel to build a specific format.
@echo "--- Building client distribution ---"
Expand Down
1 change: 1 addition & 0 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ plugins { `kotlin-dsl` }

dependencies {
implementation(gradleKotlinDsl())
implementation(baselibs.cyclonedx)
implementation(baselibs.errorprone)
implementation(baselibs.idea.ext)
implementation(baselibs.jandex)
Expand Down
94 changes: 94 additions & 0 deletions build-logic/src/main/kotlin/polaris-sbom-app.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import java.util.Base64
import org.cyclonedx.gradle.CyclonedxDirectTask
import org.cyclonedx.model.AttachmentText
import org.cyclonedx.model.Component.Type.APPLICATION
import org.cyclonedx.model.License
import org.cyclonedx.model.LicenseChoice
import org.cyclonedx.model.Property
import sbom.CyclonedxBundleTask
import sbom.createCyclonedxConfigurations

val cyclonedxApplicationBomTask =
tasks.register<CyclonedxBundleTask>("cyclonedxApplicationBom") {
group = "publishing"
description = "Generate CycloneDX SBOMs for this as an application"

val cyclonedxDirectBom = tasks.named<CyclonedxDirectTask>("cyclonedxDirectBom")
inputBoms.from(cyclonedxDirectBom.map { it.jsonOutput })

// want to include the original license text in the generated SBOM as it may include variations
// from the "standard" license text
includeLicenseText = true

projectType = APPLICATION

// Needed for projects that use subdirectories in their build/ directory, like the Spark plugin
jsonOutput.set(project.layout.buildDirectory.file("reports/cyclonedx-app/bom.json"))
xmlOutput.set(project.layout.buildDirectory.file("reports/cyclonedx-app/bom.xml"))

val relativeProjectDir = project.projectDir.relativeTo(project.rootProject.projectDir)
val gitInfo = GitInfo.memoized(project)

licenseChoice.set(
LicenseChoice().apply {
addLicense(
License().apply {
val gitCommit = GitInfo.memoized(project).gitHead
id = "Apache-2.0"
// TODO URL or text ??
url = gitInfo.rawGithubLink("$relativeProjectDir/distribution/LICENSE")
setLicenseText(
AttachmentText().apply() {
contentType = "plain/text"
encoding = "base64"
text =
Base64.getEncoder()
.encodeToString(project.file("distribution/LICENSE").readBytes())
}
)

// TODO Is there a better way to include NOTICE + DISCLAIMER in a CycloneDX SBOM?
val props = mutableListOf<Property>()
props.add(
Property().apply {
name = "NOTICE"
value =
project.file("distribution/NOTICE").readText(Charsets.UTF_8).replace("\n", "\\n")
}
)
val disclaimerFile = project.file("distribution/DISCLAIMER")
if (disclaimerFile.isFile) {
props.add(
Property().apply {
name = "DISCLAIMER"
value = disclaimerFile.readText(Charsets.UTF_8).replace("\n", "\\n")
}
)
}
properties = props
}
)
}
)
}

createCyclonedxConfigurations(project, cyclonedxApplicationBomTask)
93 changes: 93 additions & 0 deletions build-logic/src/main/kotlin/polaris-sbom-bundle.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import java.util.Base64
import org.cyclonedx.model.AttachmentText
import org.cyclonedx.model.License
import org.cyclonedx.model.LicenseChoice
import org.cyclonedx.model.Property
import publishing.digestTaskOutputs
import publishing.signTaskOutputs
import sbom.CyclonedxBundleTask
import sbom.createCyclonedxConfigurations

plugins { id("org.cyclonedx.bom") }

val bundleSboms by
configurations.creating {
isCanBeConsumed = false
isCanBeResolved = true
}

val cyclonedxBundleBom = tasks.register<CyclonedxBundleTask>("cyclonedxBundleBom")

cyclonedxBundleBom.configure {
inputBoms = bundleSboms
// The distribution itself has no dependencies, just components
includeDependencies = false

val relativeProjectDir = project.projectDir.relativeTo(project.rootProject.projectDir)
val gitInfo = GitInfo.memoized(project)

licenseChoice.set(
LicenseChoice().apply {
addLicense(
License().apply {
id = "Apache-2.0"
// TODO URL or text ??
url = gitInfo.rawGithubLink("$relativeProjectDir/LICENSE")
setLicenseText(
AttachmentText().apply() {
contentType = "plain/text"
encoding = "base64"
text = Base64.getEncoder().encodeToString(project.file("LICENSE").readBytes())
}
)

// TODO Is there a better way to include NOTICE + DISCLAIMER in a CycloneDX SBOM?
val props = mutableListOf<org.cyclonedx.model.Property>()
props.add(
Property().apply {
name = "NOTICE"
value = project.file("NOTICE").readText(Charsets.UTF_8).replace("\n", "\\n")
}
)
val disclaimerFile = project.file("DISCLAIMER")
if (disclaimerFile.isFile) {
props.add(
Property().apply {
name = "DISCLAIMER"
value = disclaimerFile.readText(Charsets.UTF_8).replace("\n", "\\n")
}
)
}
properties = props
}
)
}
)
}

createCyclonedxConfigurations(project, cyclonedxBundleBom)

tasks.named("assemble") { dependsOn(cyclonedxBundleBom) }

digestTaskOutputs(cyclonedxBundleBom)

signTaskOutputs(cyclonedxBundleBom)
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import org.gradle.kotlin.dsl.registering
import org.gradle.kotlin.dsl.withType
import org.gradle.plugins.signing.SigningExtension
import org.gradle.plugins.signing.SigningPlugin
import sbom.configureCycloneDx

/**
* Release-publishing helper plugin to generate publications that pass Sonatype validations,
Expand Down Expand Up @@ -94,6 +95,7 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl

apply(plugin = "maven-publish")
apply(plugin = "signing")
apply(plugin = "org.cyclonedx.bom")

// Generate a source tarball for a release to be uploaded to
// https://dist.apache.org/repos/dist/dev/<name>/apache-<name>-<version-with-rc>/
Expand Down Expand Up @@ -175,5 +177,7 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl
}
}
}

configureCycloneDx()
}
}
Loading
Loading