Copilot commented on code in PR #13559:
URL: https://github.com/apache/maven/pull/13559#discussion_r4495099307


##########
impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java:
##########
@@ -272,19 +272,51 @@ public BuildPlan buildInitialPlan(List<TaskSegment> 
taskSegments) {
             // Handle reactor plugins: if a project uses a plugin that is also 
a reactor module,
             // the project's PLAN step must wait for the plugin project's 
READY step.
             // This must be done after PLAN/READY steps are created above.
+            applyReactorPluginConstraints(plan);
+
+            return plan;
+        }
+
+        /**
+         * Applies reactor-plugin ordering and skip-clearing constraints to a 
plan.
+         * <p>
+         * For each project that uses a plugin which is itself a reactor 
module, this method:
+         * <ol>
+         *   <li>Makes the consumer project's PLAN step wait for the plugin 
project's READY step.</li>
+         *   <li>Clears the {@code skip} flag on the plugin project's READY 
step and all its
+         *       predecessors within the same project, so that the plugin is 
always built to
+         *       READY even when the requested phase would otherwise stop 
before READY
+         *       (e.g. {@code initialize}).</li>
+         * </ol>
+         * <p>
+         * This method is package-private so that unit tests can exercise the 
logic independently
+         * of the full {@link #buildInitialPlan} setup (which requires a live 
{@code MavenSession}).
+         * Callers must ensure that PLAN steps for consumer projects and 
lifecycle steps (including
+         * READY) for plugin projects have already been added to the plan 
before calling this method.
+         *
+         * @param plan the build plan to mutate; must already contain PLAN 
steps for every project
+         */
+        void applyReactorPluginConstraints(BuildPlan plan) {
             Map<String, MavenProject> reactorGavs =
                     
plan.getAllProjects().keySet().stream().collect(Collectors.toMap(BuildPlanExecutor::gav,
 p -> p));
             for (MavenProject project : plan.getAllProjects().keySet()) {
                 for (Plugin plugin : project.getBuild().getPlugins()) {
                     MavenProject pluginProject = reactorGavs.get(gav(plugin));
                     if (pluginProject != null && pluginProject != project) {
-                        plan.step(project, PLAN)
-                                .ifPresent(pp -> plan.step(pluginProject, 
READY).ifPresent(pp::executeAfter));
+                        plan.step(project, PLAN).ifPresent(pp -> {
+                            plan.step(pluginProject, 
READY).ifPresent(readyStep -> {
+                                pp.executeAfter(readyStep);
+                                // Force the plugin project to reach READY 
even if the
+                                // requested phase is earlier (e.g. 
initialize).
+                                readyStep
+                                        .allPredecessors()
+                                        .filter(s -> s.project == 
pluginProject)

Review Comment:
   Restricting activation to `pluginProject` leaves its required reactor 
libraries skipped. With `initialize` on a clean reactor containing a library, a 
plugin that compiles against it, and a plugin consumer, the library's READY 
step completes without compiling its classes, so the newly enabled plugin 
compilation fails. Activate the required reactor dependency phases recursively 
as well, and add a three-project regression test.



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