jamesfredley commented on code in PR #16082:
URL: https://github.com/apache/grails-core/pull/16082#discussion_r3699559916


##########
grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy:
##########
@@ -244,22 +246,69 @@ class GrailsPluginGradlePlugin extends GrailsGradlePlugin 
{
         }
     }
 
+    /**
+     * Packages plugin templates into the runtime jar and routes command 
scripts into either the
+     * runtime jar or the companion {@code -cli} jar.
+     *
+     * <p>When {@link GrailsCliArtifactGradlePlugin} is applied, {@code 
src/main/scripts} is copied
+     * into the cli source set as {@code META-INF/commands} so 
Groovy/YAML/JSON command resources
+     * ship only on {@code grailsCliClasspath} and stay out of {@code 
runtimeClasspath},
+     * {@code bootJar}, and {@code bootWar}. Without a companion, the 
historical behavior is
+     * preserved: scripts remain in the runtime plugin jar so unmigrated 
Grails 7 plugins and
+     * {@code legacyCommandSupport} consumers keep discovering them on the 
application classpath.
+     * Templates always stay on the runtime jar.</p>
+     */
     @CompileDynamic
     protected void configurePluginResources(Project project) {
         project.afterEvaluate() {
             ProcessResources processResources = (ProcessResources) 
project.tasks.getByName('processResources')
+            boolean hasCliCompanion = 
project.pluginManager.hasPlugin(GrailsCliArtifactGradlePlugin.PLUGIN_ID)
+            ProcessResources commandResources = processResources
+            if (hasCliCompanion) {
+                SourceSet cliSourceSet = 
project.extensions.getByType(SourceSetContainer)
+                        
.getByName(GrailsCliArtifactGradlePlugin.CLI_SOURCE_SET_NAME)
+                commandResources = (ProcessResources) 
project.tasks.getByName(cliSourceSet.processResourcesTaskName)
+            }
 
-            TaskProvider<Copy> copyCommands = 
project.tasks.register('copyCommands', Copy) {
-                from("${project.projectDir}/src/main/scripts")
-                into("${processResources.destinationDir}/META-INF/commands")
+            TaskProvider<Copy> copyCommands = 
project.tasks.register('copyCommands', Copy) { Copy copy ->
+                copy.from("${project.projectDir}/src/main/scripts")
+                // Resolve the destination lazily so the process*Resources 
output dir is final.
+                copy.into {
+                    "${commandResources.destinationDir}/META-INF/commands"
+                }
             }
 
-            TaskProvider<Copy> copyTemplates = 
project.tasks.register('copyTemplates', Copy) {
-                from("${project.projectDir}/src/main/templates")
-                into("${processResources.destinationDir}/META-INF/templates")
+            TaskProvider<Copy> copyTemplates = 
project.tasks.register('copyTemplates', Copy) { Copy copy ->
+                copy.from("${project.projectDir}/src/main/templates")
+                copy.into {
+                    "${processResources.destinationDir}/META-INF/templates"
+                }
             }
             processResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE)
-            processResources.dependsOn(copyCommands, copyTemplates)
+            if (hasCliCompanion) {
+                
commandResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE)
+                commandResources.dependsOn(copyCommands)
+                processResources.dependsOn(copyTemplates)
+                // A prior non-companion (or pre-migration) build may have 
left src/main/scripts
+                // copies under the main processResources output. Wipe 
META-INF/commands there so
+                // incremental jars do not keep shipping them; 
processResources then re-runs (its
+                // outputs changed) and restores any hand-authored 
src/main/resources/META-INF/commands.
+                // Use the configured processResources destination, not a 
hard-coded build path.
+                TaskProvider cleanStaleRuntimeCommands = project.tasks
+                        .register('cleanStaleRuntimeCommandResources') { Task 
cleanTask ->
+                            cleanTask.outputs.upToDateWhen { false }
+                            cleanTask.doLast {
+                                project.delete(new 
File(processResources.destinationDir, 'META-INF/commands'))
+                            }
+                        }

Review Comment:
   Addressed in 7a3049d707.
   
   Removed `cleanStaleRuntimeCommandResources` entirely (no more 
`outputs.upToDateWhen { false }` wired into `processResources`/`jar`).
   
   Instead:
   1. `copyCommands` / `copyTemplates` are now **`Sync`** tasks with **unique** 
dirs under `build/tmp/`
   2. `processResources` / `processCliResources` consume those via `from(...)` 
so Gradle owns each path
   3. When a companion is present, the runtime `jar` filters 
`META-INF/commands` to only hand-authored 
`src/main/resources/META-INF/commands` entries - covers leftover files from 
prior non-companion packaging **without** a forced clean task
   
   `PluginScriptCommandPackagingSpec` still asserts companion vs non-companion 
packaging, unique Sync output path, and that seeded stale runtime leftovers are 
excluded from the runtime jar while hand-authored commands remain.



##########
grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsPluginGradlePlugin.groovy:
##########
@@ -244,22 +246,69 @@ class GrailsPluginGradlePlugin extends GrailsGradlePlugin 
{
         }
     }
 
+    /**
+     * Packages plugin templates into the runtime jar and routes command 
scripts into either the
+     * runtime jar or the companion {@code -cli} jar.
+     *
+     * <p>When {@link GrailsCliArtifactGradlePlugin} is applied, {@code 
src/main/scripts} is copied
+     * into the cli source set as {@code META-INF/commands} so 
Groovy/YAML/JSON command resources
+     * ship only on {@code grailsCliClasspath} and stay out of {@code 
runtimeClasspath},
+     * {@code bootJar}, and {@code bootWar}. Without a companion, the 
historical behavior is
+     * preserved: scripts remain in the runtime plugin jar so unmigrated 
Grails 7 plugins and
+     * {@code legacyCommandSupport} consumers keep discovering them on the 
application classpath.
+     * Templates always stay on the runtime jar.</p>
+     */
     @CompileDynamic
     protected void configurePluginResources(Project project) {
         project.afterEvaluate() {
             ProcessResources processResources = (ProcessResources) 
project.tasks.getByName('processResources')
+            boolean hasCliCompanion = 
project.pluginManager.hasPlugin(GrailsCliArtifactGradlePlugin.PLUGIN_ID)
+            ProcessResources commandResources = processResources
+            if (hasCliCompanion) {
+                SourceSet cliSourceSet = 
project.extensions.getByType(SourceSetContainer)
+                        
.getByName(GrailsCliArtifactGradlePlugin.CLI_SOURCE_SET_NAME)
+                commandResources = (ProcessResources) 
project.tasks.getByName(cliSourceSet.processResourcesTaskName)
+            }
 
-            TaskProvider<Copy> copyCommands = 
project.tasks.register('copyCommands', Copy) {
-                from("${project.projectDir}/src/main/scripts")
-                into("${processResources.destinationDir}/META-INF/commands")
+            TaskProvider<Copy> copyCommands = 
project.tasks.register('copyCommands', Copy) { Copy copy ->
+                copy.from("${project.projectDir}/src/main/scripts")
+                // Resolve the destination lazily so the process*Resources 
output dir is final.
+                copy.into {
+                    "${commandResources.destinationDir}/META-INF/commands"
+                }
             }
 
-            TaskProvider<Copy> copyTemplates = 
project.tasks.register('copyTemplates', Copy) {
-                from("${project.projectDir}/src/main/templates")
-                into("${processResources.destinationDir}/META-INF/templates")
+            TaskProvider<Copy> copyTemplates = 
project.tasks.register('copyTemplates', Copy) { Copy copy ->
+                copy.from("${project.projectDir}/src/main/templates")
+                copy.into {
+                    "${processResources.destinationDir}/META-INF/templates"
+                }
             }
             processResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE)
-            processResources.dependsOn(copyCommands, copyTemplates)
+            if (hasCliCompanion) {
+                
commandResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE)
+                commandResources.dependsOn(copyCommands)
+                processResources.dependsOn(copyTemplates)
+                // A prior non-companion (or pre-migration) build may have 
left src/main/scripts
+                // copies under the main processResources output. Wipe 
META-INF/commands there so
+                // incremental jars do not keep shipping them; 
processResources then re-runs (its
+                // outputs changed) and restores any hand-authored 
src/main/resources/META-INF/commands.
+                // Use the configured processResources destination, not a 
hard-coded build path.
+                TaskProvider cleanStaleRuntimeCommands = project.tasks
+                        .register('cleanStaleRuntimeCommandResources') { Task 
cleanTask ->
+                            cleanTask.outputs.upToDateWhen { false }
+                            cleanTask.doLast {
+                                project.delete(new 
File(processResources.destinationDir, 'META-INF/commands'))
+                            }
+                        }

Review Comment:
   Agreed - forced clean tasks were the wrong tool. Fixed in 7a3049d707 per 
your guidance:
   
   - Unique Sync output dirs for `copyCommands` / `copyTemplates` 
(`build/tmp/grails-plugin-*`)
   - Downstream `process*Resources` consume via `from(...)` so Gradle tracks 
ownership
   - No clean task forced out-of-date or wired into every build
   
   For leftovers already sitting under `processResources.destinationDir` from 
the old side-write design, the runtime jar filters non-hand-authored 
`META-INF/commands` entries when a companion is present (packaging-time filter, 
not a clean task).



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