Skip to content

Commit c98d548

Browse files
authored
Add individual precommit task plugins (#56926)
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.
1 parent eb9de19 commit c98d548

19 files changed

+696
-305
lines changed

buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ package org.elasticsearch.gradle
2222
import groovy.transform.CompileStatic
2323
import org.apache.commons.io.IOUtils
2424
import org.elasticsearch.gradle.info.GlobalBuildInfoPlugin
25-
import org.elasticsearch.gradle.precommit.DependencyLicensesTask
2625
import org.elasticsearch.gradle.precommit.PrecommitTasks
2726
import org.elasticsearch.gradle.test.ErrorReportingTestListener
2827
import org.elasticsearch.gradle.testclusters.ElasticsearchCluster
@@ -48,10 +47,8 @@ import org.gradle.api.credentials.HttpHeaderCredentials
4847
import org.gradle.api.execution.TaskActionListener
4948
import org.gradle.api.plugins.ExtraPropertiesExtension
5049
import org.gradle.api.plugins.JavaPlugin
51-
import org.gradle.api.tasks.TaskProvider
5250
import org.gradle.api.tasks.testing.Test
5351
import org.gradle.authentication.http.HttpHeaderAuthentication
54-
import org.gradle.language.base.plugins.LifecycleBasePlugin
5552
import org.gradle.util.GradleVersion
5653

5754
import java.nio.charset.StandardCharsets
@@ -95,7 +92,7 @@ class BuildPlugin implements Plugin<Project> {
9592

9693
configureRepositories(project)
9794
project.extensions.getByType(ExtraPropertiesExtension).set('versions', VersionProperties.versions)
98-
configurePrecommit(project)
95+
PrecommitTasks.create(project, true)
9996
configureFips140(project)
10097
}
10198

@@ -259,18 +256,6 @@ class BuildPlugin implements Plugin<Project> {
259256
}
260257
}
261258

262-
private static configurePrecommit(Project project) {
263-
TaskProvider precommit = PrecommitTasks.create(project, true)
264-
project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).configure { it.dependsOn(precommit) }
265-
project.tasks.named(JavaPlugin.TEST_TASK_NAME).configure { it.mustRunAfter(precommit) }
266-
// only require dependency licenses for non-elasticsearch deps
267-
project.tasks.withType(DependencyLicensesTask).named('dependencyLicenses').configure {
268-
it.dependencies = project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).fileCollection { Dependency dependency ->
269-
dependency.group.startsWith('org.elasticsearch') == false
270-
} - project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
271-
}
272-
}
273-
274259
private static class TestFailureReportingPlugin implements Plugin<Project> {
275260
@Override
276261
void apply(Project project) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.gradle.precommit
21+
22+
import org.gradle.api.Project
23+
import org.gradle.api.Task
24+
import org.gradle.api.tasks.TaskProvider
25+
26+
class LicenseHeadersPrecommitPlugin extends PrecommitPlugin {
27+
@Override
28+
TaskProvider<? extends Task> createTask(Project project) {
29+
return project.getTasks().register("licenseHeaders", LicenseHeadersTask.class);
30+
}
31+
}

buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy

Lines changed: 12 additions & 233 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,8 @@
1818
*/
1919
package org.elasticsearch.gradle.precommit
2020

21-
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
22-
import de.thetaphi.forbiddenapis.gradle.ForbiddenApisPlugin
23-
import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask
24-
import org.elasticsearch.gradle.VersionProperties
25-
import org.elasticsearch.gradle.info.BuildParams
26-
import org.elasticsearch.gradle.util.Util
27-
import org.gradle.api.JavaVersion
21+
2822
import org.gradle.api.Project
29-
import org.gradle.api.artifacts.Configuration
30-
import org.gradle.api.file.FileCollection
31-
import org.gradle.api.plugins.JavaBasePlugin
32-
import org.gradle.api.plugins.quality.Checkstyle
33-
import org.gradle.api.tasks.SourceSet
34-
import org.gradle.api.tasks.TaskProvider
3523

3624
/**
3725
* Validation tasks which should be run before committing. These run before tests.
@@ -40,42 +28,21 @@ class PrecommitTasks {
4028

4129
/** Adds a precommit task, which depends on non-test verification tasks. */
4230

43-
public static TaskProvider create(Project project, boolean includeDependencyLicenses) {
44-
project.configurations.create("forbiddenApisCliJar")
45-
project.dependencies {
46-
forbiddenApisCliJar('de.thetaphi:forbiddenapis:2.7')
47-
}
48-
49-
Configuration jarHellConfig = project.configurations.create("jarHell")
50-
if (BuildParams.internal && project.path.equals(":libs:elasticsearch-core") == false) {
51-
// External plugins will depend on this already via transitive dependencies.
52-
// Internal projects are not all plugins, so make sure the check is available
53-
// we are not doing this for this project itself to avoid jar hell with itself
54-
project.dependencies {
55-
jarHell project.project(":libs:elasticsearch-core")
56-
}
57-
}
31+
public static void create(Project project, boolean includeDependencyLicenses) {
5832

59-
List<TaskProvider> precommitTasks = [
60-
configureCheckstyle(project),
61-
configureForbiddenApisCli(project),
62-
project.tasks.register('forbiddenPatterns', ForbiddenPatternsTask),
63-
project.tasks.register('licenseHeaders', LicenseHeadersTask),
64-
project.tasks.register('filepermissions', FilePermissionsTask),
65-
configureJarHell(project, jarHellConfig),
66-
configureThirdPartyAudit(project),
67-
configureTestingConventions(project)
68-
]
33+
project.pluginManager.apply(CheckstylePrecommitPlugin)
34+
project.pluginManager.apply(ForbiddenApisPrecommitPlugin)
35+
project.pluginManager.apply(JarHellPrecommitPlugin)
36+
project.pluginManager.apply(ForbiddenPatternsPrecommitPlugin)
37+
project.pluginManager.apply(LicenseHeadersPrecommitPlugin)
38+
project.pluginManager.apply(FilePermissionsPrecommitPlugin)
39+
project.pluginManager.apply(ThirdPartyAuditPrecommitPlugin)
40+
project.pluginManager.apply(TestingConventionsPrecommitPlugin)
6941

7042
// tasks with just tests don't need dependency licenses, so this flag makes adding
7143
// the task optional
7244
if (includeDependencyLicenses) {
73-
TaskProvider<DependencyLicensesTask> dependencyLicenses = project.tasks.register('dependencyLicenses', DependencyLicensesTask)
74-
precommitTasks.add(dependencyLicenses)
75-
// we also create the updateShas helper task that is associated with dependencyLicenses
76-
project.tasks.register('updateShas', UpdateShasTask) {
77-
it.parentTask = dependencyLicenses
78-
}
45+
project.pluginManager.apply(DependencyLicensesPrecommitPlugin)
7946
}
8047
if (project.path != ':build-tools') {
8148
/*
@@ -88,195 +55,7 @@ class PrecommitTasks {
8855
* use the NamingConventionsCheck we break the circular dependency
8956
* here.
9057
*/
91-
precommitTasks.add(configureLoggerUsage(project))
92-
}
93-
94-
// We want to get any compilation error before running the pre-commit checks.
95-
project.sourceSets.all { sourceSet ->
96-
precommitTasks.each { provider ->
97-
provider.configure {
98-
shouldRunAfter(sourceSet.getClassesTaskName())
99-
}
100-
}
101-
}
102-
103-
TaskProvider precommit = project.tasks.register('precommit') {
104-
group = JavaBasePlugin.VERIFICATION_GROUP
105-
description = 'Runs all non-test checks.'
106-
dependsOn = precommitTasks
107-
}
108-
109-
// not all jar projects produce a pom (we don't ship all jars), so a pom validation
110-
// task is only added on some projects, and thus we can't always have a task
111-
// here to add to precommit tasks explicitly. Instead, we apply our internal
112-
// pom validation plugin after the precommit task is created and let the
113-
// plugin add the task if necessary
114-
project.plugins.apply(PomValidationPlugin)
115-
116-
return precommit
117-
}
118-
119-
static TaskProvider configureTestingConventions(Project project) {
120-
return project.getTasks().register("testingConventions", TestingConventionsTasks) {
121-
naming {
122-
Tests {
123-
baseClass "org.apache.lucene.util.LuceneTestCase"
124-
}
125-
IT {
126-
baseClass "org.elasticsearch.test.ESIntegTestCase"
127-
baseClass 'org.elasticsearch.test.rest.ESRestTestCase'
128-
}
129-
}
130-
}
131-
}
132-
133-
private static TaskProvider configureJarHell(Project project, Configuration jarHellConfig) {
134-
return project.tasks.register('jarHell', JarHellTask) { task ->
135-
task.classpath = project.sourceSets.test.runtimeClasspath + jarHellConfig
136-
task.dependsOn(jarHellConfig)
137-
}
138-
}
139-
140-
private static TaskProvider configureThirdPartyAudit(Project project) {
141-
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')
142-
return project.tasks.register('thirdPartyAudit', ThirdPartyAuditTask) { task ->
143-
task.dependsOn(buildResources)
144-
task.signatureFile = buildResources.copy("forbidden/third-party-audit.txt")
145-
task.javaHome = BuildParams.runtimeJavaHome
146-
task.targetCompatibility.set(project.provider({ BuildParams.runtimeJavaVersion }))
147-
}
148-
}
149-
150-
private static TaskProvider configureForbiddenApisCli(Project project) {
151-
project.pluginManager.apply(ForbiddenApisPlugin)
152-
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')
153-
project.tasks.withType(CheckForbiddenApis).configureEach {
154-
dependsOn(buildResources)
155-
156-
assert name.startsWith(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME)
157-
String sourceSetName
158-
if (ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.equals(name)) {
159-
sourceSetName = "main"
160-
} else {
161-
//parse out the sourceSetName
162-
char[] chars = name.substring(ForbiddenApisPlugin.FORBIDDEN_APIS_TASK_NAME.length()).toCharArray()
163-
chars[0] = Character.toLowerCase(chars[0])
164-
sourceSetName = new String(chars)
165-
}
166-
167-
SourceSet sourceSet = project.sourceSets.getByName(sourceSetName)
168-
classpath = project.files { sourceSet.runtimeClasspath.plus(sourceSet.compileClasspath) }
169-
170-
targetCompatibility = BuildParams.runtimeJavaVersion.majorVersion
171-
if (BuildParams.runtimeJavaVersion > JavaVersion.VERSION_14) {
172-
// TODO: forbidden apis does not yet support java 15, rethink using runtime version
173-
targetCompatibility = JavaVersion.VERSION_14.majorVersion
174-
}
175-
bundledSignatures = [
176-
"jdk-unsafe", "jdk-deprecated", "jdk-non-portable", "jdk-system-out"
177-
]
178-
signaturesFiles = project.files(
179-
buildResources.copy("forbidden/jdk-signatures.txt"),
180-
buildResources.copy("forbidden/es-all-signatures.txt")
181-
)
182-
suppressAnnotations = ['**.SuppressForbidden']
183-
if (name.endsWith('Test')) {
184-
signaturesFiles += project.files(
185-
buildResources.copy("forbidden/es-test-signatures.txt"),
186-
buildResources.copy("forbidden/http-signatures.txt")
187-
)
188-
} else {
189-
signaturesFiles += project.files(buildResources.copy("forbidden/es-server-signatures.txt"))
190-
}
191-
ext.replaceSignatureFiles = { String... names ->
192-
signaturesFiles = project.files(
193-
names.collect { buildResources.copy("forbidden/${it}.txt") }
194-
)
195-
}
196-
ext.addSignatureFiles = { String... names ->
197-
signaturesFiles += project.files(
198-
names.collect { buildResources.copy("forbidden/${it}.txt") }
199-
)
200-
}
201-
}
202-
TaskProvider forbiddenApis = project.tasks.named("forbiddenApis")
203-
forbiddenApis.configure {
204-
group = ""
205-
}
206-
return forbiddenApis
207-
}
208-
209-
private static TaskProvider configureCheckstyle(Project project) {
210-
// Always copy the checkstyle configuration files to 'buildDir/checkstyle' since the resources could be located in a jar
211-
// file. If the resources are located in a jar, Gradle will fail when it tries to turn the URL into a file
212-
URL checkstyleConfUrl = PrecommitTasks.getResource("/checkstyle.xml")
213-
URL checkstyleSuppressionsUrl = PrecommitTasks.getResource("/checkstyle_suppressions.xml")
214-
File checkstyleDir = new File(project.buildDir, "checkstyle")
215-
File checkstyleSuppressions = new File(checkstyleDir, "checkstyle_suppressions.xml")
216-
File checkstyleConf = new File(checkstyleDir, "checkstyle.xml");
217-
TaskProvider copyCheckstyleConf = project.tasks.register("copyCheckstyleConf")
218-
219-
// configure inputs and outputs so up to date works properly
220-
copyCheckstyleConf.configure {
221-
outputs.files(checkstyleSuppressions, checkstyleConf)
222-
}
223-
if ("jar".equals(checkstyleConfUrl.getProtocol())) {
224-
JarURLConnection jarURLConnection = (JarURLConnection) checkstyleConfUrl.openConnection()
225-
copyCheckstyleConf.configure {
226-
inputs.file(jarURLConnection.getJarFileURL())
227-
}
228-
} else if ("file".equals(checkstyleConfUrl.getProtocol())) {
229-
copyCheckstyleConf.configure {
230-
inputs.files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile())
231-
}
232-
}
233-
234-
copyCheckstyleConf.configure {
235-
doLast {
236-
checkstyleDir.mkdirs()
237-
// withStream will close the output stream and IOGroovyMethods#getBytes reads the InputStream fully and closes it
238-
new FileOutputStream(checkstyleConf).withStream {
239-
it.write(checkstyleConfUrl.openStream().getBytes())
240-
}
241-
new FileOutputStream(checkstyleSuppressions).withStream {
242-
it.write(checkstyleSuppressionsUrl.openStream().getBytes())
243-
}
244-
}
245-
}
246-
247-
TaskProvider checkstyleTask = project.tasks.register('checkstyle') {
248-
dependsOn project.tasks.withType(Checkstyle)
249-
}
250-
// Apply the checkstyle plugin to create `checkstyleMain` and `checkstyleTest`. It only
251-
// creates them if there is main or test code to check and it makes `check` depend
252-
// on them. We also want `precommit` to depend on `checkstyle`.
253-
project.pluginManager.apply('checkstyle')
254-
project.checkstyle {
255-
configDir = checkstyleDir
256-
}
257-
project.dependencies {
258-
checkstyle "com.puppycrawl.tools:checkstyle:${VersionProperties.versions.checkstyle}"
259-
checkstyle project.files(Util.buildSrcCodeSource)
260-
}
261-
262-
project.tasks.withType(Checkstyle).configureEach { task ->
263-
task.dependsOn(copyCheckstyleConf)
264-
task.reports {
265-
html.enabled false
266-
}
267-
}
268-
269-
return checkstyleTask
270-
}
271-
272-
private static TaskProvider configureLoggerUsage(Project project) {
273-
Object dependency = BuildParams.internal ? project.project(':test:logger-usage') :
274-
"org.elasticsearch.test:logger-usage:${VersionProperties.elasticsearch}"
275-
276-
project.configurations.create('loggerUsagePlugin')
277-
project.dependencies.add('loggerUsagePlugin', dependency)
278-
return project.tasks.register('loggerUsageCheck', LoggerUsageTask) {
279-
classpath = project.configurations.loggerUsagePlugin
58+
project.pluginManager.apply(LoggerUsagePrecommitPlugin)
28059
}
28160
}
28261
}

buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,5 @@ class StandaloneRestTestPlugin implements Plugin<Project> {
9595
idea.module.scopes.put('TEST', [plus: [project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME)]] as Map<String, Collection<Configuration>>)
9696

9797
PrecommitTasks.create(project, false)
98-
project.tasks.named('check').configure { it.dependsOn(project.tasks.named('precommit')) }
9998
}
10099
}

buildSrc/src/main/java/org/elasticsearch/gradle/PublishPlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import groovy.util.Node;
2525
import groovy.util.NodeList;
2626
import org.elasticsearch.gradle.info.BuildParams;
27+
import org.elasticsearch.gradle.precommit.PomValidationPrecommitPlugin;
2728
import org.elasticsearch.gradle.util.Util;
2829
import org.gradle.api.Plugin;
2930
import org.gradle.api.Project;
@@ -50,6 +51,7 @@ public class PublishPlugin implements Plugin<Project> {
5051
@Override
5152
public void apply(Project project) {
5253
project.getPluginManager().apply("nebula.maven-base-publish");
54+
project.getPluginManager().apply(PomValidationPrecommitPlugin.class);
5355

5456
configureJavadocJar(project);
5557
configureSourcesJar(project);

0 commit comments

Comments
 (0)