Visitar URL original
Keep a custom @Execute phase instead of resolving it as an enum by CaptainAni187 · Pull Request #1235 · apache/maven-plugin-tools · GitHub
Skip to content

Keep a custom @Execute phase instead of resolving it as an enum - #1235

Open
CaptainAni187 wants to merge 2 commits into
apache:masterfrom
CaptainAni187:fix-execute-custom-phase
Open

CaptainAni187 wants to merge 2 commits into
apache:masterfrom
CaptainAni187:fix-execute-custom-phase

Conversation

@CaptainAni187

@CaptainAni187 CaptainAni187 commented Oct 6, 2026 •

Copy link
Copy Markdown

Fixes #1232.

ExecuteAnnotationContent.phase(String) already maps a standard phase id or enum name to LifecyclePhase and keeps any other value as customPhase, but its last line then overwrote the result with LifecyclePhase.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 with No enum constant ... LifecyclePhase.none.

This removes that leftover line. The extractor already turns customPhase into 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 to LifecyclePhase.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 to LifecyclePhase.NONE, the same as Maven 3's LifecyclePhase.NONE.


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

Copy link
Copy Markdown
Author

@slachiewicz could you take a look at this and #1236 when you have time? Both have been green since Oct 6.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 plain String, 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 gnodet-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@CaptainAni187

Copy link
Copy Markdown
Author

@gnodet Thanks. Done in e1193cc: the enum name comparison is now case-insensitive, so "none" maps to LifecyclePhase.NONE, and the test checks that instead of the custom phase.

@slachiewicz slachiewicz added the bug Something isn't working label Oct 29, 2026
@CaptainAni187

Copy link
Copy Markdown
Author

@gnodet could you take another look when you have a moment? The case-insensitive none change from your review is in e1193cc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@Execute with a custom phase or "none" fails descriptor extraction

4 participants