From 33ca5ba44bc0001ad1f0c3063001a7ac24d439dc Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 20 May 2020 14:12:36 -0700 Subject: [PATCH] Add individual precommit task plugins (#56926) (#57015) Each precommit task is currently registered inside the shared PrecommitTasks class. Having a single class with all precommit tasks makes individualizing which precommit tasks are needed based on type of project difficult, where we often just disable somet tasks eg for all qa projects. This commit creates plugins for each precommit task, and moves the configuration of the task into each plugin. PrecommitTasks remains for now, and just delegates to each plugin, but will be removed in a future change. --- .../elasticsearch/gradle/BuildPlugin.groovy | 17 +- .../LicenseHeadersPrecommitPlugin.groovy | 31 +++ .../gradle/precommit/PrecommitTasks.groovy | 245 +----------------- .../test/StandaloneRestTestPlugin.groovy | 1 - .../elasticsearch/gradle/PublishPlugin.java | 2 + .../precommit/CheckstylePrecommitPlugin.java | 101 ++++++++ .../DependencyLicensesPrecommitPlugin.java | 49 ++++ .../precommit/DependencyLicensesTask.java | 6 +- .../FilePermissionsPrecommitPlugin.java | 31 +++ .../ForbiddenApisPrecommitPlugin.java | 124 +++++++++ .../ForbiddenPatternsPrecommitPlugin.java | 31 +++ .../precommit/JarHellPrecommitPlugin.java | 50 ++++ .../precommit/LoggerUsagePrecommitPlugin.java | 43 +++ .../gradle/precommit/PomValidationPlugin.java | 53 ---- .../PomValidationPrecommitPlugin.java | 54 ++++ .../gradle/precommit/PrecommitPlugin.java | 75 ++++++ .../TestingConventionsPrecommitPlugin.java | 40 +++ .../precommit/TestingConventionsTasks.java | 2 +- .../ThirdPartyAuditPrecommitPlugin.java | 46 ++++ 19 files changed, 696 insertions(+), 305 deletions(-) create mode 100644 buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/LicenseHeadersPrecommitPlugin.groovy create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/CheckstylePrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/FilePermissionsPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenApisPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenPatternsPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/JarHellPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/LoggerUsagePrecommitPlugin.java delete mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsPrecommitPlugin.java create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditPrecommitPlugin.java diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index c3c2c8bb675..00169f35284 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -23,7 +23,6 @@ import groovy.transform.CompileStatic import org.apache.commons.io.IOUtils import org.elasticsearch.gradle.info.BuildParams import org.elasticsearch.gradle.info.GlobalBuildInfoPlugin -import org.elasticsearch.gradle.precommit.DependencyLicensesTask import org.elasticsearch.gradle.precommit.PrecommitTasks import org.elasticsearch.gradle.test.ErrorReportingTestListener import org.elasticsearch.gradle.testclusters.ElasticsearchCluster @@ -51,10 +50,8 @@ import org.gradle.api.credentials.HttpHeaderCredentials import org.gradle.api.execution.TaskActionListener import org.gradle.api.plugins.ExtraPropertiesExtension import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.testing.Test import org.gradle.authentication.http.HttpHeaderAuthentication -import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.util.GradleVersion import java.nio.charset.StandardCharsets @@ -98,7 +95,7 @@ class BuildPlugin implements Plugin { configureRepositories(project) project.extensions.getByType(ExtraPropertiesExtension).set('versions', VersionProperties.versions) - configurePrecommit(project) + PrecommitTasks.create(project, true) configureFips140(project) } @@ -276,18 +273,6 @@ class BuildPlugin implements Plugin { } } - private static configurePrecommit(Project project) { - 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.withType(DependencyLicensesTask).named('dependencyLicenses').configure { - it.dependencies = project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).fileCollection { Dependency dependency -> - dependency.group.startsWith('org.elasticsearch') == false - } - project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME) - } - } - private static class TestFailureReportingPlugin implements Plugin { @Override void apply(Project project) { diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/LicenseHeadersPrecommitPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/LicenseHeadersPrecommitPlugin.groovy new file mode 100644 index 00000000000..fcf23a2119e --- /dev/null +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/LicenseHeadersPrecommitPlugin.groovy @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.TaskProvider + +class LicenseHeadersPrecommitPlugin extends PrecommitPlugin { + @Override + TaskProvider createTask(Project project) { + return project.getTasks().register("licenseHeaders", LicenseHeadersTask.class); + } +} diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy index 3ce2454181f..98863224daa 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy @@ -18,20 +18,8 @@ */ package org.elasticsearch.gradle.precommit -import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis -import de.thetaphi.forbiddenapis.gradle.ForbiddenApisPlugin -import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask -import org.elasticsearch.gradle.VersionProperties -import org.elasticsearch.gradle.info.BuildParams -import org.elasticsearch.gradle.util.Util -import org.gradle.api.JavaVersion + import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection -import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.plugins.quality.Checkstyle -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.TaskProvider /** * Validation tasks which should be run before committing. These run before tests. @@ -40,42 +28,21 @@ class PrecommitTasks { /** Adds a precommit task, which depends on non-test verification tasks. */ - public static TaskProvider create(Project project, boolean includeDependencyLicenses) { - project.configurations.create("forbiddenApisCliJar") - project.dependencies { - forbiddenApisCliJar('de.thetaphi:forbiddenapis:2.7') - } + public static void create(Project project, boolean includeDependencyLicenses) { - Configuration jarHellConfig = project.configurations.create("jarHell") - if (BuildParams.internal && project.path.equals(":libs:elasticsearch-core") == false) { - // External plugins will depend on this already via transitive dependencies. - // Internal projects are not all plugins, so make sure the check is available - // we are not doing this for this project itself to avoid jar hell with itself - project.dependencies { - jarHell project.project(":libs:elasticsearch-core") - } - } - - List precommitTasks = [ - configureCheckstyle(project), - configureForbiddenApisCli(project), - project.tasks.register('forbiddenPatterns', ForbiddenPatternsTask), - project.tasks.register('licenseHeaders', LicenseHeadersTask), - project.tasks.register('filepermissions', FilePermissionsTask), - configureJarHell(project, jarHellConfig), - configureThirdPartyAudit(project), - configureTestingConventions(project) - ] + project.pluginManager.apply(CheckstylePrecommitPlugin) + project.pluginManager.apply(ForbiddenApisPrecommitPlugin) + project.pluginManager.apply(JarHellPrecommitPlugin) + project.pluginManager.apply(ForbiddenPatternsPrecommitPlugin) + project.pluginManager.apply(LicenseHeadersPrecommitPlugin) + project.pluginManager.apply(FilePermissionsPrecommitPlugin) + project.pluginManager.apply(ThirdPartyAuditPrecommitPlugin) + project.pluginManager.apply(TestingConventionsPrecommitPlugin) // tasks with just tests don't need dependency licenses, so this flag makes adding // the task optional if (includeDependencyLicenses) { - TaskProvider dependencyLicenses = project.tasks.register('dependencyLicenses', DependencyLicensesTask) - precommitTasks.add(dependencyLicenses) - // we also create the updateShas helper task that is associated with dependencyLicenses - project.tasks.register('updateShas', UpdateShasTask) { - it.parentTask = dependencyLicenses - } + project.pluginManager.apply(DependencyLicensesPrecommitPlugin) } if (project.path != ':build-tools') { /* @@ -88,195 +55,7 @@ class PrecommitTasks { * use the NamingConventionsCheck we break the circular dependency * here. */ - precommitTasks.add(configureLoggerUsage(project)) - } - - // We want to get any compilation error before running the pre-commit checks. - project.sourceSets.all { sourceSet -> - precommitTasks.each { provider -> - provider.configure { - shouldRunAfter(sourceSet.getClassesTaskName()) - } - } - } - - TaskProvider precommit = project.tasks.register('precommit') { - group = JavaBasePlugin.VERIFICATION_GROUP - description = 'Runs all non-test checks.' - dependsOn = precommitTasks - } - - // not all jar projects produce a pom (we don't ship all jars), so a pom validation - // task is only added on some projects, and thus we can't always have a task - // here to add to precommit tasks explicitly. Instead, we apply our internal - // pom validation plugin after the precommit task is created and let the - // plugin add the task if necessary - project.plugins.apply(PomValidationPlugin) - - return precommit - } - - 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' - } - } - } - } - - private static TaskProvider configureJarHell(Project project, Configuration jarHellConfig) { - return project.tasks.register('jarHell', JarHellTask) { task -> - task.classpath = project.sourceSets.test.runtimeClasspath + jarHellConfig - task.dependsOn(jarHellConfig) - } - } - - private static TaskProvider configureThirdPartyAudit(Project project) { - ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources') - return project.tasks.register('thirdPartyAudit', ThirdPartyAuditTask) { task -> - task.dependsOn(buildResources) - task.signatureFile = buildResources.copy("forbidden/third-party-audit.txt") - task.javaHome = BuildParams.runtimeJavaHome - task.targetCompatibility.set(project.provider({ BuildParams.runtimeJavaVersion })) - } - } - - private static TaskProvider configureForbiddenApisCli(Project project) { - project.pluginManager.apply(ForbiddenApisPlugin) - ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources') - project.tasks.withType(CheckForbiddenApis).configureEach { - dependsOn(buildResources) - - assert name.startsWith(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME) - String sourceSetName - if (ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.equals(name)) { - sourceSetName = "main" - } else { - //parse out the sourceSetName - char[] chars = name.substring(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.length()).toCharArray() - chars[0] = Character.toLowerCase(chars[0]) - sourceSetName = new String(chars) - } - - SourceSet sourceSet = project.sourceSets.getByName(sourceSetName) - classpath = project.files { sourceSet.runtimeClasspath.plus(sourceSet.compileClasspath) } - - targetCompatibility = BuildParams.runtimeJavaVersion.majorVersion - if (BuildParams.runtimeJavaVersion > JavaVersion.VERSION_14) { - // TODO: forbidden apis does not yet support java 15, rethink using runtime version - targetCompatibility = JavaVersion.VERSION_14.majorVersion - } - bundledSignatures = [ - "jdk-unsafe", "jdk-deprecated", "jdk-non-portable", "jdk-system-out" - ] - signaturesFiles = project.files( - buildResources.copy("forbidden/jdk-signatures.txt"), - buildResources.copy("forbidden/es-all-signatures.txt") - ) - suppressAnnotations = ['**.SuppressForbidden'] - if (name.endsWith('Test')) { - signaturesFiles += project.files( - buildResources.copy("forbidden/es-test-signatures.txt"), - buildResources.copy("forbidden/http-signatures.txt") - ) - } else { - signaturesFiles += project.files(buildResources.copy("forbidden/es-server-signatures.txt")) - } - ext.replaceSignatureFiles = { String... names -> - signaturesFiles = project.files( - names.collect { buildResources.copy("forbidden/${it}.txt") } - ) - } - ext.addSignatureFiles = { String... names -> - signaturesFiles += project.files( - names.collect { buildResources.copy("forbidden/${it}.txt") } - ) - } - } - TaskProvider forbiddenApis = project.tasks.named("forbiddenApis") - forbiddenApis.configure { - group = "" - } - return forbiddenApis - } - - 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") - URL checkstyleSuppressionsUrl = PrecommitTasks.getResource("/checkstyle_suppressions.xml") - File checkstyleDir = new File(project.buildDir, "checkstyle") - File checkstyleSuppressions = new File(checkstyleDir, "checkstyle_suppressions.xml") - File checkstyleConf = new File(checkstyleDir, "checkstyle.xml"); - TaskProvider copyCheckstyleConf = project.tasks.register("copyCheckstyleConf") - - // configure inputs and outputs so up to date works properly - copyCheckstyleConf.configure { - outputs.files(checkstyleSuppressions, checkstyleConf) - } - if ("jar".equals(checkstyleConfUrl.getProtocol())) { - JarURLConnection jarURLConnection = (JarURLConnection) checkstyleConfUrl.openConnection() - copyCheckstyleConf.configure { - inputs.file(jarURLConnection.getJarFileURL()) - } - } else if ("file".equals(checkstyleConfUrl.getProtocol())) { - copyCheckstyleConf.configure { - inputs.files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile()) - } - } - - 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`. - project.pluginManager.apply('checkstyle') - project.checkstyle { - configDir = checkstyleDir - } - project.dependencies { - checkstyle "com.puppycrawl.tools:checkstyle:${VersionProperties.versions.checkstyle}" - checkstyle project.files(Util.buildSrcCodeSource) - } - - project.tasks.withType(Checkstyle).configureEach { task -> - task.dependsOn(copyCheckstyleConf) - task.reports { - html.enabled false - } - } - - return checkstyleTask - } - - private static TaskProvider configureLoggerUsage(Project project) { - Object dependency = BuildParams.internal ? project.project(':test:logger-usage') : - "org.elasticsearch.test:logger-usage:${VersionProperties.elasticsearch}" - - project.configurations.create('loggerUsagePlugin') - project.dependencies.add('loggerUsagePlugin', dependency) - return project.tasks.register('loggerUsageCheck', LoggerUsageTask) { - classpath = project.configurations.loggerUsagePlugin + project.pluginManager.apply(LoggerUsagePrecommitPlugin) } } } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy index 4aac7eba1a8..23298344936 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy @@ -95,6 +95,5 @@ class StandaloneRestTestPlugin implements Plugin { idea.module.scopes.put('TEST', [plus: [project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME)]] as Map>) PrecommitTasks.create(project, false) - project.tasks.named('check').configure { it.dependsOn(project.tasks.named('precommit')) } } } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/PublishPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/PublishPlugin.java index 857f5c73316..c67473e24ba 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/PublishPlugin.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/PublishPlugin.java @@ -24,6 +24,7 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowExtension; import groovy.util.Node; import groovy.util.NodeList; import org.elasticsearch.gradle.info.BuildParams; +import org.elasticsearch.gradle.precommit.PomValidationPrecommitPlugin; import org.elasticsearch.gradle.util.Util; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -50,6 +51,7 @@ public class PublishPlugin implements Plugin { @Override public void apply(Project project) { project.getPluginManager().apply("nebula.maven-base-publish"); + project.getPluginManager().apply(PomValidationPrecommitPlugin.class); configureJavadocJar(project); configureSourcesJar(project); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/CheckstylePrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/CheckstylePrecommitPlugin.java new file mode 100644 index 00000000000..2c6fd329750 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/CheckstylePrecommitPlugin.java @@ -0,0 +1,101 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.VersionProperties; +import org.elasticsearch.gradle.util.Util; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.plugins.quality.Checkstyle; +import org.gradle.api.plugins.quality.CheckstyleExtension; +import org.gradle.api.tasks.TaskProvider; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.JarURLConnection; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +public class CheckstylePrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(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 = CheckstylePrecommitPlugin.class.getResource("/checkstyle.xml"); + URL checkstyleSuppressionsUrl = CheckstylePrecommitPlugin.class.getResource("/checkstyle_suppressions.xml"); + File checkstyleDir = new File(project.getBuildDir(), "checkstyle"); + File checkstyleSuppressions = new File(checkstyleDir, "checkstyle_suppressions.xml"); + File checkstyleConf = new File(checkstyleDir, "checkstyle.xml"); + TaskProvider copyCheckstyleConf = project.getTasks().register("copyCheckstyleConf"); + + // configure inputs and outputs so up to date works properly + copyCheckstyleConf.configure(t -> t.getOutputs().files(checkstyleSuppressions, checkstyleConf)); + if ("jar".equals(checkstyleConfUrl.getProtocol())) { + try { + JarURLConnection jarURLConnection = (JarURLConnection) checkstyleConfUrl.openConnection(); + copyCheckstyleConf.configure(t -> t.getInputs().file(jarURLConnection.getJarFileURL())); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } else if ("file".equals(checkstyleConfUrl.getProtocol())) { + copyCheckstyleConf.configure(t -> t.getInputs().files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile())); + } + + copyCheckstyleConf.configure(t -> t.doLast(task -> { + checkstyleDir.mkdirs(); + try (InputStream stream = checkstyleConfUrl.openStream()) { + Files.copy(stream, checkstyleConf.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + try (InputStream stream = checkstyleSuppressionsUrl.openStream()) { + Files.copy(stream, checkstyleSuppressions.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + })); + + TaskProvider checkstyleTask = project.getTasks().register("checkstyle"); + checkstyleTask.configure(t -> t.dependsOn(project.getTasks().withType(Checkstyle.class))); + + // 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`. + project.getPluginManager().apply("checkstyle"); + CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class); + checkstyle.getConfigDirectory().set(checkstyleDir); + + DependencyHandler dependencies = project.getDependencies(); + String checkstyleVersion = VersionProperties.getVersions().get("checkstyle"); + dependencies.add("checkstyle", "com.puppycrawl.tools:checkstyle:" + checkstyleVersion); + dependencies.add("checkstyle", project.files(Util.getBuildSrcCodeSource())); + + project.getTasks().withType(Checkstyle.class).configureEach(t -> { + t.dependsOn(copyCheckstyleConf); + t.reports(r -> r.getHtml().setEnabled(false)); + }); + + return checkstyleTask; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesPrecommitPlugin.java new file mode 100644 index 00000000000..f1bc11a44c2 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesPrecommitPlugin.java @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.TaskProvider; + +public class DependencyLicensesPrecommitPlugin extends PrecommitPlugin { + + @Override + public TaskProvider createTask(Project project) { + TaskProvider dependencyLicenses = project.getTasks() + .register("dependencyLicenses", DependencyLicensesTask.class); + + // only require dependency licenses for non-elasticsearch deps + dependencyLicenses.configure(t -> { + Configuration runtimeClasspath = project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); + Configuration compileOnly = project.getConfigurations().getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME); + t.setDependencies( + runtimeClasspath.fileCollection(dependency -> dependency.getGroup().startsWith("org.elasticsearch") == false) + .minus(compileOnly) + ); + }); + + // we also create the updateShas helper task that is associated with dependencyLicenses + project.getTasks().register("updateShas", UpdateShasTask.class, t -> t.setParentTask(dependencyLicenses)); + return dependencyLicenses; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesTask.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesTask.java index 73817199245..5c7b5e55d86 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesTask.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/DependencyLicensesTask.java @@ -186,7 +186,11 @@ public class DependencyLicensesTask extends DefaultTask { } return; // no dependencies to check } else if (licensesDir.exists() == false) { - throw new GradleException("Licences dir " + licensesDir + " does not exist, but there are dependencies"); + String deps = ""; + for (File file : dependencies) { + deps += file.getName() + "\n"; + } + throw new GradleException("Licences dir " + licensesDir + " does not exist, but there are dependencies: " + deps); } Map licenses = new HashMap<>(); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/FilePermissionsPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/FilePermissionsPrecommitPlugin.java new file mode 100644 index 00000000000..82fd55164af --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/FilePermissionsPrecommitPlugin.java @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.TaskProvider; + +public class FilePermissionsPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + return project.getTasks().register("filepermissions", FilePermissionsTask.class); + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenApisPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenApisPrecommitPlugin.java new file mode 100644 index 00000000000..a5c8e82fe14 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenApisPrecommitPlugin.java @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis; +import de.thetaphi.forbiddenapis.gradle.ForbiddenApisPlugin; +import groovy.lang.Closure; +import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask; +import org.elasticsearch.gradle.info.BuildParams; +import org.elasticsearch.gradle.util.GradleUtils; +import org.gradle.api.JavaVersion; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.plugins.ExtraPropertiesExtension; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.api.tasks.TaskProvider; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class ForbiddenApisPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + project.getPluginManager().apply(ForbiddenApisPlugin.class); + + TaskProvider buildResources = project.getTasks() + .named("buildResources", ExportElasticsearchBuildResourcesTask.class); + project.getTasks().withType(CheckForbiddenApis.class).configureEach(t -> { + ExportElasticsearchBuildResourcesTask buildResourcesTask = buildResources.get(); + t.dependsOn(buildResources); + + assert t.getName().startsWith(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME); + String sourceSetName; + if (ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.equals(t.getName())) { + sourceSetName = "main"; + } else { + // parse out the sourceSetName + char[] chars = t.getName().substring(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.length()).toCharArray(); + chars[0] = Character.toLowerCase(chars[0]); + sourceSetName = new String(chars); + } + + SourceSetContainer sourceSets = GradleUtils.getJavaSourceSets(project); + SourceSet sourceSet = sourceSets.getByName(sourceSetName); + t.setClasspath(project.files(sourceSet.getRuntimeClasspath()).plus(sourceSet.getCompileClasspath())); + + t.setTargetCompatibility(BuildParams.getRuntimeJavaVersion().getMajorVersion()); + if (BuildParams.getRuntimeJavaVersion().compareTo(JavaVersion.VERSION_14) > 0) { + // TODO: forbidden apis does not yet support java 15, rethink using runtime version + t.setTargetCompatibility(JavaVersion.VERSION_14.getMajorVersion()); + } + t.setBundledSignatures(Set.of("jdk-unsafe", "jdk-deprecated", "jdk-non-portable", "jdk-system-out")); + t.setSignaturesFiles( + project.files( + buildResourcesTask.copy("forbidden/jdk-signatures.txt"), + buildResourcesTask.copy("forbidden/es-all-signatures.txt") + ) + ); + t.setSuppressAnnotations(Set.of("**.SuppressForbidden")); + if (t.getName().endsWith("Test")) { + t.setSignaturesFiles( + t.getSignaturesFiles() + .plus( + project.files( + buildResourcesTask.copy("forbidden/es-test-signatures.txt"), + buildResourcesTask.copy("forbidden/http-signatures.txt") + ) + ) + ); + } else { + t.setSignaturesFiles( + t.getSignaturesFiles().plus(project.files(buildResourcesTask.copy("forbidden/es-server-signatures.txt"))) + ); + } + ExtraPropertiesExtension ext = t.getExtensions().getExtraProperties(); + ext.set("replaceSignatureFiles", new Closure(t) { + @Override + public Void call(Object... names) { + List resources = new ArrayList<>(names.length); + for (Object name : names) { + resources.add(buildResourcesTask.copy("forbidden/" + name + ".txt")); + } + t.setSignaturesFiles(project.files(resources)); + return null; + } + + }); + ext.set("addSignatureFiles", new Closure(t) { + @Override + public Void call(Object... names) { + List resources = new ArrayList<>(names.length); + for (Object name : names) { + resources.add(buildResourcesTask.copy("forbidden/" + name + ".txt")); + } + t.setSignaturesFiles(t.getSignaturesFiles().plus(project.files(resources))); + return null; + } + }); + }); + TaskProvider forbiddenApis = project.getTasks().named("forbiddenApis"); + forbiddenApis.configure(t -> t.setGroup("")); + return forbiddenApis; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenPatternsPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenPatternsPrecommitPlugin.java new file mode 100644 index 00000000000..bb174ae4f08 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ForbiddenPatternsPrecommitPlugin.java @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.TaskProvider; + +public class ForbiddenPatternsPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + return project.getTasks().register("forbiddenPatterns", ForbiddenPatternsTask.class); + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/JarHellPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/JarHellPrecommitPlugin.java new file mode 100644 index 00000000000..4f78f6eda23 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/JarHellPrecommitPlugin.java @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.info.BuildParams; +import org.elasticsearch.gradle.util.Util; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; + +public class JarHellPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + Configuration jarHellConfig = project.getConfigurations().create("jarHell"); + if (BuildParams.isInternal() && project.getPath().equals(":libs:elasticsearch-core") == false) { + // External plugins will depend on this already via transitive dependencies. + // Internal projects are not all plugins, so make sure the check is available + // we are not doing this for this project itself to avoid jar hell with itself + project.getDependencies().add("jarHell", project.project(":libs:elasticsearch-core")); + } + + TaskProvider jarHell = project.getTasks().register("jarHell", JarHellTask.class); + jarHell.configure(t -> { + SourceSet testSourceSet = Util.getJavaTestSourceSet(project).get(); + t.setClasspath(testSourceSet.getRuntimeClasspath().plus(jarHellConfig)); + t.dependsOn(jarHellConfig); + }); + + return jarHell; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/LoggerUsagePrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/LoggerUsagePrecommitPlugin.java new file mode 100644 index 00000000000..f2f3d62b170 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/LoggerUsagePrecommitPlugin.java @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.VersionProperties; +import org.elasticsearch.gradle.info.BuildParams; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.tasks.TaskProvider; + +public class LoggerUsagePrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + Object dependency = BuildParams.isInternal() + ? project.project(":test:logger-usage") + : ("org.elasticsearch.test:logger-usage:" + VersionProperties.getElasticsearch()); + + Configuration loggerUsageConfig = project.getConfigurations().create("loggerUsagePlugin"); + project.getDependencies().add("loggerUsagePlugin", dependency); + TaskProvider loggerUsage = project.getTasks().register("loggerUsageCheck", LoggerUsageTask.class); + loggerUsage.configure(t -> t.setClasspath(loggerUsageConfig)); + + return loggerUsage; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPlugin.java deleted file mode 100644 index c6ed039de90..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPlugin.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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. - */ - -package org.elasticsearch.gradle.precommit; - -import org.elasticsearch.gradle.util.Util; -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.publish.PublishingExtension; -import org.gradle.api.publish.maven.tasks.GenerateMavenPom; -import org.gradle.api.tasks.TaskProvider; - -/** - * Adds pom validation to every pom generation task. - */ -public class PomValidationPlugin implements Plugin { - - @Override - public void apply(Project project) { - project.getPluginManager().withPlugin("maven-publish", p -> { - PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); - publishing.getPublications().all(publication -> { - String publicationName = Util.capitalize(publication.getName()); - TaskProvider validateTask = project.getTasks() - .register("validate" + publicationName + "Pom", PomValidationTask.class); - validateTask.configure(task -> { - GenerateMavenPom generateMavenPom = project.getTasks() - .withType(GenerateMavenPom.class) - .getByName("generatePomFileFor" + publicationName + "Publication"); - task.dependsOn(generateMavenPom); - task.getPomFile().fileValue(generateMavenPom.getDestination()); - }); - project.getTasks().named("precommit").configure(precommit -> { precommit.dependsOn(validateTask); }); - }); - }); - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPrecommitPlugin.java new file mode 100644 index 00000000000..dd237f7e98e --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PomValidationPrecommitPlugin.java @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.util.Util; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.tasks.GenerateMavenPom; +import org.gradle.api.tasks.TaskProvider; + +/** + * Adds pom validation to every pom generation task. + */ +public class PomValidationPrecommitPlugin extends PrecommitPlugin { + + @Override + public TaskProvider createTask(Project project) { + TaskProvider validatePom = project.getTasks().register("validatePom"); + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + publishing.getPublications().all(publication -> { + String publicationName = Util.capitalize(publication.getName()); + TaskProvider validateTask = project.getTasks() + .register("validate" + publicationName + "Pom", PomValidationTask.class); + validatePom.configure(t -> t.dependsOn(validateTask)); + validateTask.configure(task -> { + GenerateMavenPom generateMavenPom = project.getTasks() + .withType(GenerateMavenPom.class) + .getByName("generatePomFileFor" + publicationName + "Publication"); + task.dependsOn(generateMavenPom); + task.getPomFile().fileValue(generateMavenPom.getDestination()); + }); + }); + + return validatePom; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PrecommitPlugin.java new file mode 100644 index 00000000000..3c6f9cb0883 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/PrecommitPlugin.java @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.util.GradleUtils; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.testing.Test; +import org.gradle.language.base.plugins.LifecycleBasePlugin; + +/** + * Base plugin for adding a precommit task. + */ +public abstract class PrecommitPlugin implements Plugin { + + public static final String PRECOMMIT_TASK_NAME = "precommit"; + + @Override + public final void apply(Project project) { + project.getPluginManager().apply(PrecommitTaskPlugin.class); + TaskProvider task = createTask(project); + TaskProvider precommit = project.getTasks().named(PRECOMMIT_TASK_NAME); + precommit.configure(t -> t.dependsOn(task)); + + project.getPluginManager() + .withPlugin( + "java", + p -> { + // We want to get any compilation error before running the pre-commit checks. + for (SourceSet sourceSet : GradleUtils.getJavaSourceSets(project)) { + task.configure(t -> t.shouldRunAfter(sourceSet.getClassesTaskName())); + } + } + ); + } + + public abstract TaskProvider createTask(Project project); + + static class PrecommitTaskPlugin implements Plugin { + + @Override + public void apply(Project project) { + TaskProvider precommit = project.getTasks().register(PRECOMMIT_TASK_NAME, t -> { + t.setGroup(JavaBasePlugin.VERIFICATION_GROUP); + t.setDescription("Runs all non-test checks"); + }); + + project.getPluginManager().withPlugin("java", p -> { + project.getTasks().named(LifecycleBasePlugin.CHECK_TASK_NAME).configure(t -> t.dependsOn(precommit)); + project.getTasks().withType(Test.class).configureEach(t -> t.mustRunAfter(precommit)); + }); + } + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsPrecommitPlugin.java new file mode 100644 index 00000000000..c73284effb4 --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsPrecommitPlugin.java @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.TaskProvider; + +public class TestingConventionsPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + TaskProvider testingConventions = project.getTasks() + .register("testingConventions", TestingConventionsTasks.class); + testingConventions.configure(t -> { + TestingConventionRule testsRule = t.getNaming().maybeCreate("Tests"); + testsRule.baseClass("org.apache.lucene.util.LuceneTestCase"); + TestingConventionRule itRule = t.getNaming().maybeCreate("IT"); + itRule.baseClass("org.elasticsearch.test.ESIntegTestCase"); + itRule.baseClass("org.elasticsearch.test.rest.ESRestTestCase"); + }); + return testingConventions; + } +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java index 3b06873f2fa..337ba7ac6bd 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java @@ -106,7 +106,7 @@ public class TestingConventionsTasks extends DefaultTask { return new File(getProject().getBuildDir(), "markers/" + getName()); } - public void naming(Closure action) { + public void naming(Closure action) { naming.configure(action); } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditPrecommitPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditPrecommitPlugin.java new file mode 100644 index 00000000000..5053f8b51fe --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditPrecommitPlugin.java @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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. + */ + +package org.elasticsearch.gradle.precommit; + +import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask; +import org.elasticsearch.gradle.info.BuildParams; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.TaskProvider; + +public class ThirdPartyAuditPrecommitPlugin extends PrecommitPlugin { + @Override + public TaskProvider createTask(Project project) { + project.getConfigurations().create("forbiddenApisCliJar"); + project.getDependencies().add("forbiddenApisCliJar", "de.thetaphi:forbiddenapis:2.7"); + + TaskProvider buildResources = project.getTasks() + .named("buildResources", ExportElasticsearchBuildResourcesTask.class); + + TaskProvider audit = project.getTasks().register("thirdPartyAudit", ThirdPartyAuditTask.class); + audit.configure(t -> { + t.dependsOn(buildResources); + t.setSignatureFile(buildResources.get().copy("forbidden/third-party-audit.txt")); + t.setJavaHome(BuildParams.getRuntimeJavaHome().toString()); + t.getTargetCompatibility().set(project.provider(BuildParams::getRuntimeJavaVersion)); + }); + return audit; + } +}