Repository navigation
Keep a custom @Execute phase instead of resolving it as an enum - #1235
CaptainAni187 wants to merge 2 commits into
Conversation
ExecuteAnnotationContent.phase(String) already matches the value against LifecyclePhase and keeps anything else as a custom phase, but its last line then overwrote the result with LifecyclePhase.valueOf(phase). A standard phase returns from the loop before reaching that line; any other value threw, so @execute(phase = "my-phase") and @execute(phase = "none") failed descriptor extraction with "No enum constant LifecyclePhase.none". Drop the leftover line, which predates the loop added for MPLUGIN-508. Fixes apache#1232
|
@slachiewicz could you take a look at this and #1236 when you have time? Both have been green since Oct 6. |
gnodet
left a comment
There was a problem hiding this comment.
Claude Code on behalf of Guillaume Nodet
Thanks for the fix — removing the broken line 75 is clearly correct, good catch.
A couple of things to address before merge:
1. "none" should map to LifecyclePhase.NONE
With this fix, @Execute(phase = "none") (lowercase) ends up as customPhase = "none" — a literal custom phase that Maven will try to execute. In Maven 3, LifecyclePhase.NONE (id "") means "disabled / no phase", and users migrating to Maven 4 (where phase is a plain String) will naturally write "none" expecting the same semantics.
The comparison at line 63 is case-sensitive, so "none" doesn't match NONE.name() ("NONE"). The fix should add a case-insensitive comparison on the enum name, e.g.:
if (Objects.equals(phase, p.id()) || phase.equalsIgnoreCase(p.name())) {2. Broader follow-up: the two-field phase/customPhase model is a Maven 3 artifact
The LifecyclePhase enum only contains Maven 3 standard phases. In Maven 4:
- Phase names are hierarchical (
after:test-compile,before:integration-test, etc.) - Custom phases can be user-defined via
reactor.xml(see apache/maven#13249) @Execute.phase()is a plainString, no enum at all
So customPhase is no longer an "escape hatch" — it's the primary path for Maven 4. I'll file a follow-up issue to rethink the internal model.
For this PR: the immediate fix (removing line 75) + the "none" case-insensitive mapping would be enough to merge.
gnodet-bot
left a comment
There was a problem hiding this comment.
LGTM. Clean, correct, minimal one-line deletion that removes dead/broken code. The deleted this.phase = LifecyclePhase.valueOf(phase) was unreachable for valid standard phases (the for-loop returns early) and threw IllegalArgumentException for any non-standard phase, defeating the entire purpose of customPhase support. Tests exercise all four equivalence classes of the method.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Compare the phase with the enum constant names case-insensitively, so a lowercase "none" means no phase instead of a custom phase called none.
Fixes #1232.
ExecuteAnnotationContent.phase(String)already maps a standard phase id or enum name toLifecyclePhaseand keeps any other value ascustomPhase, but its last line then overwrote the result withLifecyclePhase.valueOf(phase). A standard phase returns from the loop before reaching it; any other value threw, so@Execute(phase = "my-phase")and@Execute(phase = "none")failed descriptor extraction withNo enum constant ... LifecyclePhase.none.This removes that leftover line. The extractor already turns
customPhaseinto the descriptor's execute phase, so nothing else needed to change.Added
ExecuteAnnotationContentTest: a standard phase id, an enum constant name, a custom phase and"none", which maps toLifecyclePhase.NONE. The last two fail on master with the error from the issue."none"is matched case-insensitively against the enum constant names, so@Execute(phase = "none")maps toLifecyclePhase.NONE, the same as Maven 3'sLifecyclePhase.NONE.