jdaugherty commented on code in PR #11:
URL: https://github.com/apache/grails-micronaut/pull/11#discussion_r4222679196


##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -87,7 +88,8 @@ class CompilePlugin implements Plugin<Project> {
 
             jar.manifest.attributes(
                     'Implementation-Title': 'Apache Grails',
-                    'Implementation-Version': lookupPropertyByType(project, 
'grailsVersion', String),
+                    'Implementation-Version': lookupProperty(project, 
'projectVersion',
+                            lookupPropertyByType(project, 'grailsVersion', 
String)),

Review Comment:
   Are you trying to pin a version here? Whats the goal of this?



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {

Review Comment:
   Beyond the CME on line 165, this wiring is fragile. It runs in 
`afterEvaluate`, realizes every `GroovyCompile` eagerly, creates the writer 
with `register(...).get()`, adds a manual `dependsOn`, and overwrites the 
script the `configureEach` above just set. A `GroovyCompile` registered after 
that callback would silently fall back to grails-core's 
`Implementation-Version`.
   
   grails-gradle 8.0.0 solved the same problem with 
`GrailsCompilerConfigScriptTask`. Mirroring it would remove most of this:
   
   - a typed task with an `@Input` version property (fed from `project.provider 
{ project.version.toString() }`) and an `@OutputFile`
   - registered per source set with `sourceSets.configureEach`
   - wired from the existing `configureEach` with 
`it.groovyOptions.configurationScriptFile.set(writer.flatMap { it.outputFile })`
   
   That gives the compile task an implicit dependency on the writer and needs 
no `afterEvaluate`. Not blocking if the CME and the skip list are fixed.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -145,6 +147,24 @@ class CompilePlugin implements Plugin<Project> {
                 // when both are present.
                 it.groovyOptions.configurationScript =
                         
GradleUtils.findRootGrailsCoreDir(project).file('gradle/groovy-compile-configscript.groovy').asFile
+            }
+                // Stamp this repository's published version onto compiled 
classes after the build
+                // script has assigned version. Without the stamp, the Grails 
transform falls back to
+                // grails-core's Implementation-Version, so a snapshot build 
of this plugin would
+                // advertise the released framework version. The script is 
generated by a task so
+                // `clean compileGroovy` can recreate it after `clean` deletes 
`build/`.
+            project.afterEvaluate {
+                // Applications and plugins built with the Grails Gradle 
plugin already stamp
+                // project.version. Replacing their merged compiler script 
would drop that plugin's
+                // own configuration. This repository's published plugin does 
not apply it.
+                if 
(project.plugins.hasPlugin('org.apache.grails.gradle.grails-plugin')
+                        || 
project.plugins.hasPlugin('org.apache.grails.gradle.grails-web')
+                        || 
project.plugins.hasPlugin('org.apache.grails.gradle.grails-gsp')) {

Review Comment:
   The reasoning in this comment doesn't match grails-gradle 8.0.0:
   
   - Only `GrailsPluginGradlePlugin` (`grails-plugin`) stamps 
`projectVersion`/`projectName`. Applications (`grails-web`, `grails-app`) don't.
   - `GrailsGradlePlugin` reads whatever `configurationScript` the task has at 
`taskGraph.whenReady` and folds it into its combined script, so setting ours 
wouldn't drop its configuration.
   
   Apps still need to be skipped, but for a different reason: stamping 
`projectName` makes `GlobalGrailsClassInjectorTransformation` add 
`@GrailsPlugin(name, version)` to every `grails-app` artefact, so app classes 
would look plugin-provided.
   
   The list also misses `org.apache.grails.gradle.grails-app` (the base 
`GrailsGradlePlugin`), and `grails-gsp` doesn't apply `GrailsGradlePlugin` 
itself. Rather than maintain this deny-list, could stamping be opt-in? Gating 
on `org.apache.grails.buildsrc.publish` would select exactly 
`:grails-micronaut`.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile
+        File output = 
project.layout.buildDirectory.file("groovy-compiler/${compile.name}-config.groovy").get().asFile
+        // Captured here, inside afterEvaluate, so version is the build 
script's value and the
+        // writer action does not touch the project. A configuration-time 
write would not survive
+        // `clean`, and compileGroovy would then fail because nothing 
regenerates its input.
+        String version = project.version?.toString() ?: ''
+        String name = project.name
+        String writerName = "grailsCompilerConfig${compile.name.capitalize()}"
+        // mustRunAfter(clean): `clean compileGroovy` schedules both, and 
command-line order is not a
+        // dependency. Without this, clean can delete the script after the 
writer creates it.
+        Task writer = project.tasks.register(writerName) { Task task ->
+            task.mustRunAfter('clean')
+            
task.inputs.file(baseScript).withPathSensitivity(PathSensitivity.NONE).withPropertyName('reproducibleCompilerScript')
+            task.inputs.property('publishedVersion', version)
+            task.inputs.property('publishedName', name)
+            task.outputs.file(output)
+            task.doLast {
+                writePublishedVersionScript(baseScript, output, version, name)
+            }
+        }.get()
+        compile.dependsOn(writer)
+        compile.groovyOptions.configurationScript = output
+    }
+
+    private static void writePublishedVersionScript(File baseScript, File 
output, String version, String name) {
+        output.parentFile.mkdirs()
+        String base = baseScript.exists() ? 
baseScript.getText(StandardCharsets.UTF_8.name()) : ''

Review Comment:
   Minor: the `''` branch can't be reached. `task.inputs.file(baseScript)` 
fails Gradle's input validation when the file is missing, before this action 
runs. Either drop the fallback or mark the input `.optional()` if a missing 
base script should be supported.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -145,6 +147,24 @@ class CompilePlugin implements Plugin<Project> {
                 // when both are present.
                 it.groovyOptions.configurationScript =
                         
GradleUtils.findRootGrailsCoreDir(project).file('gradle/groovy-compile-configscript.groovy').asFile
+            }
+                // Stamp this repository's published version onto compiled 
classes after the build
+                // script has assigned version. Without the stamp, the Grails 
transform falls back to
+                // grails-core's Implementation-Version, so a snapshot build 
of this plugin would
+                // advertise the released framework version. The script is 
generated by a task so
+                // `clean compileGroovy` can recreate it after `clean` deletes 
`build/`.
+            project.afterEvaluate {
+                // Applications and plugins built with the Grails Gradle 
plugin already stamp
+                // project.version. Replacing their merged compiler script 
would drop that plugin's
+                // own configuration. This repository's published plugin does 
not apply it.
+                if 
(project.plugins.hasPlugin('org.apache.grails.gradle.grails-plugin')
+                        || 
project.plugins.hasPlugin('org.apache.grails.gradle.grails-web')
+                        || 
project.plugins.hasPlugin('org.apache.grails.gradle.grails-gsp')) {
+                    return
+                }
+                project.tasks.withType(GroovyCompile).each { GroovyCompile 
compile ->

Review Comment:
   **Blocker:** this fails configuration for any non-SNAPSHOT version:
   
   ```
   ./gradlew help -PprojectVersion=8.0.0    # same with 8.0.0-RC1
   * What went wrong:
   A problem occurred configuring project ':grails-micronaut'.
   > java.util.ConcurrentModificationException
       at 
org.gradle.api.internal.collections.FilteredElementSource$FilteringIterator.findNext(FilteredElementSource.java:118)
       ...
       at 
org.apache.grails.buildsrc.CompilePlugin$_configureCompiler_closure6$_closure11.doCall(CompilePlugin.groovy:165)
   ```
   
   `configurePublishedVersionScript` registers and realizes a new task while 
this `.each` is still iterating the live `tasks.withType(GroovyCompile)` 
collection. The default version and `8.0.1-SNAPSHOT` configure fine, so 
SNAPSHOT-only testing doesn't catch it, but every release or RC version throws. 
All three steps in `.github/workflows/release.yml` pass 
`-PprojectVersion=${RELEASE_VERSION}`, so the release jobs would fail before 
running a task.
   
   Iterating over a copy fixes it. With this change, `-PprojectVersion=8.0.0` 
builds and `grails-plugin.xml` gets `version='8.0.0'`:
   
   ```suggestion
                   project.tasks.withType(GroovyCompile).toList().each { 
GroovyCompile compile ->
   ```
   
   A CI step that configures the build with a release version (for example 
`./gradlew help -PprojectVersion=0.0.0`) would catch release-only configuration 
failures like this before a tag.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile

Review Comment:
   This branch can't be reached: `task.inputs.file(baseScript)` fails input 
validation first when the file is missing. And if it were reached, the appended 
`withConfig(configuration) { … }` block is valid on its own, so the script 
wouldn't be broken. See the note on line 215.



##########
build-logic/plugins/src/test/groovy/org/apache/grails/buildsrc/CompilePluginSpec.groovy:
##########
@@ -116,6 +116,90 @@ class CompilePluginSpec extends Specification {
         result.output.contains('TEST_INDY=true')
     }
 
+    def "compiler configuration stamps the published project version"() {
+        given:
+        testProjectDir.resolve('build.gradle').toFile().text = """
+            plugins {
+                id 'groovy'
+                id 'org.apache.grails.buildsrc.compile'
+            }
+
+            version = '8.0.0-SNAPSHOT'
+
+            ext {
+                javaVersion = 21
+                grailsVersion = '8.0.0'
+                formattedBuildDate = '2026-01-01'
+            }
+
+            repositories {
+                mavenCentral()
+            }
+        """
+
+        when:
+        def result = GradleRunner.create()
+                .withProjectDir(testProjectDir.toFile())
+                .withArguments(['grailsCompilerConfigCompileGroovy', 
'--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',")

Review Comment:
   Both new specs only use `8.0.0-SNAPSHOT`, which is why the release-version 
failure on `CompilePlugin.groovy:165` wasn't caught. A release-version case 
here, or the CI configuration check suggested on that comment, would cover it. 
Also, this assertion doesn't check the name value, and nothing covers the skip 
path for projects that apply the Grails Gradle plugins.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile
+        File output = 
project.layout.buildDirectory.file("groovy-compiler/${compile.name}-config.groovy").get().asFile
+        // Captured here, inside afterEvaluate, so version is the build 
script's value and the
+        // writer action does not touch the project. A configuration-time 
write would not survive
+        // `clean`, and compileGroovy would then fail because nothing 
regenerates its input.
+        String version = project.version?.toString() ?: ''
+        String name = project.name
+        String writerName = "grailsCompilerConfig${compile.name.capitalize()}"
+        // mustRunAfter(clean): `clean compileGroovy` schedules both, and 
command-line order is not a
+        // dependency. Without this, clean can delete the script after the 
writer creates it.
+        Task writer = project.tasks.register(writerName) { Task task ->
+            task.mustRunAfter('clean')
+            
task.inputs.file(baseScript).withPathSensitivity(PathSensitivity.NONE).withPropertyName('reproducibleCompilerScript')
+            task.inputs.property('publishedVersion', version)
+            task.inputs.property('publishedName', name)
+            task.outputs.file(output)
+            task.doLast {
+                writePublishedVersionScript(baseScript, output, version, name)
+            }
+        }.get()
+        compile.dependsOn(writer)
+        compile.groovyOptions.configurationScript = output

Review Comment:
   Same as the thread on line 190. See the comment on line 165 for the 
`ConcurrentModificationException` this wiring causes.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile
+        File output = 
project.layout.buildDirectory.file("groovy-compiler/${compile.name}-config.groovy").get().asFile
+        // Captured here, inside afterEvaluate, so version is the build 
script's value and the
+        // writer action does not touch the project. A configuration-time 
write would not survive
+        // `clean`, and compileGroovy would then fail because nothing 
regenerates its input.
+        String version = project.version?.toString() ?: ''
+        String name = project.name
+        String writerName = "grailsCompilerConfig${compile.name.capitalize()}"
+        // mustRunAfter(clean): `clean compileGroovy` schedules both, and 
command-line order is not a
+        // dependency. Without this, clean can delete the script after the 
writer creates it.
+        Task writer = project.tasks.register(writerName) { Task task ->
+            task.mustRunAfter('clean')
+            
task.inputs.file(baseScript).withPathSensitivity(PathSensitivity.NONE).withPropertyName('reproducibleCompilerScript')
+            task.inputs.property('publishedVersion', version)
+            task.inputs.property('publishedName', name)
+            task.outputs.file(output)
+            task.doLast {
+                writePublishedVersionScript(baseScript, output, version, name)
+            }
+        }.get()
+        compile.dependsOn(writer)
+        compile.groovyOptions.configurationScript = output
+    }
+
+    private static void writePublishedVersionScript(File baseScript, File 
output, String version, String name) {
+        output.parentFile.mkdirs()
+        String base = baseScript.exists() ? 
baseScript.getText(StandardCharsets.UTF_8.name()) : ''
+        String script = """${base}
+
+withConfig(configuration) {
+    inline(phase: 'CONVERSION') { source, context, classNode ->
+        classNode.putNodeMetaData('projectVersion', 
'${escapeGroovyLiteral(version)}')
+        classNode.putNodeMetaData('projectName', 
'${escapeGroovyLiteral(name)}')
+    }
+}
+"""
+        output.setText(script, StandardCharsets.UTF_8.name())
+    }
+
+    private static String escapeGroovyLiteral(String value) {
+        value.replace('\\', '\\\\').replace('\'', '\\\'')

Review Comment:
   Not a concern here: the inputs are `project.version` and `project.name`, 
which won't contain newlines. grails-gradle's `GrailsPluginGradlePlugin` embeds 
the same values without any escaping.



##########
settings.gradle:
##########
@@ -27,11 +27,11 @@ pluginManagement {
         configurePluginRepositories(delegate)
     }
     plugins {
-        def grailsVersion = providers.gradleProperty('projectVersion').get()
+        def grailsVersion = providers.gradleProperty('grailsVersion').get()
         id 'org.apache.grails.gradle.grails-gsp' version grailsVersion
         id 'org.apache.grails.gradle.grails-plugin' version grailsVersion
         id 'org.apache.grails.gradle.grails-web' version grailsVersion
-        id 'cloud.wondrify.asset-pipeline' version '5.2.0-M3'
+        id 'cloud.wondrify.asset-pipeline' version '5.2.0'

Review Comment:
   Not an issue: `grailsVersion` is always set in `gradle.properties`, and this 
is the same `.get()` pattern the previous `projectVersion` lookup used.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -87,7 +88,8 @@ class CompilePlugin implements Plugin<Project> {
 
             jar.manifest.attributes(
                     'Implementation-Title': 'Apache Grails',
-                    'Implementation-Version': lookupPropertyByType(project, 
'grailsVersion', String),
+                    'Implementation-Version': lookupProperty(project, 
'projectVersion',
+                            lookupPropertyByType(project, 'grailsVersion', 
String)),

Review Comment:
   For context: something here is needed. Without it, the 
`SharedPropertyPlugin` change flips the jar's `Implementation-Version` to 
`8.0.0`. If keeping the manifest on this repository's version is the goal, 
please read `project.version` rather than the `projectVersion` property so the 
manifest and the compiler stamp use one source, and mention the manifest change 
in the PR description.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -145,6 +147,24 @@ class CompilePlugin implements Plugin<Project> {
                 // when both are present.
                 it.groovyOptions.configurationScript =
                         
GradleUtils.findRootGrailsCoreDir(project).file('gradle/groovy-compile-configscript.groovy').asFile
+            }
+                // Stamp this repository's published version onto compiled 
classes after the build
+                // script has assigned version. Without the stamp, the Grails 
transform falls back to
+                // grails-core's Implementation-Version, so a snapshot build 
of this plugin would
+                // advertise the released framework version. The script is 
generated by a task so
+                // `clean compileGroovy` can recreate it after `clean` deletes 
`build/`.

Review Comment:
   Nit: this comment is indented one level deeper than the 
`project.afterEvaluate` it describes and sits right after the closing brace 
above, so it reads as part of the previous block.



##########
README.md:
##########
@@ -20,7 +20,7 @@ limitations under the License.
 
 This repository contains the Grails Micronaut plugin, its Micronaut-specific 
BOMs, and focused integration examples.
 
-The build consumes published `org.apache.grails` artifacts from the Grails 
8.0.x repositories. Only the four artifacts owned by this repository are built 
locally:
+The build consumes the released Grails 8.0.0 artifacts (`grailsVersion` in 
`gradle.properties`). This repository's own version stays `8.0.0-SNAPSHOT` 
until its release tag. Only the four artifacts owned by this repository are 
built locally:

Review Comment:
   Nit: hard-coding `8.0.0` here will drift on the next Grails bump. Pointing 
at `grailsVersion` in `gradle.properties` is enough.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile
+        File output = 
project.layout.buildDirectory.file("groovy-compiler/${compile.name}-config.groovy").get().asFile

Review Comment:
   Agreed, and the bigger problem in this area is the 
`ConcurrentModificationException`: registering the writer while line 165 
iterates the `GroovyCompile` tasks breaks configuration for release versions. 
See the comment on line 165, and the one on line 187 for a lazier design.



##########
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy:
##########
@@ -155,6 +175,60 @@ class CompilePlugin implements Plugin<Project> {
         }
     }
 
+    /**
+     * Writes the Groovy compiler configuration for {@code compile}, including 
the shared
+     * reproducibility script and this project's published version.
+     *
+     * <p>The published version is captured in {@code afterEvaluate}, after 
the build script assigns
+     * {@code version}. The script file is produced by a task, not written 
during configuration, so
+     * {@code clean compileGroovy} in one invocation regenerates it after 
{@code clean} deletes
+     * {@code build/}.</p>
+     */
+    private static void configurePublishedVersionScript(Project project, 
GroovyCompile compile) {
+        File baseScript = GradleUtils.findRootGrailsCoreDir(project)
+                .file('gradle/groovy-compile-configscript.groovy').asFile
+        File output = 
project.layout.buildDirectory.file("groovy-compiler/${compile.name}-config.groovy").get().asFile
+        // Captured here, inside afterEvaluate, so version is the build 
script's value and the
+        // writer action does not touch the project. A configuration-time 
write would not survive
+        // `clean`, and compileGroovy would then fail because nothing 
regenerates its input.
+        String version = project.version?.toString() ?: ''
+        String name = project.name
+        String writerName = "grailsCompilerConfig${compile.name.capitalize()}"
+        // mustRunAfter(clean): `clean compileGroovy` schedules both, and 
command-line order is not a
+        // dependency. Without this, clean can delete the script after the 
writer creates it.
+        Task writer = project.tasks.register(writerName) { Task task ->
+            task.mustRunAfter('clean')
+            
task.inputs.file(baseScript).withPathSensitivity(PathSensitivity.NONE).withPropertyName('reproducibleCompilerScript')
+            task.inputs.property('publishedVersion', version)
+            task.inputs.property('publishedName', name)
+            task.outputs.file(output)
+            task.doLast {
+                writePublishedVersionScript(baseScript, output, version, name)
+            }
+        }.get()
+        compile.dependsOn(writer)
+        compile.groovyOptions.configurationScript = output
+    }
+
+    private static void writePublishedVersionScript(File baseScript, File 
output, String version, String name) {
+        output.parentFile.mkdirs()
+        String base = baseScript.exists() ? 
baseScript.getText(StandardCharsets.UTF_8.name()) : ''
+        String script = """${base}

Review Comment:
   Same as the thread on line 189: unreachable, and the appended block is valid 
on its own.



-- 
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]

Reply via email to