Conversation
gnodet
left a comment
There was a problem hiding this comment.
Code Review
The core architecture for wiring @After annotation ordering constraints into the concurrent build plan is sound and follows the existing Lifecycle.Link processing patterns well. The decision to access afterLinks directly from the V4 descriptor rather than bridging through the V3 compat layer is correct. However, there is a compilation error in the IT plugin that needs fixing.
1. Compilation error in IT plugin (high)
File: its/core-it-suite/src/test/resources/mng-12534-after-annotation/plugin/src/main/java/org/apache/maven/its/mng12534/TouchMojo.java
@After(phase = "sources") is missing the required type attribute. After.type() has no default value (Type type();), so javac will reject this with error: annotation @After is missing a default value for the element 'type'. Fix: either add type = After.Type.PROJECT here, or add default Type.PROJECT to the annotation definition if that's the desired UX.
2. Missing scope TODO in DEPENDENCIES branch (medium)
File: impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java (lines 685-692)
The DEPENDENCIES branch of applyAfterLinks ignores afterLink.getScope() without comment. The existing lifecycle link processing at line 971 has an explicit // TODO: String scope = ... comment acknowledging this gap. Adding a matching TODO would maintain consistency.
3. PR description claims non-existent tests (medium)
The test plan in the PR description checks off MojoDescriptorTest and PluginDescriptorBuilderTest as completed, but neither file was modified in this changeset. The description should be updated to reflect the actual test coverage (BuildPlanCreatorTest + the IT).
4. Simulation-style unit test (low)
File: impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanCreatorTest.java (lines 134-160)
The new tests manually create BuildStep edges rather than invoking the actual applyAfterLinks method. Since the method is private in a different class, this is a reasonable compromise — the IT covers the end-to-end path.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
gnodet
left a comment
There was a problem hiding this comment.
Thanks for the thorough review! Addressed all four points:
@After.type()default — Addeddefault Type.PROJECTso the common case is just@After(phase = "sources"). Added atypeDefaultsToProjecttest to verify.- Scope TODO — Added
// TODO: String scope = afterLink.getScope();in the DEPENDENCIES branch, matching the existing pattern at line 1017. - PR description — Updated to reflect actual test coverage (AfterAnnotationTest, BuildPlanCreatorTest, MavenITmng12534AfterAnnotationTest). Removed references to MojoDescriptorTest/PluginDescriptorBuilderTest.
- Simulation-style unit test — Agreed, this is a reasonable compromise given
applyAfterLinksis private in BuildPlanExecutor. The IT covers the end-to-end path through the actual method.
gnodet
left a comment
There was a problem hiding this comment.
Re-review after commit 56823a3 ("Address review feedback")
All four previously flagged issues are resolved:
- ✅ Default
Type.PROJECTon@After.type()— IT plugin no longer requires explicit type attribute; newtypeDefaultsToProjecttest validates this. - ✅ Scope TODO — now matches the existing pattern at line 1018 in lifecycle link processing.
- ✅ PR description — test plan updated to reference actual tests (AfterAnnotationTest, BuildPlanCreatorTest, MavenITmng12534AfterAnnotationTest).
- ✅ Simulation-style test — acknowledged as reasonable compromise since
applyAfterLinksis private and the IT covers end-to-end.
Looks good to merge. 👍
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
00e47ba to
967d91a
Compare
|
CI failure is unrelated to this PR — it's the same PR #12543 (Dependabot: bump All our actual tests pass (AfterAnnotationTest, BuildPlanCreatorTest, and the IT) — the build fails before reaching our code because the resolver SNAPSHOT artifacts aren't available in the Apache snapshots repository. |
gnodet
left a comment
There was a problem hiding this comment.
Re-review after scope filtering implementation (11 new commits)
The @After annotation wiring and IT remain solid. The new filterByScope method is well-structured, but two concerns:
-
No test coverage for
filterByScope—testAfterLinkDependenciesOrderingbypasses the scope filter by iterating the raw upstream project list directly rather than callingfilterByScope. A unit test with dependencies of different scopes would strengthen confidence. -
Behavioral change for
provided-scoped reactor deps — Previously (TODO), ALL upstream projects were included in dependency ordering. Now,dependencies(SCOPE_COMPILE, READY)on the compile phase uses exact string matching, soprovided-scoped reactor deps are excluded from ordering. SincePathScope.MAIN_COMPILEincludesDependencyScope.PROVIDED, these deps ARE on the compile classpath but the concurrent builder may no longer wait for them. Risk is mitigated by rarity of provided-scoped reactor deps, but worth validating.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
59a6c81 to
d92aa3d
Compare
|
Addressed both points from the re-review:
|
gnodet
left a comment
There was a problem hiding this comment.
Re-review after addressing feedback ✅
Both prior findings are resolved:
-
filterByScopetest coverage — Two new unit tests added (testFilterByScopeNullReturnsAll,testFilterByScopeMatchesExact) covering null/empty scope, compile, provided, test, and null-scoped (default compile) dependencies. Method made package-visible for direct testing. -
provided-scope behavior documented — Javadoc now explicitly documents that filtering is exact on scope strings and does not perform path-scope resolution (e.g.,provideddeps are not included when filtering bycompile). Notes that broader scope-aware filtering can be added in a follow-up.
Looks good to merge.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
Add support for the @after annotation to declare lifecycle ordering constraints on Mojo classes. This allows plugins to specify that a goal must run after a particular phase, with support for same-project, cross-dependency, and parent-child ordering. Changes: - Make @after repeatable via @afters container annotation - Add default Type.PROJECT to @After.type() for simpler common case - Add AfterLink model class to plugin.mdo (V2 plugin descriptor) - Apply afterLinks in BuildPlanExecutor.applyAfterLinks() to create build step ordering edges matching Lifecycle.Link semantics - Implement dependency scope filtering for DEPENDENCIES pointer type in both afterLinks and existing lifecycle link processing - Add AfterAnnotationTest, BuildPlanCreatorTest, and end-to-end IT The annotation scanner in maven-plugin-tools does not yet read @after; that is a separate follow-up. The IT uses a handcrafted V2 descriptor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
✅ Re-review after rebase — all previous feedback remains addressed. The @After annotation wiring is architecturally sound, follows existing Lifecycle.Link patterns, and has good test coverage including an end-to-end IT.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
|
@gnodet Please assign appropriate label to PR according to the type of change. |
…Maven core Backport of #12535 to maven-4.0.x for RC-6. Makes @after repeatable (@afters container), defaults type() to PROJECT, and wires up annotation processing in BuildPlanExecutor so that mojos annotated with @after correctly declare ordering constraints in the concurrent build plan. Includes unit tests for PROJECT, DEPENDENCIES, and CHILDREN after-link types, filterByScope logic, and an integration test with a handcrafted V2 plugin descriptor. Co-authored-by: Guillaume Nodet <gnodet@apache.org>
Summary
@Afterannotation@Repeatableby adding an@Afterscontainer annotation, so plugin mojos can declare multiple lifecycle ordering constraintsType.PROJECT) for@After.type()so the common case needs only@After(phase = "...")AfterLinkmodel class toplugin.mdo(V4 plugin descriptor) withphase,type, andscopefields to persist@Afterdata inMETA-INF/maven/plugin.xml@Afterordering constraints inBuildPlanExecutor.applyAfterLinks()— translates eachAfterLinkinto build step edges matching the same semantics asLifecycle.Linkprocessing (PROJECT, DEPENDENCIES, CHILDREN pointer types)Test plan
AfterAnnotationTest— verifies@Repeatablebehavior (single, multiple, container annotation, scope default)BuildPlanCreatorTest— verifies PROJECT, DEPENDENCIES, and CHILDREN ordering constraints create correct build step edgesMavenITmng12534AfterAnnotationTest— end-to-end IT: installs a V4 plugin with@After(phase = "sources"), builds a consumer project with-b concurrent, and verifies the mojo executes and the touch file is createdNotes
The annotation scanner in
maven-plugin-tools(separate repo) does not yet read@After— that's a follow-up to emit the new<afterLinks>elements intoplugin.xmlfrom Java source annotations. The IT plugin uses a handcrafted V2 descriptor until then.🤖 Generated with Claude Code