jdaugherty commented on code in PR #11:
URL: https://github.com/apache/grails-micronaut/pull/11#discussion_r4230978194
##########
build-logic/plugins/src/test/groovy/org/apache/grails/buildsrc/CompilePluginSpec.groovy:
##########
@@ -116,6 +116,159 @@ class CompilePluginSpec extends Specification {
result.output.contains('TEST_INDY=true')
}
+ def "compiler configuration stamps the published project version"() {
+ given:
+ usePublishedBuild('projectVersion')
+
+ when:
+ def result = GradleRunner.create()
+ .withProjectDir(testProjectDir.toFile())
+ .withArguments(['grailsCompilerConfigCompileGroovy',
'printManifestVersion', '-PprojectVersion=8.0.0-SNAPSHOT', '--stacktrace'])
+ .withPluginClasspath()
+ .build()
+
+ then:
+ result.task(':grailsCompilerConfigCompileGroovy').outcome ==
TaskOutcome.SUCCESS
+ def script =
testProjectDir.resolve('build/groovy-compiler/compileGroovy-config.groovy').toFile().text
+ script.contains("putNodeMetaData('projectVersion', '8.0.0-SNAPSHOT')")
+ script.contains("putNodeMetaData('projectName', 'grails-micronaut')")
+ result.output.contains('IMPL_VERSION=8.0.0-SNAPSHOT')
+ !script.contains('7.9.9')
+ }
+
+ def "release version configures and stamps project.version"() {
+ given:
+ usePublishedBuild('projectVersion')
+
+ when:
+ def result = GradleRunner.create()
+ .withProjectDir(testProjectDir.toFile())
+ .withArguments(['grailsCompilerConfigCompileGroovy',
'printManifestVersion', '-PprojectVersion=8.0.0', '--stacktrace'])
+ .withPluginClasspath()
+ .build()
+
+ then:
+ result.task(':grailsCompilerConfigCompileGroovy').outcome ==
TaskOutcome.SUCCESS
+ def script =
testProjectDir.resolve('build/groovy-compiler/compileGroovy-config.groovy').toFile().text
+ script.contains("putNodeMetaData('projectVersion', '8.0.0')")
+ !script.contains('SNAPSHOT')
+ !script.contains('7.9.9')
+ script.contains("putNodeMetaData('projectName', 'grails-micronaut')")
+ result.output.contains('IMPL_VERSION=8.0.0')
+ !result.output.contains('IMPL_VERSION=8.0.0-SNAPSHOT')
+ !result.output.contains('IMPL_VERSION=7.9.9')
+ }
+
+ def "compiler version stamp is limited to published projects"() {
+ given:
+ testProjectDir.resolve('build.gradle').toFile().text = '''
+ plugins {
+ id 'groovy'
+ id 'org.apache.grails.buildsrc.compile'
+ }
+
+ version = '0.1'
+
+ ext {
+ javaVersion = 21
+ grailsVersion = '8.0.0'
+ formattedBuildDate = '2026-01-01'
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ tasks.register('printCompilerScript') {
+ def compileTask = tasks.named('compileGroovy',
org.gradle.api.tasks.compile.GroovyCompile)
+ doLast {
+ println
"HAS_WRITER=${tasks.names.contains('grailsCompilerConfigCompileGroovy')}"
+ println
"SCRIPT=${compileTask.get().groovyOptions.configurationScript}"
+ }
+ }
+ '''
+
+ when:
+ def result = GradleRunner.create()
+ .withProjectDir(testProjectDir.toFile())
+ .withArguments(['printCompilerScript', '--stacktrace'])
+ .withPluginClasspath()
+ .build()
+
+ then:
+ result.task(':printCompilerScript').outcome == TaskOutcome.SUCCESS
+ result.output.contains('HAS_WRITER=false')
+ result.output.contains('groovy-compile-configscript.groovy')
+ !result.output.contains('IMPL_VERSION=')
Review Comment:
Nit: this assertion can't fail. This build doesn't register
`printManifestVersion`, so nothing prints `IMPL_VERSION=`. The manifest reads
`project.version` whether or not the project is published, so I'd drop this
line rather than add the task.
##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +170,57 @@ class CompilePlugin implements Plugin<Project> {
}
}
+ /**
+ * Stamps {@code project.version} onto every source set's Groovy compile.
+ *
+ * <p>The writer is registered from the source-set container. Registering
a task while
+ * iterating {@code tasks.withType(GroovyCompile)} throws {@code
ConcurrentModificationException}
+ * once {@code projectVersion} is not a snapshot. Wiring
+ * {@code configurationScriptFile} to the writer's output makes the
compile task depend on
+ * the writer, including after {@code clean} deletes {@code build/}.</p>
+ */
+ private static void configurePublishedVersionScript(Project project) {
+ SourceSetContainer sourceSets =
project.extensions.getByType(SourceSetContainer)
+ sourceSets.configureEach { SourceSet sourceSet ->
+ registerPublishedVersionScript(project,
sourceSet.getCompileTaskName('groovy'))
+ }
+
+ project.tasks.withType(GroovyCompile).configureEach { GroovyCompile
compile ->
+ TaskProvider<PublishedVersionCompilerScriptTask> writer =
project.tasks.named(
+ publishedVersionScriptTaskName(compile.name),
+ PublishedVersionCompilerScriptTask
+ )
+ compile.groovyOptions.configurationScriptFile.set(writer.flatMap {
PublishedVersionCompilerScriptTask task ->
+ task.outputFile
+ })
+ }
Review Comment:
Non-blocking: this wiring assumes every `GroovyCompile` comes from a source
set. In a project that applies the publish plugin, any other `GroovyCompile`
now fails to configure. For example, adding this to
`grails-micronaut/build.gradle`:
```groovy
tasks.register('compileExtraGroovy', GroovyCompile) {
source = files()
classpath = files()
destinationDirectory = layout.buildDirectory.dir('extra')
}
```
fails with:
```
> Could not create task ':grails-micronaut:compileExtraGroovy'.
> Task with name 'grailsCompilerConfigCompileExtraGroovy' not found in
project ':grails-micronaut'.
```
Nothing registers a task like that today, so this can't fail yet. Wiring
each source set's own compile task avoids the lookup and stays lazy
(`register`, `named(...).configure`, `flatMap`). With the change below,
`CompilePluginSpec` still passes, the extra task keeps the shared script, and
`-PprojectVersion=8.0.0` still stamps `version='8.0.0'` into
`grails-plugin.xml`. Adding a `GroovyCompile` like the one above to the
published fixture would cover the case.
```suggestion
sourceSets.configureEach { SourceSet sourceSet ->
String compileTaskName = sourceSet.getCompileTaskName('groovy')
TaskProvider<PublishedVersionCompilerScriptTask> writer =
registerPublishedVersionScript(project, compileTaskName)
project.tasks.named(compileTaskName, GroovyCompile).configure {
GroovyCompile compile ->
compile.groovyOptions.configurationScriptFile.set(writer.flatMap {
PublishedVersionCompilerScriptTask task ->
task.outputFile
})
}
}
```
Separately, the `tasks.names.contains(writerName)` guard in
`registerPublishedVersionScript` can't be reached. `configureEach` fires once
per source set, and source set names are unique.
##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -87,7 +95,7 @@ class CompilePlugin implements Plugin<Project> {
jar.manifest.attributes(
'Implementation-Title': 'Apache Grails',
- 'Implementation-Version': lookupPropertyByType(project,
'grailsVersion', String),
+ 'Implementation-Version': project.version.toString(),
Review Comment:
`project.version.toString()` runs when the `Jar` task is realized, not when
the jar is written. That works today only because nothing realizes a jar before
the build script assigns `version`. The compiler stamp reads the same value
through `project.provider`, so if anything realizes the jar early, the two
disagree. Adding `tasks.named('jar').get()` above `version = projectVersion` in
`grails-micronaut/build.gradle` and building with `-PprojectVersion=8.0.0`
writes `Implementation-Version: unspecified`, while
`compileGroovy-config.groovy` stamps `8.0.0`.
A provider defers the read until the manifest is written, the same way the
compiler stamp does:
```suggestion
'Implementation-Version': project.provider {
project.version.toString() },
```
The spec's `printManifestVersion` reads the in-memory attribute, so with
this change it prints `provider(?)` and both stamp specs fail. Reading
`Implementation-Version` from `META-INF/MANIFEST.MF` in the built jar checks
what actually ships. A case that realizes `jar` before assigning `version`
would cover the ordering: it fails at this head and passes with the provider.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]