Build: Assert jar LICENSE and NOTICE files match

Adds tasks that check that the all jars that we build have LICENSE.txt
and NOTICE.txt files and that the files are correct. Sets check to
depend on these task.

This is mostly there for extra parnoia because we automatically
configure all Jar tasks to include the LICENSE.txt and NOTICE.txt
files anyway. But it is quite possible to add configuration to those
tasks that would override either file.

This causes check to depend on several more things than it used to.
Take, for example, javadoc:

check depends on the new verifyJavadocJarNotice which depends on
extractJavadocJar which depends on javadocJar which depends on
javadoc, this check now depends on javadoc.
This commit is contained in:
Nik Everett 2018-04-25 09:38:31 -04:00
parent a103533f1d
commit a8f40b3e04
7 changed files with 80 additions and 27 deletions

View File

@ -20,6 +20,7 @@
import org.apache.tools.ant.taskdefs.condition.Os import org.apache.tools.ant.taskdefs.condition.Os
import org.elasticsearch.gradle.BuildPlugin import org.elasticsearch.gradle.BuildPlugin
import org.elasticsearch.gradle.LoggedExec
import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.VersionCollection import org.elasticsearch.gradle.VersionCollection
import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.VersionProperties
@ -30,6 +31,7 @@ import org.gradle.api.tasks.wrapper.Wrapper.DistributionType
import org.gradle.util.GradleVersion import org.gradle.util.GradleVersion
import org.gradle.util.DistributionLocator import org.gradle.util.DistributionLocator
import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.security.MessageDigest import java.security.MessageDigest
@ -459,6 +461,59 @@ gradle.projectsEvaluated {
} }
static void assertLinesInFile(final Path path, final List<String> expectedLines) {
final List<String> actualLines = Files.readAllLines(path)
int line = 0
for (final String expectedLine : expectedLines) {
final String actualLine = actualLines.get(line)
if (expectedLine != actualLine) {
throw new GradleException("expected line [${line + 1}] in [${path}] to be [${expectedLine}] but was [${actualLine}]")
}
line++
}
}
/*
* Check that all generated JARs have our NOTICE.txt and an appropriate
* LICENSE.txt in them. We configurate this in gradle but we'd like to
* be extra paranoid.
*/
subprojects { project ->
project.tasks.withType(Jar).whenTaskAdded { jarTask ->
final Task extract = project.task("extract${jarTask.name.capitalize()}", type: LoggedExec) {
dependsOn jarTask
ext.destination = project.buildDir.toPath().resolve("jar-extracted/${jarTask.name}")
commandLine "${->new File(rootProject.compilerJavaHome, 'bin/jar')}",
'xf', "${-> jarTask.outputs.files.singleFile}", 'META-INF/LICENSE.txt', 'META-INF/NOTICE.txt'
workingDir destination
doFirst {
project.delete(destination)
Files.createDirectories(destination)
}
}
final Task checkNotice = project.task("verify${jarTask.name.capitalize()}Notice") {
dependsOn extract
doLast {
final List<String> noticeLines = Files.readAllLines(project.noticeFile.toPath())
final Path noticePath = extract.destination.resolve('META-INF/NOTICE.txt')
assertLinesInFile(noticePath, noticeLines)
}
}
project.check.dependsOn checkNotice
final Task checkLicense = project.task("verify${jarTask.name.capitalize()}License") {
dependsOn extract
doLast {
final List<String> licenseLines = Files.readAllLines(project.licenseFile.toPath())
final Path licensePath = extract.destination.resolve('META-INF/LICENSE.txt')
assertLinesInFile(licensePath, licenseLines)
}
}
project.check.dependsOn checkLicense
}
}
/* Remove assemble on all qa projects because we don't need to publish /* Remove assemble on all qa projects because we don't need to publish
* artifacts for them. */ * artifacts for them. */
gradle.projectsEvaluated { gradle.projectsEvaluated {

View File

@ -201,8 +201,7 @@ subprojects {
} }
final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename)) final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename))
final Path licensePath = archiveExtractionDir.toPath().resolve("elasticsearch-${VersionProperties.elasticsearch}/LICENSE.txt") final Path licensePath = archiveExtractionDir.toPath().resolve("elasticsearch-${VersionProperties.elasticsearch}/LICENSE.txt")
final List<String> actualLines = Files.readAllLines(licensePath) assertLinesInFile(licensePath, licenseLines)
assertLinesInFile(licensePath, actualLines, licenseLines)
} }
} }
check.dependsOn checkLicense check.dependsOn checkLicense
@ -213,8 +212,7 @@ subprojects {
doLast { doLast {
final List<String> noticeLines = Arrays.asList("Elasticsearch", "Copyright 2009-2018 Elasticsearch") final List<String> noticeLines = Arrays.asList("Elasticsearch", "Copyright 2009-2018 Elasticsearch")
final Path noticePath = archiveExtractionDir.toPath().resolve("elasticsearch-${VersionProperties.elasticsearch}/NOTICE.txt") final Path noticePath = archiveExtractionDir.toPath().resolve("elasticsearch-${VersionProperties.elasticsearch}/NOTICE.txt")
final List<String> actualLines = Files.readAllLines(noticePath) assertLinesInFile(noticePath, noticeLines)
assertLinesInFile(noticePath, actualLines, noticeLines)
} }
} }
check.dependsOn checkNotice check.dependsOn checkNotice
@ -304,4 +302,3 @@ configure(subprojects.findAll { it.name.contains('zip') }) {
} }
} }
} }

View File

@ -460,14 +460,3 @@ subprojects {
return result return result
} }
} }
static void assertLinesInFile(final Path path, final List<String> actualLines, final List<String> expectedLines) {
int line = 0
for (final String expectedLine : expectedLines) {
final String actualLine = actualLines.get(line)
if (expectedLine != actualLine) {
throw new GradleException("expected line [${line + 1}] in [${path}] to be [${expectedLine}] but was [${actualLine}]")
}
line++
}
}

View File

@ -415,8 +415,7 @@ subprojects {
"License: " + expectedLicense) "License: " + expectedLicense)
final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename)) final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename))
final List<String> expectedLines = header + licenseLines.collect { " " + it } final List<String> expectedLines = header + licenseLines.collect { " " + it }
final List<String> actualLines = Files.readAllLines(copyrightPath) assertLinesInFile(copyrightPath, expectedLines)
assertLinesInFile(copyrightPath, actualLines, expectedLines)
} }
} }
} else { } else {
@ -432,8 +431,7 @@ subprojects {
} }
final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename)) final List<String> licenseLines = Files.readAllLines(rootDir.toPath().resolve("licenses/" + licenseFilename))
final Path licensePath = packageExtractionDir.toPath().resolve("usr/share/elasticsearch/LICENSE.txt") final Path licensePath = packageExtractionDir.toPath().resolve("usr/share/elasticsearch/LICENSE.txt")
final List<String> actualLines = Files.readAllLines(licensePath) assertLinesInFile(licensePath, licenseLines)
assertLinesInFile(licensePath, actualLines, licenseLines)
} }
} }
} }
@ -444,8 +442,7 @@ subprojects {
doLast { doLast {
final List<String> noticeLines = Arrays.asList("Elasticsearch", "Copyright 2009-2018 Elasticsearch") final List<String> noticeLines = Arrays.asList("Elasticsearch", "Copyright 2009-2018 Elasticsearch")
final Path noticePath = packageExtractionDir.toPath().resolve("usr/share/elasticsearch/NOTICE.txt") final Path noticePath = packageExtractionDir.toPath().resolve("usr/share/elasticsearch/NOTICE.txt")
final List<String> actualLines = Files.readAllLines(noticePath) assertLinesInFile(noticePath, noticeLines)
assertLinesInFile(noticePath, actualLines, noticeLines)
} }
} }
check.dependsOn checkNotice check.dependsOn checkNotice

View File

@ -23,10 +23,8 @@ subprojects {
ext.licenseName = 'Elastic License' ext.licenseName = 'Elastic License'
ext.licenseUrl = "https://raw.githubusercontent.com/elastic/elasticsearch/${licenseCommit}/licenses/ELASTIC-LICENSE.txt" ext.licenseUrl = "https://raw.githubusercontent.com/elastic/elasticsearch/${licenseCommit}/licenses/ELASTIC-LICENSE.txt"
plugins.withType(BuildPlugin).whenPluginAdded { project.ext.licenseFile = rootProject.file('licenses/ELASTIC-LICENSE.txt')
project.licenseFile = rootProject.file('licenses/ELASTIC-LICENSE.txt') project.ext.noticeFile = xpackRootProject.file('NOTICE.txt')
project.noticeFile = xpackRootProject.file('NOTICE.txt')
}
plugins.withType(PluginBuildPlugin).whenPluginAdded { plugins.withType(PluginBuildPlugin).whenPluginAdded {
project.esplugin.licenseFile = rootProject.file('licenses/ELASTIC-LICENSE.txt') project.esplugin.licenseFile = rootProject.file('licenses/ELASTIC-LICENSE.txt')

View File

@ -31,6 +31,20 @@ configurations {
task testJar(type: Jar) { task testJar(type: Jar) {
appendix 'test' appendix 'test'
from sourceSets.test.output from sourceSets.test.output
/*
* Stick the license and notice file in the jar. This isn't strictly
* needed because we don't publish it but it makes our super-paranoid
* tests happy.
*/
metaInf {
from(project.licenseFile.parent) {
include project.licenseFile.name
rename { 'LICENSE.txt' }
}
from(project.noticeFile.parent) {
include project.noticeFile.name
}
}
} }
artifacts { artifacts {
testArtifacts testJar testArtifacts testJar

View File

@ -45,9 +45,12 @@ dependencyLicenses {
* can be easilly shipped around and used. * can be easilly shipped around and used.
*/ */
jar { jar {
from { from({
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}) {
// We don't need the META-INF from the things we bundle. For now.
exclude 'META-INF/*'
} }
manifest { manifest {
attributes 'Main-Class': 'org.elasticsearch.xpack.sql.cli.Cli' attributes 'Main-Class': 'org.elasticsearch.xpack.sql.cli.Cli'