Skip to content

Commit 1283065

Browse files
committed
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.
1 parent eece3ee commit 1283065

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
@@ -23,7 +23,6 @@ import groovy.transform.CompileStatic
2323
import org.apache.commons.io.IOUtils
2424
import org.elasticsearch.gradle.info.BuildParams
2525
import org.elasticsearch.gradle.info.GlobalBuildInfoPlugin
26-
import org.elasticsearch.gradle.precommit.DependencyLicensesTask
2726
import org.elasticsearch.gradle.precommit.PrecommitTasks
2827
import org.elasticsearch.gradle.test.ErrorReportingTestListener
2928
import org.elasticsearch.gradle.testclusters.ElasticsearchCluster
@@ -51,10 +50,8 @@ import org.gradle.api.credentials.HttpHeaderCredentials
5150
import org.gradle.api.execution.TaskActionListener
5251
import org.gradle.api.plugins.ExtraPropertiesExtension
5352
import org.gradle.api.plugins.JavaPlugin
54-
import org.gradle.api.tasks.TaskProvider
5553
import org.gradle.api.tasks.testing.Test
5654
import org.gradle.authentication.http.HttpHeaderAuthentication
57-
import org.gradle.language.base.plugins.LifecycleBasePlugin
5855
import org.gradle.util.GradleVersion
5956

6057
import java.nio.charset.StandardCharsets
@@ -98,7 +95,7 @@ class BuildPlugin implements Plugin<Project> {
9895

9996
configureRepositories(project)
10097
project.extensions.getByType(ExtraPropertiesExtension).set('versions', VersionProperties.versions)
101-
configurePrecommit(project)
98+
PrecommitTasks.create(project, true)
10299
configureFips140(project)
103100
}
104101

@@ -277,18 +274,6 @@ class BuildPlugin implements Plugin<Project> {
277274
throw new GradleException(message)
278275
}
279276
}
280-
281-
private static configurePrecommit(Project project) {
282-
TaskProvider precommit = PrecommitTasks.create(project, true)
283-
project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).configure { it.dependsOn(precommit) }
284-
project.tasks.named(JavaPlugin.TEST_TASK_NAME).configure { it.mustRunAfter(precommit) }
285-
// only require dependency licenses for non-elasticsearch deps
286-
project.tasks.withType(DependencyLicensesTask).named('dependencyLicenses').configure {
287-
it.dependencies = project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).fileCollection { Dependency dependency ->
288-
dependency.group.startsWith('org.elasticsearch') == false
289-
} - project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME)
290-
}
291-
}
292277

293278
private static class TestFailureReportingPlugin implements Plugin<Project> {
294279
@Override
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)