Skip to content

Commit ce40b46

Browse files
beatbrotleonard84
andauthored
Extract more build logic into Convention Plugin (#2086)
Continuation of #2026 --------- Co-authored-by: Leonard Brünings <[email protected]>
1 parent 069ee92 commit ce40b46

File tree

9 files changed

+215
-63
lines changed

9 files changed

+215
-63
lines changed

build-logic/base/base.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ dependencies {
1919
testing {
2020
suites {
2121
test {
22-
useSpock('2.3-groovy-3.0')
22+
useSpock('2.4-M5-groovy-3.0')
2323
}
2424
}
2525
}

build-logic/base/src/main/groovy/org/spockframework/gradle/AsciiDocLinkVerifier.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
115
package org.spockframework.gradle
216

317
import groovy.transform.CompileDynamic

build-logic/base/src/main/groovy/org/spockframework/gradle/JacocoJavaagentProvider.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
115
package org.spockframework.gradle
216

317
import groovy.transform.CompileStatic

build-logic/base/src/main/groovy/org/spockframework/gradle/SpockBasePlugin.groovy

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,42 @@ package org.spockframework.gradle
1919
import groovy.transform.CompileStatic
2020
import org.gradle.api.Plugin
2121
import org.gradle.api.Project
22+
import org.gradle.api.artifacts.VersionCatalogsExtension
23+
import org.gradle.api.plugins.ExtraPropertiesExtension
2224
import org.gradle.api.plugins.JavaPlugin
25+
import org.gradle.api.tasks.SourceSetContainer
26+
import org.gradle.api.tasks.bundling.Jar
2327
import org.gradle.api.tasks.compile.GroovyCompile
2428
import org.gradle.api.tasks.compile.JavaCompile
29+
import org.gradle.api.tasks.diagnostics.DependencyInsightReportTask
2530
import org.gradle.api.tasks.testing.Test
2631
import org.gradle.jvm.toolchain.JavaLanguageVersion
2732
import org.gradle.jvm.toolchain.JavaToolchainService
33+
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
2834
import org.jetbrains.annotations.VisibleForTesting
2935

36+
import java.time.Duration
37+
3038
@CompileStatic
3139
class SpockBasePlugin implements Plugin<Project> {
3240

3341
@VisibleForTesting
3442
public static final JavaLanguageVersion COMPILER_VERSION = JavaLanguageVersion.of(8)
3543

3644
void apply(Project project) {
45+
applyPlugins(project)
3746
compileTasks(project)
47+
jarTasks(project)
3848
testTasks(project)
49+
jacoco(project)
50+
dependencyInsight(project)
51+
}
52+
53+
static void applyPlugins(Project project) {
54+
def plugins = project.plugins
55+
plugins.apply("java-library")
56+
plugins.apply("groovy")
57+
plugins.apply("jacoco")
3958
}
4059

4160
private static void compileTasks(Project project) {
@@ -55,13 +74,63 @@ class SpockBasePlugin implements Plugin<Project> {
5574
}
5675
}
5776

77+
private static void jarTasks(Project project) {
78+
project.tasks.withType(Jar).configureEach { jar ->
79+
/*
80+
* Ensure the jar can be built in a reproducible manner, This shall prevent build cache misses, when different variants are tested.
81+
*/
82+
jar.preserveFileTimestamps = false
83+
jar.reproducibleFileOrder = true
84+
}
85+
86+
def sourceSets = project.extensions.getByType(SourceSetContainer)
87+
project.tasks.register("sourcesJar", Jar) {
88+
it.archiveClassifier.set("sources")
89+
it.from(sourceSets.named("main").map { it.allSource })
90+
}
91+
92+
project.tasks.register("javadocJar", Jar) {
93+
it.archiveClassifier.set("javadoc")
94+
it.from(project.tasks.named("javadoc"))
95+
}
96+
}
97+
5898
private static void testTasks(Project project) {
5999
project.tasks.withType(Test).configureEach { task ->
100+
task.useJUnitPlatform()
60101
def taskName = task.name.capitalize()
102+
def variant = project.rootProject.extensions.getByType(ExtraPropertiesExtension)
103+
.get("variant")
104+
105+
def junitXml = task.reports.junitXml
106+
junitXml.outputLocation.set(project.file("${junitXml.outputLocation.get()}/$taskName-$variant"))
107+
def html = task.reports.html
108+
html.outputLocation.set(project.file("${html.outputLocation.get()}/$taskName-$variant"))
109+
110+
// As a generous general timeout, instead of the 6h of GHA.
111+
// But only on CI or longer needing debug sessions get killed by the timeout.
112+
boolean isCiServer = System.getenv("CI") || System.getenv("GITHUB_ACTIONS")
113+
if (isCiServer) {
114+
task.timeout.set(Duration.ofMinutes(15))
115+
}
116+
61117
File configFile = project.file("Spock${taskName}Config.groovy")
62118
if (configFile.exists()) {
63119
task.jvmArgumentProviders.add(new SpockConfigArgumentProvider(configFile))
64120
}
65121
}
66122
}
123+
124+
private static void jacoco(Project project) {
125+
// For tests, we have to handle the case where version catalogs are not present
126+
127+
def jacocoVersion = project.rootProject.extensions.findByType(VersionCatalogsExtension).find("libs")
128+
.flatMap { it.findVersion("jacoco") }
129+
.orElseThrow { new IllegalStateException("Jacoco version not found") }
130+
project.extensions.getByType(JacocoPluginExtension).toolVersion = jacocoVersion.requiredVersion
131+
}
132+
133+
private static void dependencyInsight(Project project) {
134+
project.tasks.register("allDependencyInsight", DependencyInsightReportTask)
135+
}
67136
}

build-logic/base/src/main/groovy/org/spockframework/gradle/SpockConfigArgumentProvider.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
115
package org.spockframework.gradle
216

317
import groovy.transform.CompileStatic

build-logic/base/src/test/groovy/org/spockframework/gradle/AsciiDocLinkVerifierTest.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
115
package org.spockframework.gradle
216

317

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,111 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
//file:noinspection ConfigurationAvoidance
116
package org.spockframework.gradle
217

318
import org.gradle.api.Project
19+
import org.gradle.api.artifacts.VersionCatalog
20+
import org.gradle.api.artifacts.VersionCatalogsExtension
21+
import org.gradle.api.artifacts.VersionConstraint
22+
import org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestFramework
423
import org.gradle.api.plugins.JavaPlugin
24+
import org.gradle.api.tasks.compile.GroovyCompile
525
import org.gradle.api.tasks.compile.JavaCompile
26+
import org.gradle.api.tasks.testing.Test
27+
import org.gradle.jvm.tasks.Jar
628
import org.gradle.testfixtures.ProjectBuilder
729
import spock.lang.Specification
30+
import spock.lang.TempDir
31+
import spock.util.io.FileSystemFixture
832

933
class SpockBasePluginSpec extends Specification {
34+
@TempDir
35+
FileSystemFixture projectDir
1036

1137
def 'Compile settings are configured'() {
1238
setup:
1339
def project = createProject()
1440

15-
when:
41+
expect:
1642
def compileJavaTasks = project.tasks.withType(JavaCompile)
17-
def compileJava = project.tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME) as JavaCompile
43+
verifyEach(compileJavaTasks) { options.encoding == "UTF-8" }
1844

19-
then:
20-
compileJavaTasks.every { it.options.encoding == "UTF-8" }
45+
and:
46+
def compileJava = project.tasks.getByName(JavaPlugin.COMPILE_JAVA_TASK_NAME) as JavaCompile
2147
compileJava.javaCompiler.get().metadata.languageVersion == SpockBasePlugin.COMPILER_VERSION
48+
49+
and:
50+
def compileGroovyTasks = project.tasks.withType(GroovyCompile)
51+
verifyEach(compileGroovyTasks) { options.encoding == "UTF-8" }
2252
}
2353

24-
private static Project createProject() {
25-
def result = ProjectBuilder.builder()
54+
def "Jar settings are configured"() {
55+
setup:
56+
def project = createProject()
57+
58+
expect:
59+
def jarTasks = project.tasks.withType(Jar)
60+
jarTasks.size() == 3
61+
verifyEach(jarTasks) { reproducibleFileOrder }
62+
verifyEach(jarTasks) { !preserveFileTimestamps }
63+
64+
and:
65+
project.tasks.named("sourcesJar", Jar)
66+
project.tasks.named("javadocJar", Jar)
67+
}
68+
69+
@SuppressWarnings('GroovyInArgumentCheck')
70+
def "test settings are configured"() {
71+
setup:
72+
def spockConfig = projectDir.file("SpockTestConfig.groovy")
73+
spockConfig.text = '// Spock test config stub'
74+
75+
and:
76+
def project = createProject()
77+
78+
expect:
79+
def testTask = project.tasks.named('test',Test).get()
80+
SpockConfigArgumentProvider in testTask.jvmArgumentProviders*.getClass()
81+
82+
and:
83+
testTask.reports.junitXml.outputLocation.get().asFile == project.file("build/test-results/test/Test-4.0")
84+
testTask.reports.html.outputLocation.get().asFile == project.file("build/reports/tests/test/Test-4.0")
85+
86+
and:
87+
testTask.testFramework.getClass() == JUnitPlatformTestFramework
88+
}
89+
90+
private Project createProject() {
91+
def project = ProjectBuilder.builder()
92+
.withName("spock-foo")
93+
.withProjectDir(projectDir.currentPath.toFile())
2694
.build()
27-
result.plugins.apply("java-library")
28-
result.plugins.apply("groovy")
29-
result.plugins.apply(SpockBasePlugin)
30-
return result
95+
96+
97+
project.extensions.tap {
98+
getExtraProperties().set("variant", "4.0")
99+
add('versionCatalogs', Stub(VersionCatalogsExtension) {
100+
find('libs') >> Optional.of(Stub(VersionCatalog) {
101+
findVersion('jacoco') >> Optional.of(Stub(VersionConstraint) {
102+
requiredVersion >> '0.8.12'
103+
})
104+
})
105+
})
106+
}
107+
108+
project.plugins.apply(SpockBasePlugin)
109+
return project
31110
}
32111
}

build.gradle

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ allprojects {
8585
group = "org.spockframework"
8686
version = fullVersion
8787

88-
apply from: script("common")
89-
9088
// ignore mutable data that is irrelevant for compilation output
9189
normalization {
9290
runtimeClasspath {
@@ -99,13 +97,8 @@ allprojects {
9997

10098
apply from: script("ide")
10199

102-
boolean isCiServer = System.env["CI"] || System.env["GITHUB_ACTIONS"]
103100
subprojects {
104101
if (it.name == "spock-bom") return
105-
106-
apply plugin: "java-library"
107-
apply plugin: "groovy"
108-
apply plugin: "jacoco"
109102
apply plugin: "org.spockframework.base"
110103

111104
java {
@@ -168,48 +161,6 @@ subprojects {
168161

169162
configureJavadoc(tasks.named("javadoc"))
170163
configureGroovydoc(tasks.named("groovydoc"))
171-
172-
tasks.register("sourcesJar", Jar) {
173-
archiveClassifier = "sources"
174-
from sourceSets.main.allSource
175-
}
176-
177-
tasks.register("javadocJar", Jar) {
178-
archiveClassifier = "javadoc"
179-
from javadoc
180-
}
181-
182-
tasks.withType(Jar).configureEach {
183-
/*
184-
* Ensure the jar can be built in a reproducible manner, This shall prevent build cache misses, when different variants are tested.
185-
*/
186-
preserveFileTimestamps = false
187-
reproducibleFileOrder = true
188-
}
189-
190-
tasks.withType(Test).configureEach {
191-
useJUnitPlatform()
192-
def taskName = name
193-
reports {
194-
junitXml {
195-
outputLocation = file("${outputLocation.get()}/$taskName-$variant")
196-
}
197-
html {
198-
outputLocation = file("${outputLocation.get()}/$taskName-$variant")
199-
}
200-
}
201-
// As a generous general timeout, instead of the 6h of GHA.
202-
// But only on CI or longer needing debug sessions get killed by the timeout.
203-
if (isCiServer) {
204-
timeout = Duration.ofMinutes(15)
205-
}
206-
}
207-
208-
tasks.register("allDependencyInsight", DependencyInsightReportTask) {}
209-
210-
jacoco {
211-
toolVersion = libs.versions.jacoco.get()
212-
}
213164
}
214165

215166
tasks.register("collectTestXml") {

gradle/common.gradle

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)