Avoid unnecessary eager creation of Gradle tasks (#45098) (#45310)

This commit is contained in:
Mark Vieira 2019-08-08 10:50:09 -07:00 committed by GitHub
parent b716b840d3
commit 0ae103c40f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 278 additions and 192 deletions

View File

@ -24,10 +24,13 @@ import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.BwcVersions
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.plugin.PluginBuildPlugin
import org.elasticsearch.gradle.tool.Boilerplate
import org.gradle.util.GradleVersion
import org.gradle.util.DistributionLocator
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
plugins {
id 'com.gradle.build-scan' version '2.3'
id 'base'
@ -212,7 +215,7 @@ task branchConsistency {
allprojects {
// ignore missing javadocs
tasks.withType(Javadoc) { Javadoc javadoc ->
tasks.withType(Javadoc).configureEach { Javadoc javadoc ->
// the -quiet here is because of a bug in gradle, in that adding a string option
// by itself is not added to the options. By adding quiet, both this option and
// the "value" -quiet is added, separated by a space. This is ok since the javadoc
@ -329,13 +332,9 @@ allprojects {
}
}
task cleanIdeaBuildDir(type: Delete) {
delete 'build-idea'
tasks.named('cleanIdea') {
delete 'build-idea'
}
cleanIdeaBuildDir.setGroup("ide")
cleanIdeaBuildDir.setDescription("Deletes the IDEA build directory.")
tasks.cleanIdea.dependsOn(cleanIdeaBuildDir)
}
idea {
@ -390,29 +389,20 @@ allprojects {
String lineSeparator = Os.isFamily(Os.FAMILY_WINDOWS) ? '\\\\r\\\\n' : '\\\\n'
String licenseHeader = licenseHeaderFile.getText('UTF-8').replace(System.lineSeparator(), lineSeparator)
task copyEclipseSettings(type: Copy) {
tasks.register('copyEclipseSettings', Copy) {
mustRunAfter 'wipeEclipseSettings'
// TODO: "package this up" for external builds
from new File(project.rootDir, 'buildSrc/src/main/resources/eclipse.settings')
into '.settings'
filter{ it.replaceAll('@@LICENSE_HEADER_TEXT@@', licenseHeader)}
}
// otherwise .settings is not nuked entirely
task wipeEclipseSettings(type: Delete) {
tasks.register('wipeEclipseSettings', Delete) {
delete '.settings'
}
tasks.cleanEclipse.dependsOn(wipeEclipseSettings)
tasks.named('cleanEclipse') { dependsOn 'wipeEclipseSettings' }
// otherwise the eclipse merging is *super confusing*
tasks.eclipse.dependsOn(cleanEclipse, copyEclipseSettings)
// work arround https://github.com/gradle/gradle/issues/6582
tasks.eclipseProject.mustRunAfter tasks.cleanEclipseProject
tasks.matching { it.name == 'eclipseClasspath' }.all {
it.mustRunAfter { tasks.cleanEclipseClasspath }
}
tasks.matching { it.name == 'eclipseJdt' }.all {
it.mustRunAfter { tasks.cleanEclipseJdt }
}
tasks.copyEclipseSettings.mustRunAfter tasks.wipeEclipseSettings
tasks.named('eclipse') { dependsOn 'cleanEclipse', 'copyEclipseSettings' }
}
allprojects {
@ -477,13 +467,11 @@ gradle.projectsEvaluated {
* need to publish artifacts for them.
*/
if (project.name.equals('qa') || project.path.contains(':qa:')) {
Task assemble = project.tasks.findByName('assemble')
if (assemble) {
assemble.enabled = false
maybeConfigure(project.tasks, 'assemble') {
it.enabled = false
}
Task dependenciesInfo = project.tasks.findByName('dependenciesInfo')
if (dependenciesInfo) {
dependenciesInfo.enabled = false
maybeConfigure(project.tasks, 'dependenciesInfo') {
it.enabled = false
}
}
}
@ -505,7 +493,7 @@ gradle.projectsEvaluated {
}
allprojects {
task resolveAllDependencies {
tasks.register('resolveAllDependencies') {
dependsOn tasks.matching { it.name == "pullFixture"}
doLast {
configurations.findAll { it.isCanBeResolved() }.each { it.resolve() }
@ -535,13 +523,13 @@ allprojects {
}
}
task checkPart1
task checkPart2
tasks.matching { it.name == "check" }.all { check ->
if (check.path.startsWith(":x-pack:")) {
checkPart2.dependsOn check
} else {
checkPart1.dependsOn check
}
}
def checkPart1 = tasks.register('checkPart1')
def checkPart2 = tasks.register('checkPart2')
plugins.withId('lifecycle-base') {
if (project.path.startsWith(":x-pack:")) {
checkPart1.configure { dependsOn 'check' }
} else {
checkPart2.configure { dependsOn 'check' }
}
}
}

View File

@ -18,6 +18,7 @@
*/
package org.elasticsearch.gradle
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import groovy.transform.CompileDynamic
@ -66,6 +67,7 @@ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.GroovyCompile
import org.gradle.api.tasks.compile.JavaCompile
@ -82,10 +84,11 @@ import org.gradle.process.ExecSpec
import org.gradle.util.GradleVersion
import java.nio.charset.StandardCharsets
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.nio.file.Files
import java.util.regex.Matcher
import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
/**
* Encapsulates build configuration for elasticsearch projects.
*/
@ -127,7 +130,7 @@ class BuildPlugin implements Plugin<Project> {
// apply global test task failure listener
project.rootProject.pluginManager.apply(TestFailureReportingPlugin)
project.getTasks().create("buildResources", ExportElasticsearchBuildResourcesTask)
project.getTasks().register("buildResources", ExportElasticsearchBuildResourcesTask)
setupSeed(project)
configureRepositories(project)
@ -154,7 +157,7 @@ class BuildPlugin implements Plugin<Project> {
ExtraPropertiesExtension ext = project.extensions.getByType(ExtraPropertiesExtension)
// Common config when running with a FIPS-140 runtime JVM
if (ext.has('inFipsJvm') && ext.get('inFipsJvm')) {
project.tasks.withType(Test) { Test task ->
project.tasks.withType(Test).configureEach { Test task ->
task.systemProperty 'javax.net.ssl.trustStorePassword', 'password'
task.systemProperty 'javax.net.ssl.keyStorePassword', 'password'
}
@ -530,7 +533,7 @@ class BuildPlugin implements Plugin<Project> {
static void configurePomGeneration(Project project) {
// Only works with `enableFeaturePreview('STABLE_PUBLISHING')`
// https://github.com/gradle/gradle/issues/5696#issuecomment-396965185
project.tasks.withType(GenerateMavenPom.class) { GenerateMavenPom generatePOMTask ->
project.tasks.withType(GenerateMavenPom.class).configureEach({ GenerateMavenPom generatePOMTask ->
// The GenerateMavenPom task is aggressive about setting the destination, instead of fighting it,
// just make a copy.
ExtraPropertiesExtension ext = generatePOMTask.extensions.getByType(ExtraPropertiesExtension)
@ -546,12 +549,15 @@ class BuildPlugin implements Plugin<Project> {
}
}
}
// build poms with assemble (if the assemble task exists)
Task assemble = project.tasks.findByName('assemble')
if (assemble && assemble.enabled) {
assemble.dependsOn(generatePOMTask)
} as Action<GenerateMavenPom>)
// build poms with assemble (if the assemble task exists)
maybeConfigure(project.tasks, 'assemble') { assemble ->
if (assemble.enabled) {
assemble.dependsOn(project.tasks.withType(GenerateMavenPom))
}
}
project.plugins.withType(MavenPublishPlugin).whenPluginAdded {
PublishingExtension publishing = project.extensions.getByType(PublishingExtension)
publishing.publications.all { MavenPublication publication -> // we only deal with maven
@ -607,7 +613,7 @@ class BuildPlugin implements Plugin<Project> {
project.afterEvaluate {
File compilerJavaHome = ext.get('compilerJavaHome') as File
project.tasks.withType(JavaCompile) { JavaCompile compileTask ->
project.tasks.withType(JavaCompile).configureEach({ JavaCompile compileTask ->
final JavaVersion targetCompatibilityVersion = JavaVersion.toVersion(compileTask.targetCompatibility)
// we only fork if the Gradle JDK is not the same as the compiler JDK
if (compilerJavaHome.canonicalPath == Jvm.current().javaHome.canonicalPath) {
@ -644,9 +650,9 @@ class BuildPlugin implements Plugin<Project> {
// TODO: use native Gradle support for --release when available (cf. https://github.com/gradle/gradle/issues/2510)
compileTask.options.compilerArgs << '--release' << targetCompatibilityVersion.majorVersion
}
} as Action<JavaCompile>)
// also apply release flag to groovy, which is used in build-tools
project.tasks.withType(GroovyCompile) { GroovyCompile compileTask ->
project.tasks.withType(GroovyCompile).configureEach({ GroovyCompile compileTask ->
// we only fork if the Gradle JDK is not the same as the compiler JDK
if (compilerJavaHome.canonicalPath == Jvm.current().javaHome.canonicalPath) {
compileTask.options.fork = false
@ -655,19 +661,23 @@ class BuildPlugin implements Plugin<Project> {
compileTask.options.forkOptions.javaHome = compilerJavaHome
compileTask.options.compilerArgs << '--release' << JavaVersion.toVersion(compileTask.targetCompatibility).majorVersion
}
}
} as Action<GroovyCompile>)
}
}
static void configureJavadoc(Project project) {
// remove compiled classes from the Javadoc classpath: http://mail.openjdk.java.net/pipermail/javadoc-dev/2018-January/000400.html
final List<File> classes = new ArrayList<>()
project.tasks.withType(JavaCompile) { JavaCompile javaCompile ->
project.tasks.withType(JavaCompile).configureEach { JavaCompile javaCompile ->
classes.add(javaCompile.destinationDir)
}
project.tasks.withType(Javadoc) { Javadoc javadoc ->
project.tasks.withType(Javadoc).configureEach { Javadoc javadoc ->
File compilerJavaHome = project.extensions.getByType(ExtraPropertiesExtension).get('compilerJavaHome') as File
javadoc.executable = new File(compilerJavaHome, 'bin/javadoc')
// only explicitly set javadoc executable if compiler JDK is different from Gradle
// this ensures better cacheability as setting ths input to an absolute path breaks portability
if (Files.isSameFile(compilerJavaHome.toPath(), Jvm.current().getJavaHome().toPath()) == false) {
javadoc.executable = new File(compilerJavaHome, 'bin/javadoc')
}
javadoc.classpath = javadoc.getClasspath().filter { f ->
return classes.contains(f) == false
}
@ -682,21 +692,27 @@ class BuildPlugin implements Plugin<Project> {
/** Adds a javadocJar task to generate a jar containing javadocs. */
static void configureJavadocJar(Project project) {
Jar javadocJarTask = project.tasks.create('javadocJar', Jar)
javadocJarTask.classifier = 'javadoc'
javadocJarTask.group = 'build'
javadocJarTask.description = 'Assembles a jar containing javadocs.'
javadocJarTask.from(project.tasks.getByName(JavaPlugin.JAVADOC_TASK_NAME))
project.tasks.getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(javadocJarTask)
TaskProvider<Jar> javadocJarTask = project.tasks.register('javadocJar', Jar, { Jar jar ->
jar.archiveClassifier.set('javadoc')
jar.group = 'build'
jar.description = 'Assembles a jar containing javadocs.'
jar.from(project.tasks.named(JavaPlugin.JAVADOC_TASK_NAME))
} as Action<Jar>)
maybeConfigure(project.tasks, BasePlugin.ASSEMBLE_TASK_NAME) { Task t ->
t.dependsOn(javadocJarTask)
}
}
static void configureSourcesJar(Project project) {
Jar sourcesJarTask = project.tasks.create('sourcesJar', Jar)
sourcesJarTask.classifier = 'sources'
sourcesJarTask.group = 'build'
sourcesJarTask.description = 'Assembles a jar containing source files.'
sourcesJarTask.from(project.extensions.getByType(SourceSetContainer).getByName(SourceSet.MAIN_SOURCE_SET_NAME).allSource)
project.tasks.getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(sourcesJarTask)
TaskProvider<Jar> sourcesJarTask = project.tasks.register('sourcesJar', Jar, { Jar jar ->
jar.archiveClassifier.set('sources')
jar.group = 'build'
jar.description = 'Assembles a jar containing source files.'
jar.from(project.extensions.getByType(SourceSetContainer).getByName(SourceSet.MAIN_SOURCE_SET_NAME).allSource)
} as Action<Jar>)
maybeConfigure(project.tasks, BasePlugin.ASSEMBLE_TASK_NAME) { Task t ->
t.dependsOn(sourcesJarTask)
}
}
/** Adds additional manifest info to jars */
@ -704,7 +720,7 @@ class BuildPlugin implements Plugin<Project> {
ExtraPropertiesExtension ext = project.extensions.getByType(ExtraPropertiesExtension)
ext.set('licenseFile', null)
ext.set('noticeFile', null)
project.tasks.withType(Jar) { Jar jarTask ->
project.tasks.withType(Jar).configureEach { Jar jarTask ->
// we put all our distributable files under distributions
jarTask.destinationDir = new File(project.buildDir, 'distributions')
// fixup the jar manifest
@ -720,9 +736,10 @@ class BuildPlugin implements Plugin<Project> {
'Build-Date': ext.get('buildDate'),
'Build-Java-Version': compilerJavaVersion)
}
// add license/notice files
project.afterEvaluate {
}
// add license/notice files
project.afterEvaluate {
project.tasks.withType(Jar).configureEach { Jar jarTask ->
if (ext.has('licenseFile') == false || ext.get('licenseFile') == null || ext.has('noticeFile') == false || ext.get('noticeFile') == null) {
throw new GradleException("Must specify license and notice file for project ${project.path}")
}
@ -748,8 +765,8 @@ class BuildPlugin implements Plugin<Project> {
* normal jar with the shadow jar so we no longer want to run
* the jar task.
*/
project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).enabled = false
project.tasks.getByName('shadowJar').configure { ShadowJar shadowJar ->
project.tasks.named(JavaPlugin.JAR_TASK_NAME).configure { it.enabled = false }
project.tasks.named('shadowJar').configure { ShadowJar shadowJar ->
/*
* Replace the default "shadow" classifier with null
* which will leave the classifier off of the file name.
@ -766,7 +783,9 @@ class BuildPlugin implements Plugin<Project> {
shadowJar.configurations = [project.configurations.getByName('bundle')]
}
// Make sure we assemble the shadow jar
project.tasks.getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn project.tasks.getByName('shadowJar')
project.tasks.named(BasePlugin.ASSEMBLE_TASK_NAME).configure {
it.dependsOn project.tasks.named('shadowJar')
}
project.artifacts.add('apiElements', project.tasks.getByName('shadowJar'))
}
}
@ -775,7 +794,7 @@ class BuildPlugin implements Plugin<Project> {
ExtraPropertiesExtension ext = project.extensions.getByType(ExtraPropertiesExtension)
// Default test task should run only unit tests
project.tasks.withType(Test).matching { Test task -> task.name == 'test' }.all { Test task ->
maybeConfigure(project.tasks, 'test', Test) { Test task ->
task.include '**/*Tests.class'
}
@ -783,7 +802,7 @@ class BuildPlugin implements Plugin<Project> {
if (project.path != ':build-tools') {
File heapdumpDir = new File(project.buildDir, 'heapdump')
project.tasks.withType(Test) { Test test ->
project.tasks.withType(Test).configureEach { Test test ->
File testOutputDir = new File(test.reports.junitXml.getDestination(), "output")
ErrorReportingTestListener listener = new ErrorReportingTestListener(test.testLogging, testOutputDir)
@ -894,30 +913,37 @@ class BuildPlugin implements Plugin<Project> {
}
private static configurePrecommit(Project project) {
Task precommit = PrecommitTasks.create(project, true)
project.tasks.getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(precommit)
project.tasks.getByName(JavaPlugin.TEST_TASK_NAME).mustRunAfter(precommit)
TaskProvider precommit = PrecommitTasks.create(project, true)
project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).configure { it.dependsOn(precommit) }
project.tasks.named(JavaPlugin.TEST_TASK_NAME).configure { it.mustRunAfter(precommit) }
// only require dependency licenses for non-elasticsearch deps
(project.tasks.getByName('dependencyLicenses') as DependencyLicensesTask).dependencies = project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME).fileCollection { Dependency dependency ->
dependency.group.startsWith('org.elasticsearch') == false
} - project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
project.plugins.withType(ShadowPlugin).whenPluginAdded {
(project.tasks.getByName('dependencyLicenses') as DependencyLicensesTask).dependencies += project.configurations.getByName('bundle').fileCollection { Dependency dependency ->
project.tasks.withType(DependencyLicensesTask).named('dependencyLicenses').configure {
it.dependencies = project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME).fileCollection { Dependency dependency ->
dependency.group.startsWith('org.elasticsearch') == false
} - project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
}
project.plugins.withType(ShadowPlugin).whenPluginAdded {
project.tasks.withType(DependencyLicensesTask).named('dependencyLicenses').configure {
it.dependencies += project.configurations.getByName('bundle').fileCollection { Dependency dependency ->
dependency.group.startsWith('org.elasticsearch') == false
}
}
}
}
private static configureDependenciesInfo(Project project) {
DependenciesInfoTask deps = project.tasks.create("dependenciesInfo", DependenciesInfoTask)
deps.runtimeConfiguration = project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME)
TaskProvider<DependenciesInfoTask> deps = project.tasks.register("dependenciesInfo", DependenciesInfoTask, { DependenciesInfoTask task ->
task.runtimeConfiguration = project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME)
task.compileOnlyConfiguration = project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
task.getConventionMapping().map('mappings') {
(project.tasks.getByName('dependencyLicenses') as DependencyLicensesTask).mappings
}
} as Action<DependenciesInfoTask>)
project.plugins.withType(ShadowPlugin).whenPluginAdded {
deps.runtimeConfiguration = project.configurations.create('infoDeps')
deps.runtimeConfiguration.extendsFrom(project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME), project.configurations.getByName('bundle'))
}
deps.compileOnlyConfiguration = project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
project.afterEvaluate {
deps.mappings = (project.tasks.getByName('dependencyLicenses') as DependencyLicensesTask).mappings
deps.configure { task ->
task.runtimeConfiguration = project.configurations.create('infoDeps')
task.runtimeConfiguration.extendsFrom(project.configurations.getByName(JavaPlugin.RUNTIME_CONFIGURATION_NAME), project.configurations.getByName('bundle'))
}
}
}

View File

@ -25,6 +25,7 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.DependencyResolutionListener
import org.gradle.api.artifacts.DependencySet
import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputFile
@ -45,7 +46,7 @@ import java.util.regex.Pattern
* </ul>
*
*/
public class DependenciesInfoTask extends DefaultTask {
public class DependenciesInfoTask extends ConventionTask {
/** Dependencies to gather information from. */
@Input
@ -55,8 +56,7 @@ public class DependenciesInfoTask extends DefaultTask {
@Input
public Configuration compileOnlyConfiguration
@Input
public LinkedHashMap<String, String> mappings
private LinkedHashMap<String, String> mappings
/** Directory to read license files */
@InputDirectory
@ -93,7 +93,7 @@ public class DependenciesInfoTask extends DefaultTask {
}
final String url = createURL(dependency.group, dependency.name, dependency.version)
final String dependencyName = DependencyLicensesTask.getDependencyName(mappings, dependency.name)
final String dependencyName = DependencyLicensesTask.getDependencyName(getMappings(), dependency.name)
logger.info("mapped dependency ${dependency.group}:${dependency.name} to ${dependencyName} for license info")
final String licenseType = getLicenseType(dependency.group, dependencyName)
@ -103,7 +103,15 @@ public class DependenciesInfoTask extends DefaultTask {
outputFile.setText(output.toString(), 'UTF-8')
}
/**
@Input
LinkedHashMap<String, String> getMappings() {
return mappings
}
void setMappings(LinkedHashMap<String, String> mappings) {
this.mappings = mappings
}
/**
* Create an URL on <a href="https://repo1.maven.org/maven2/">Maven Central</a>
* based on dependency coordinates.
*/

View File

@ -32,6 +32,7 @@ import org.gradle.api.InvalidUserDataException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
@ -112,7 +113,7 @@ class PluginBuildPlugin implements Plugin<Project> {
addNoticeGeneration(project, extension)
}
}
project.testingConventions {
project.tasks.named('testingConventions').configure {
naming.clear()
naming {
Tests {
@ -175,7 +176,7 @@ class PluginBuildPlugin implements Plugin<Project> {
/** Adds an integTest task which runs rest tests */
private static void createIntegTestTask(Project project) {
RestIntegTestTask integTest = project.tasks.create('integTest', RestIntegTestTask.class)
integTest.mustRunAfter(project.precommit, project.test)
integTest.mustRunAfter('precommit', 'test')
if (project.plugins.hasPlugin(TestClustersPlugin.class) == false) {
// only if not using test clusters
project.integTestCluster.distribution = System.getProperty('tests.distribution', 'integ-test-zip')
@ -259,7 +260,9 @@ class PluginBuildPlugin implements Plugin<Project> {
include 'bin/**'
}
}
project.assemble.dependsOn(bundle)
project.tasks.named(BasePlugin.ASSEMBLE_TASK_NAME).configure {
dependsOn(bundle)
}
// also make the zip available as a configuration (used when depending on this project)
project.configurations.create('zip')

View File

@ -26,11 +26,10 @@ import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.tool.ClasspathUtils
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.plugins.quality.Checkstyle
import org.gradle.api.tasks.TaskProvider
/**
* Validation tasks which should be run before committing. These run before tests.
@ -41,7 +40,7 @@ class PrecommitTasks {
public static final String CHECKSTYLE_VERSION = '8.20'
public static Task create(Project project, boolean includeDependencyLicenses) {
public static TaskProvider create(Project project, boolean includeDependencyLicenses) {
project.configurations.create("forbiddenApisCliJar")
project.dependencies {
forbiddenApisCliJar('de.thetaphi:forbiddenapis:2.6')
@ -57,12 +56,12 @@ class PrecommitTasks {
}
}
List<Task> precommitTasks = [
List<TaskProvider> precommitTasks = [
configureCheckstyle(project),
configureForbiddenApisCli(project),
project.tasks.create('forbiddenPatterns', ForbiddenPatternsTask.class),
project.tasks.create('licenseHeaders', LicenseHeadersTask.class),
project.tasks.create('filepermissions', FilePermissionsTask.class),
project.tasks.register('forbiddenPatterns', ForbiddenPatternsTask),
project.tasks.register('licenseHeaders', LicenseHeadersTask),
project.tasks.register('filepermissions', FilePermissionsTask),
configureJarHell(project, jarHellConfig),
configureThirdPartyAudit(project),
configureTestingConventions(project)
@ -71,11 +70,12 @@ class PrecommitTasks {
// tasks with just tests don't need dependency licenses, so this flag makes adding
// the task optional
if (includeDependencyLicenses) {
DependencyLicensesTask dependencyLicenses = project.tasks.create('dependencyLicenses', DependencyLicensesTask.class)
TaskProvider<DependencyLicensesTask> dependencyLicenses = project.tasks.register('dependencyLicenses', DependencyLicensesTask)
precommitTasks.add(dependencyLicenses)
// we also create the updateShas helper task that is associated with dependencyLicenses
UpdateShasTask updateShas = project.tasks.create('updateShas', UpdateShasTask.class)
updateShas.parentTask = dependencyLicenses
project.tasks.register('updateShas', UpdateShasTask) {
it.parentTask = dependencyLicenses
}
}
if (project.path != ':build-tools') {
/*
@ -93,35 +93,36 @@ class PrecommitTasks {
// We want to get any compilation error before running the pre-commit checks.
project.sourceSets.all { sourceSet ->
precommitTasks.each { task ->
task.shouldRunAfter(sourceSet.getClassesTaskName())
precommitTasks.each { provider ->
provider.configure {
shouldRunAfter(sourceSet.getClassesTaskName())
}
}
}
return project.tasks.create([
name : 'precommit',
group : JavaBasePlugin.VERIFICATION_GROUP,
description: 'Runs all non-test checks.',
dependsOn : precommitTasks
])
return project.tasks.register('precommit') {
group = JavaBasePlugin.VERIFICATION_GROUP
description = 'Runs all non-test checks.'
dependsOn = precommitTasks
}
}
static Task configureTestingConventions(Project project) {
TestingConventionsTasks task = project.getTasks().create("testingConventions", TestingConventionsTasks.class)
task.naming {
Tests {
baseClass "org.apache.lucene.util.LuceneTestCase"
}
IT {
baseClass "org.elasticsearch.test.ESIntegTestCase"
baseClass 'org.elasticsearch.test.rest.ESRestTestCase'
static TaskProvider configureTestingConventions(Project project) {
return project.getTasks().register("testingConventions", TestingConventionsTasks) {
naming {
Tests {
baseClass "org.apache.lucene.util.LuceneTestCase"
}
IT {
baseClass "org.elasticsearch.test.ESIntegTestCase"
baseClass 'org.elasticsearch.test.rest.ESRestTestCase'
}
}
}
return task
}
private static Task configureJarHell(Project project, Configuration jarHelConfig) {
return project.tasks.create('jarHell', JarHellTask) { task ->
private static TaskProvider configureJarHell(Project project, Configuration jarHelConfig) {
return project.tasks.register('jarHell', JarHellTask) { task ->
task.classpath = project.sourceSets.test.runtimeClasspath + jarHelConfig;
if (project.plugins.hasPlugin(ShadowPlugin)) {
task.classpath += project.configurations.bundle
@ -130,9 +131,9 @@ class PrecommitTasks {
}
}
private static Task configureThirdPartyAudit(Project project) {
private static TaskProvider configureThirdPartyAudit(Project project) {
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')
return project.tasks.create('thirdPartyAudit', ThirdPartyAuditTask.class) { task ->
return project.tasks.register('thirdPartyAudit', ThirdPartyAuditTask) { task ->
task.dependsOn(buildResources)
task.signatureFile = buildResources.copy("forbidden/third-party-audit.txt")
task.javaHome = project.runtimeJavaHome
@ -140,10 +141,10 @@ class PrecommitTasks {
}
}
private static Task configureForbiddenApisCli(Project project) {
private static TaskProvider configureForbiddenApisCli(Project project) {
project.pluginManager.apply(ForbiddenApisPlugin)
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')
project.tasks.withType(CheckForbiddenApis) {
project.tasks.withType(CheckForbiddenApis).configureEach {
dependsOn(buildResources)
doFirst {
// we need to defer this configuration since we don't know the runtime java version until execution time
@ -183,12 +184,14 @@ class PrecommitTasks {
)
}
}
Task forbiddenApis = project.tasks.getByName("forbiddenApis")
forbiddenApis.group = ""
TaskProvider forbiddenApis = project.tasks.named("forbiddenApis")
forbiddenApis.configure {
group = ""
}
return forbiddenApis
}
private static Task configureCheckstyle(Project project) {
private static TaskProvider configureCheckstyle(Project project) {
// Always copy the checkstyle configuration files to 'buildDir/checkstyle' since the resources could be located in a jar
// file. If the resources are located in a jar, Gradle will fail when it tries to turn the URL into a file
URL checkstyleConfUrl = PrecommitTasks.getResource("/checkstyle.xml")
@ -196,29 +199,39 @@ class PrecommitTasks {
File checkstyleDir = new File(project.buildDir, "checkstyle")
File checkstyleSuppressions = new File(checkstyleDir, "checkstyle_suppressions.xml")
File checkstyleConf = new File(checkstyleDir, "checkstyle.xml");
Task copyCheckstyleConf = project.tasks.create("copyCheckstyleConf")
TaskProvider copyCheckstyleConf = project.tasks.register("copyCheckstyleConf")
// configure inputs and outputs so up to date works properly
copyCheckstyleConf.outputs.files(checkstyleSuppressions, checkstyleConf)
copyCheckstyleConf.configure {
outputs.files(checkstyleSuppressions, checkstyleConf)
}
if ("jar".equals(checkstyleConfUrl.getProtocol())) {
JarURLConnection jarURLConnection = (JarURLConnection) checkstyleConfUrl.openConnection()
copyCheckstyleConf.inputs.file(jarURLConnection.getJarFileURL())
copyCheckstyleConf.configure {
inputs.file(jarURLConnection.getJarFileURL())
}
} else if ("file".equals(checkstyleConfUrl.getProtocol())) {
copyCheckstyleConf.inputs.files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile())
}
copyCheckstyleConf.doLast {
checkstyleDir.mkdirs()
// withStream will close the output stream and IOGroovyMethods#getBytes reads the InputStream fully and closes it
new FileOutputStream(checkstyleConf).withStream {
it.write(checkstyleConfUrl.openStream().getBytes())
}
new FileOutputStream(checkstyleSuppressions).withStream {
it.write(checkstyleSuppressionsUrl.openStream().getBytes())
copyCheckstyleConf.configure {
inputs.files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile())
}
}
Task checkstyleTask = project.tasks.create('checkstyle')
copyCheckstyleConf.configure {
doLast {
checkstyleDir.mkdirs()
// withStream will close the output stream and IOGroovyMethods#getBytes reads the InputStream fully and closes it
new FileOutputStream(checkstyleConf).withStream {
it.write(checkstyleConfUrl.openStream().getBytes())
}
new FileOutputStream(checkstyleSuppressions).withStream {
it.write(checkstyleSuppressionsUrl.openStream().getBytes())
}
}
}
TaskProvider checkstyleTask = project.tasks.register('checkstyle') {
dependsOn project.tasks.withType(Checkstyle)
}
// Apply the checkstyle plugin to create `checkstyleMain` and `checkstyleTest`. It only
// creates them if there is main or test code to check and it makes `check` depend
// on them. We also want `precommit` to depend on `checkstyle`.
@ -231,8 +244,7 @@ class PrecommitTasks {
toolVersion = CHECKSTYLE_VERSION
}
project.tasks.withType(Checkstyle) { task ->
checkstyleTask.dependsOn(task)
project.tasks.withType(Checkstyle).configureEach { task ->
task.dependsOn(copyCheckstyleConf)
task.inputs.file(checkstyleSuppressions)
task.reports {
@ -243,13 +255,13 @@ class PrecommitTasks {
return checkstyleTask
}
private static Task configureLoggerUsage(Project project) {
private static TaskProvider configureLoggerUsage(Project project) {
Object dependency = ClasspathUtils.isElasticsearchProject() ? project.project(':test:logger-usage') :
"org.elasticsearch.test:logger-usage:${VersionProperties.elasticsearch}"
project.configurations.create('loggerUsagePlugin')
project.dependencies.add('loggerUsagePlugin', dependency)
return project.tasks.create('loggerUsageCheck', LoggerUsageTask.class) {
return project.tasks.register('loggerUsageCheck', LoggerUsageTask) {
classpath = project.configurations.loggerUsagePlugin
}
}

View File

@ -77,7 +77,7 @@ public class GlobalBuildInfoPlugin implements Plugin<Project> {
project.allprojects(p -> {
// Make sure than any task execution generates and prints build info
p.getTasks().all(task -> {
p.getTasks().configureEach(task -> {
if (task != generateTask && task != printTask) {
task.dependsOn(printTask);
}

View File

@ -23,6 +23,7 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider;
import java.io.File;
import java.io.IOException;
@ -40,20 +41,20 @@ public class UpdateShasTask extends DefaultTask {
private final Logger logger = Logging.getLogger(getClass());
/** The parent dependency licenses task to use configuration from */
private DependencyLicensesTask parentTask;
private TaskProvider<DependencyLicensesTask> parentTask;
public UpdateShasTask() {
setDescription("Updates the sha files for the dependencyLicenses check");
setOnlyIf(element -> parentTask.getLicensesDir() != null);
setOnlyIf(element -> parentTask.get().getLicensesDir() != null);
}
@TaskAction
public void updateShas() throws NoSuchAlgorithmException, IOException {
Set<File> shaFiles = parentTask.getShaFiles();
Set<File> shaFiles = parentTask.get().getShaFiles();
for (File dependency : parentTask.getDependencies()) {
for (File dependency : parentTask.get().getDependencies()) {
String jarName = dependency.getName();
File shaFile = parentTask.getShaFile(jarName);
File shaFile = parentTask.get().getShaFile(jarName);
if (shaFile.exists() == false) {
createSha(dependency, jarName, shaFile);
@ -71,16 +72,16 @@ public class UpdateShasTask extends DefaultTask {
private void createSha(File dependency, String jarName, File shaFile) throws IOException, NoSuchAlgorithmException {
logger.lifecycle("Adding sha for " + jarName);
String sha = parentTask.getSha1(dependency);
String sha = parentTask.get().getSha1(dependency);
Files.write(shaFile.toPath(), sha.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
}
public DependencyLicensesTask getParentTask() {
return parentTask;
return parentTask.get();
}
public void setParentTask(DependencyLicensesTask parentTask) {
public void setParentTask(TaskProvider<DependencyLicensesTask> parentTask) {
this.parentTask = parentTask;
}
}

View File

@ -123,7 +123,7 @@ public class TestClustersPlugin implements Plugin<Project> {
private void createUseClusterTaskExtension(Project project, NamedDomainObjectContainer<ElasticsearchCluster> container) {
// register an extension for all current and future tasks, so that any task can declare that it wants to use a
// specific cluster.
project.getTasks().all((Task task) ->
project.getTasks().configureEach((Task task) ->
task.getExtensions().findByType(ExtraPropertiesExtension.class)
.set(
"useCluster",

View File

@ -21,8 +21,12 @@ package org.elasticsearch.gradle.tool;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.TaskProvider;
import java.util.Optional;
@ -37,6 +41,7 @@ public abstract class Boilerplate {
.orElse(collection.create(name));
}
public static <T> T maybeCreate(NamedDomainObjectContainer<T> collection, String name, Action<T> action) {
return Optional.ofNullable(collection.findByName(name))
.orElseGet(() -> {
@ -47,4 +52,37 @@ public abstract class Boilerplate {
}
public static void maybeConfigure(TaskContainer tasks, String name, Action<? super Task> config) {
TaskProvider<?> task;
try {
task = tasks.named(name);
} catch (UnknownTaskException e) {
return;
}
task.configure(config);
}
public static <T extends Task> void maybeConfigure(
TaskContainer tasks, String name,
Class<? extends T> type,
Action<? super T> config
) {
tasks.withType(type).configureEach(task -> {
if (task.getName().equals(name)) {
config.execute(task);
}
});
}
public static TaskProvider<?> findByName(TaskContainer tasks, String name) {
TaskProvider<?> task;
try {
task = tasks.named(name);
} catch (UnknownTaskException e) {
return null;
}
return task;
}
}

View File

@ -1,11 +1,13 @@
package org.elasticsearch.gradle.precommit;
import org.elasticsearch.gradle.test.GradleUnitTestCase;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.Before;
import org.junit.Rule;
@ -31,7 +33,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
private UpdateShasTask updateShas;
private DependencyLicensesTask task;
private TaskProvider<DependencyLicensesTask> task;
private Project project;
@ -51,7 +53,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
expectedException.expectMessage(containsString("exists, but there are no dependencies"));
getLicensesDir(project).mkdir();
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -60,12 +62,12 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
expectedException.expectMessage(containsString("does not exist, but there are dependencies"));
project.getDependencies().add("compile", dependency);
task.checkDependencies();
task.get().checkDependencies();
}
@Test
public void givenProjectWithoutLicensesDirNorDependenciesThenShouldReturnSilently() throws Exception {
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -78,7 +80,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createFileIn(licensesDir, "groovy-all-NOTICE.txt", "");
project.getDependencies().add("compile", project.getDependencies().localGroovy());
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -90,7 +92,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
getLicensesDir(project).mkdir();
updateShas.updateShas();
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -103,7 +105,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createFileIn(getLicensesDir(project), "groovy-all-LICENSE.txt", "");
updateShas.updateShas();
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -113,7 +115,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
File licensesDir = getLicensesDir(project);
createAllDefaultDependencyFiles(licensesDir, "groovy-all");
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -127,7 +129,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createAllDefaultDependencyFiles(licensesDir, "groovy-all");
createFileIn(licensesDir, "non-declared-LICENSE.txt", "");
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -141,7 +143,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createAllDefaultDependencyFiles(licensesDir, "groovy-all");
createFileIn(licensesDir, "non-declared-NOTICE.txt", "");
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -155,7 +157,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createAllDefaultDependencyFiles(licensesDir, "groovy-all");
createFileIn(licensesDir, "non-declared.sha1", "");
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -175,7 +177,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
Files.write(groovySha, new byte[] { 1 }, StandardOpenOption.CREATE);
task.checkDependencies();
task.get().checkDependencies();
}
@Test
@ -189,8 +191,8 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
mappings.put("from", "groovy-all");
mappings.put("to", "groovy");
task.mapping(mappings);
task.checkDependencies();
task.get().mapping(mappings);
task.get().checkDependencies();
}
@Test
@ -201,8 +203,8 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
createFileIn(licensesDir, "groovy-all-LICENSE.txt", "");
createFileIn(licensesDir, "groovy-all-NOTICE.txt", "");
task.ignoreSha("groovy-all");
task.checkDependencies();
task.get().ignoreSha("groovy-all");
task.get().checkDependencies();
}
@Test
@ -210,7 +212,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
expectedException.expect(GradleException.class);
expectedException.expectMessage(containsString("isn't a valid directory"));
task.getShaFiles();
task.get().getShaFiles();
}
private Project createProject() {
@ -244,7 +246,7 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
Files.write(file, content.getBytes(StandardCharsets.UTF_8));
}
private UpdateShasTask createUpdateShasTask(Project project, DependencyLicensesTask dependencyLicensesTask) {
private UpdateShasTask createUpdateShasTask(Project project, TaskProvider<DependencyLicensesTask> dependencyLicensesTask) {
UpdateShasTask task = project.getTasks()
.register("updateShas", UpdateShasTask.class)
.get();
@ -253,12 +255,15 @@ public class DependencyLicensesTaskTests extends GradleUnitTestCase {
return task;
}
private DependencyLicensesTask createDependencyLicensesTask(Project project) {
DependencyLicensesTask task = project.getTasks()
.register("dependencyLicenses", DependencyLicensesTask.class)
.get();
private TaskProvider<DependencyLicensesTask> createDependencyLicensesTask(Project project) {
TaskProvider<DependencyLicensesTask> task = project.getTasks()
.register("dependencyLicenses", DependencyLicensesTask.class, new Action<DependencyLicensesTask>() {
@Override
public void execute(DependencyLicensesTask dependencyLicensesTask) {
dependencyLicensesTask.setDependencies(getDependencies(project));
}
});
task.setDependencies(getDependencies(project));
return task;
}

View File

@ -2,11 +2,13 @@ package org.elasticsearch.gradle.precommit;
import org.apache.commons.io.FileUtils;
import org.elasticsearch.gradle.test.GradleUnitTestCase;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.Before;
import org.junit.Rule;
@ -125,12 +127,15 @@ public class UpdateShasTaskTests extends GradleUnitTestCase {
return task;
}
private DependencyLicensesTask createDependencyLicensesTask(Project project) {
DependencyLicensesTask task = project.getTasks()
.register("dependencyLicenses", DependencyLicensesTask.class)
.get();
private TaskProvider<DependencyLicensesTask> createDependencyLicensesTask(Project project) {
TaskProvider<DependencyLicensesTask> task = project.getTasks()
.register("dependencyLicenses", DependencyLicensesTask.class, new Action<DependencyLicensesTask>() {
@Override
public void execute(DependencyLicensesTask dependencyLicensesTask) {
dependencyLicensesTask.setDependencies(getDependencies(project));
}
});
task.setDependencies(getDependencies(project));
return task;
}