Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate license report on jar build #409

Merged
merged 5 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
96 changes: 11 additions & 85 deletions agent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import java.util.stream.Collectors
plugins {
id("elastic-otel.agent-packaging-conventions")
id("elastic-otel.sign-and-publish-conventions")
id("elastic-otel.license-report-conventions")
alias(catalog.plugins.taskinfo)
alias(catalog.plugins.licenseReport)
}

description = "Elastic Distribution of OpenTelemetry Java Agent"
Expand All @@ -26,104 +26,30 @@ dependencies {
upstreamAgent("io.opentelemetry.javaagent:opentelemetry-javaagent")
}

licenseReport {
configurations = arrayOf(
project.configurations.bootstrapLibs.name,
project.configurations.javaagentLibs.name
// No need to include the upstreamAgent, because it already has all dependent licenses packaged
// Those will be preserved in our JAR
SylvainJuge marked this conversation as resolved.
Show resolved Hide resolved
)
}

tasks {

val cleanLicenses by registering(Delete::class) {
Files.list(rootDir.toPath().resolve("licenses"))
.filter { f -> Files.isDirectory(f) || f.fileName.startsWith("NOTICE_") }
.forEach { f -> delete(f) }
}
generateLicenseReport {
dependsOn(cleanLicenses)
}

// We override the agent entrypoints defined in elastic-otel.agent-packaging-convention
shadowJar {

dependsOn(named("updateLicensesAndNotice"))

// include licenses and notices in jar
from(rootDir) {
dependsOn(fullLicenseReport)
from(fullLicenseReport.get().outputs.files.singleFile) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually passing a task as input for another task is enough for gradle to create an implicit dependency between them and also to know what outputs to consume. Some cases might need things to be done explicitly though, maybe this is one of them, but if it's not, I think it'd be enough to replace lines 44 and 45 with from(fullLicenseReport).

Copy link

@LikeTheSalad LikeTheSalad Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it seems like this config is applied the same way in the agentextension build file, if the same steps are needed for all cases then it'd probably be nice to do this work in the conventions file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be enough to replace lines 44 and 45 with from(fullLicenseReport)

Good point, i wasn't aware that from() accepts tasks as input, thanks!

Also, it seems like this config is applied the same way in the agentextension build file, if the same steps are needed for all cases then it'd probably be nice to do this work in the conventions file.

I left that intentionally in the individual sub-projects: In my opinion it is easier to follow when the content-packaging of the JAR is less spread over multiple files, especially in this case because it is now only two duplicated lines across the two files.

into("META-INF")

include("LICENSE")
include("NOTICE")
include("licenses/**")
}

}

assemble {
dependsOn(javadocJar, sourcesJar)
}

val licensesDir = rootDir.toPath().resolve("licenses")
val licenseFile = "more-licences.md"

licenseReport {
outputDir = licensesDir.toString()
renderers = arrayOf(InventoryMarkdownReportRenderer(licenseFile))
excludeBoms = true
excludes = arrayOf(
"io.opentelemetry:opentelemetry-bom-alpha",
"io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha"
)
filters = arrayOf(
LicenseBundleNormalizer(
"${rootProject.rootDir}/buildscripts/license-normalizer-bundle.json",
true
)
)
projects = arrayOf(
rootProject.project("agent"), rootProject.project("bootstrap"),
rootProject.project("common"), rootProject.project("custom"),
rootProject.project("inferred-spans"), rootProject.project("instrumentation"),
rootProject.project("resources")
)

configurations = arrayOf("runtimeClasspath", "compileClasspath")
}

register("updateLicensesAndNotice") {
dependsOn(generateLicenseReport)
doLast {

var year = Calendar.getInstance().get(Calendar.YEAR)
var lines = ArrayList<String>(
listOf(
"Elastic Distribution of OpenTelemetry Java",
"Copyright 2023-${year} Elasticsearch B.V.",
"",
"This project is licensed under the Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0",
"A copy of the Apache License, Version 2.0 is provided in the 'LICENSE' file.",
"",
"This project depends on ASM which is licensed under the 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause",
"A copy of the ASM license (3-Clause BSD License) is provided in the 'licenses/LICENSE_asm_bsd-3-clause' file.",
"",
"This project depends on okhttp, which contains 'publicsuffixes.gz' that is licensed under the Mozilla Public License, v. 2.0 - https://mozilla.org/MPL/2.0/",
"A copy of the publicsuffixes.gz license (Mozilla Public License, v. 2.0) is provided in the 'licenses/LICENSE_mpl-2' file.",
"",
"This project depends on HdrHistogram which is dual-licensed under the following licenses:",
" - 2-Clause BSD License - https://opensource.org/licenses/BSD-2-Clause",
" - Creative Commons Public Domain License - https://creativecommons.org/publicdomain/zero/1.0/",
"A copy of the HdrHistogram license is provided in the 'licenses/LICENSE_hdrhistogram_bsd-2-clause_cc0' file.",
"",
"Details on the individual dependencies notices and licenses can be found in the 'licenses' folder.",
""
)
)

Files.write(rootDir.toPath().resolve("NOTICE"), lines)

// make the generated license report idempotent by removing the date
SylvainJuge marked this conversation as resolved.
Show resolved Hide resolved
val licenseReport = licensesDir.resolve(licenseFile)
var newLicenseLines = Files.readAllLines(licenseReport)
.stream()
.map { l -> if (l.startsWith("_$year")) "" else l }
.collect(Collectors.toList())
Files.write(licenseReport, newLicenseLines)
}
}
}

13 changes: 7 additions & 6 deletions agentextension/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id("elastic-otel.java-conventions")
id("elastic-otel.sign-and-publish-conventions")
id("elastic-otel.license-report-conventions")
id("com.github.johnrengelman.shadow")
}

Expand All @@ -20,6 +21,10 @@ publishingConventions {
artifactTasks.add(tasks.sourcesJar)
}

licenseReport {
configurations = arrayOf(shadowDependencies.name)
}

tasks {

jar {
Expand All @@ -33,13 +38,9 @@ tasks {
archiveClassifier.set("")

// include licenses and notices in jar
dependsOn(project(":agent").tasks.named("updateLicensesAndNotice"))
from(rootDir) {
dependsOn(fullLicenseReport)
from(fullLicenseReport.get().outputs.files.singleFile) {
into("META-INF")

include("LICENSE")
include("NOTICE")
include("licenses/**")
}
}
}
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ repositories {
dependencies {
implementation(catalog.spotlessPlugin)
implementation(catalog.shadowPlugin)
implementation(catalog.licenseReportPlugin)
// The ant dependency is required to add custom transformers for the shadow plugin
// but it is unfortunately not exposed as transitive dependency
implementation(catalog.ant)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import org.gradle.api.tasks.Copy
import org.gradle.kotlin.dsl.register
import com.github.jk1.license.filter.LicenseBundleNormalizer
import com.github.jk1.license.render.InventoryMarkdownReportRenderer
import com.github.jk1.license.render.ReportRenderer

plugins {
id("com.github.jk1.dependency-license-report")
}

val fullLicenseReport = tasks.register("fullLicenseReport", Copy::class) {
dependsOn(tasks.generateLicenseReport)
//We want to fail in case there are any non-approved licenses
dependsOn(tasks.checkLicense)

from(rootProject.rootDir) {
include("NOTICE", "LICENSE")
}
from(licenseReport.outputDir) {
include("**/*")
exclude("dependencies-without-allowed-license.json")
exclude("project-licenses-for-check-license-task.json")
into("licenses")
}
into(layout.buildDirectory.dir("reports/all-licenses"))
}

licenseReport {
allowedLicensesFile = File("${rootProject.rootDir}/buildscripts/allowed-licenses.json")

renderers = arrayOf<ReportRenderer>(InventoryMarkdownReportRenderer("more-licences.md"))
JonasKunz marked this conversation as resolved.
Show resolved Hide resolved
excludeBoms = true
excludes = arrayOf(
"io.opentelemetry:opentelemetry-bom-alpha",
"io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha"
)
filters = arrayOf(
LicenseBundleNormalizer(
"${rootProject.rootDir}/buildscripts/license-normalizer-bundle.json",
true
)
)
}
13 changes: 13 additions & 0 deletions buildscripts/allowed-licenses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"allowedLicenses": [
{
"moduleLicense": "Apache License, Version 2.0",
"moduleName": ".*"
},
{
"moduleLicense": "The 2-Clause BSD License",
"moduleVersion": ".*",
"moduleName": "org.hdrhistogram:HdrHistogram"
}
]
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ freemarker = "org.freemarker:freemarker:2.3.33"

spotlessPlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotless" }
shadowPlugin = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
licenseReportPlugin = "com.github.jk1.dependency-license-report:com.github.jk1.dependency-license-report.gradle.plugin:2.9"
# Ant should be kept in sync with the version used in the shadow plugin
ant = "org.apache.ant:ant:1.10.15"
# ASM is currently only used during compile-time, so it is okay to diverge from the version used in ByteBuddy
Expand All @@ -81,6 +82,5 @@ jib = { id = "com.google.cloud.tools.jib", version.ref = "jib" }
taskinfo = { id = "org.barfuin.gradle.taskinfo", version = '2.2.0' }
jmh = {id = "me.champeau.jmh", version = "0.7.2"}
nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = '2.0.0' }
licenseReport = { id = "com.github.jk1.dependency-license-report", version = "2.9" }
dockerJavaApplication = { id = "com.bmuschko.docker-java-application", version = "9.4.0" }
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
41 changes: 0 additions & 41 deletions licenses/HdrHistogram-2.2.2.jar/META-INF/LICENSE.txt

This file was deleted.

28 changes: 0 additions & 28 deletions licenses/LICENSE_asm_bsd-3-clause

This file was deleted.

41 changes: 0 additions & 41 deletions licenses/LICENSE_hdrhistogram_bsd-2-clause_cc0

This file was deleted.

Loading