Skip to content

Commit f458c82

Browse files
fix: Only include project LICENSE and NOTICE in Spark Client Jar
Previously the build code would add LICENSE and NOTICE files from other shaded dependencies, some of which could potentially shade the project's LICENSE or NOTICE or cause confusion as to which file was correct. To fix this a post-processing task is added which removes all potentially confusing files and manually adds the project LICENSE and NOTICE files back to the jar.
1 parent e7a009f commit f458c82

File tree

1 file changed

+83
-7
lines changed

1 file changed

+83
-7
lines changed

plugins/spark/v3.5/spark/build.gradle.kts

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@ tasks.register<ShadowJar>("createPolarisSparkJar") {
8585
archiveClassifier = "bundle"
8686
isZip64 = true
8787

88-
// include the LICENSE and NOTICE files for the shadow Jar
89-
from(projectDir) {
90-
include("LICENSE")
91-
include("NOTICE")
92-
}
93-
9488
// pack both the source code and dependencies
9589
from(sourceSets.main.get().output)
9690
configurations = listOf(project.configurations.runtimeClasspath.get())
@@ -99,9 +93,91 @@ tasks.register<ShadowJar>("createPolarisSparkJar") {
9993
// The iceberg-spark-runtime plugin is always packaged along with our polaris-spark plugin,
10094
// therefore excluded from the optimization.
10195
minimize { exclude(dependency("org.apache.iceberg:iceberg-spark-runtime-*.*")) }
96+
97+
// Always run the license file addition after this task completes
98+
finalizedBy("addLicenseFilesToJar")
99+
}
100+
101+
// Post-processing task to add our project's LICENSE and NOTICE files to the jar and remove any
102+
// other LICENSE or NOTICE files that were shaded in.
103+
tasks.register("addLicenseFilesToJar") {
104+
dependsOn("createPolarisSparkJar")
105+
106+
doLast {
107+
val shadowTask = tasks.named("createPolarisSparkJar", ShadowJar::class.java).get()
108+
val jarFile = shadowTask.archiveFile.get().asFile
109+
val tempDir =
110+
File(
111+
"${project.layout.buildDirectory.get().asFile}/tmp/jar-cleanup-${shadowTask.archiveBaseName.get()}-${shadowTask.archiveClassifier.get()}"
112+
)
113+
val projectLicenseFile = File(projectDir, "LICENSE")
114+
val projectNoticeFile = File(projectDir, "NOTICE")
115+
116+
// Validate that required license files exist
117+
if (!projectLicenseFile.exists()) {
118+
throw GradleException("Project LICENSE file not found at: ${projectLicenseFile.absolutePath}")
119+
}
120+
if (!projectNoticeFile.exists()) {
121+
throw GradleException("Project NOTICE file not found at: ${projectNoticeFile.absolutePath}")
122+
}
123+
124+
println("Processing jar: ${jarFile.absolutePath}")
125+
println("Using temp directory: ${tempDir.absolutePath}")
126+
127+
// Clean up temp directory
128+
if (tempDir.exists()) {
129+
tempDir.deleteRecursively()
130+
}
131+
tempDir.mkdirs()
132+
133+
// Extract the jar
134+
copy {
135+
from(zipTree(jarFile))
136+
into(tempDir)
137+
}
138+
139+
fileTree(tempDir)
140+
.matching {
141+
include("LICENSE*")
142+
include("NOTICE*")
143+
include("META-INF/LICENSE*")
144+
include("META-INF/NOTICE*")
145+
}
146+
.forEach { file ->
147+
println("Removing license file: ${file.relativeTo(tempDir)}")
148+
file.delete()
149+
}
150+
151+
// Copy our project's license files to root
152+
copy {
153+
from(projectLicenseFile)
154+
into(tempDir)
155+
}
156+
println("Added project LICENSE file")
157+
158+
copy {
159+
from(projectNoticeFile)
160+
into(tempDir)
161+
}
162+
println("Added project NOTICE file")
163+
164+
// Delete the original jar
165+
jarFile.delete()
166+
167+
// Create new jar with only project LICENSE and NOTICE files
168+
ant.withGroovyBuilder {
169+
"jar"("destfile" to jarFile.absolutePath) { "fileset"("dir" to tempDir.absolutePath) }
170+
}
171+
172+
println("Recreated jar with only project LICENSE and NOTICE files")
173+
174+
// Clean up temp directory
175+
tempDir.deleteRecursively()
176+
}
102177
}
103178

104-
// ensure the ShadowJar job is run for both `assemble` and `build` task
179+
// ensure the shadow jar job (which will automatically run license addition) is run for both
180+
// `assemble` and `build` task
105181
tasks.named("assemble") { dependsOn("createPolarisSparkJar") }
106182

107183
tasks.named("build") { dependsOn("createPolarisSparkJar") }

0 commit comments

Comments
 (0)