gnodet opened a new issue, #13529: URL: https://github.com/apache/maven/issues/13529
## Summary When using `--builder concurrent`, specifying multiple lifecycle phases from the same lifecycle (e.g., `mvn package install` or `mvn package javadoc:aggregate-jar install`) causes later non-overlapping phases to be silently dropped. The `install` phase never executes. ## Steps to reproduce Create a multi-module project: ``` parent (pom) ├── module-a (jar) └── module-b (jar, depends on module-a) ``` Run with the concurrent builder: ```bash # Works correctly - install runs for all modules mvn -B --builder concurrent install # BUG: install phase is silently dropped mvn -B --builder concurrent package install # BUG: install phase is silently dropped mvn -B --builder concurrent package javadoc:aggregate-jar install ``` ## Expected behavior `mvn --builder concurrent package install` should run all phases from `validate` through `install` (deduplicated), including the `install` phase itself. ## Actual behavior Only phases up to `package` execute. The `install` phase (and any phases between `package` and `install` like `verify`) are silently dropped. ## Analysis The issue is in `BuildPlan.merge(Map<String, BuildStep>, Map<String, BuildStep>)` at line 98-109 of `BuildPlan.java`. When merging two plans with overlapping phases: 1. The merge finds "first" steps in the new plan (steps with no predecessors) and chains them after the "last" steps in the existing plan 2. But only first steps that are **not already present** in the existing plan get these ordering edges (line 105: `filter(addNode -> !org.containsKey(addNode.name))`) 3. For `package install`: the new plan's first step (e.g., `validate`) already exists in the existing plan, so it gets filtered out 4. The truly new steps (`verify`, `install`) are NOT first steps — they have predecessors within their own plan 5. Result: the new steps get added to the map but have no ordering edges connecting them to the existing plan's terminal steps The overlapping phases get correctly merged via `putIfAbsent`, but the non-overlapping later phases become unreachable in the execution graph. ## Comparison with sequential/multithreaded builders The sequential and multithreaded builders (`-T N`) process each task segment independently and re-run all phases from scratch. They never lose phases but duplicate execution (e.g., `mvn package install` runs `validate`→`package` twice). | Command | Sequential / `-T` | `--builder concurrent` | |---|---|---| | `install` | validate→install × 1 | validate→install × 1 ✅ | | `package install` | validate→package × 2, then install | validate→package × 1, **install lost** ❌ | | `package javadoc:aggregate-jar install` | validate→package × 3, then install | validate→package × 1, javadoc, **install lost** ❌ | _Claude Code on behalf of Guillaume Nodet_ -- 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]
