Skip to content

Auto-detect module source hierarchy and skip main artifact at deploy - #719

Open
gnodet wants to merge 2 commits into
apache:masterfrom
gnodet:feat/auto-detect-module-source-hierarchy
Open

gnodet wants to merge 2 commits into
apache:masterfrom
gnodet:feat/auto-detect-module-source-hierarchy

Conversation

@gnodet

@gnodet gnodet commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • When a project uses module source hierarchy (<source><module>…), the JAR plugin produces one JAR per JPMS module as attached artifacts and never assigns a file to the main artifact — the deploy plugin then fails with "is a folder"
  • Auto-detects this case by checking ProjectManager.getSourceRoots() for any enabled SourceRoot with module().isPresent(), and removes the main artifact from the deploy request
  • Deploys only the POM and per-module JARs — no flag required, no user configuration needed

How it differs from #717

PR #717 requires allowIncompleteProjects=true — a flag whose name and semantics don't match the module source hierarchy use case. This PR auto-detects instead:

#717 This PR
Requires allowIncompleteProjects=true Yes No
Detection Generic (attached artifacts exist) Specific (enabled source roots declare modules)
Existing allowIncompleteProjects behavior Replaced Preserved unchanged

Context

This is the deploy-plugin counterpart of maven-install-plugin#468, using the same auto-detection approach.

This is a workaround for Maven 4.0 (API is frozen). The proper fix is tracked in apache/maven#13396 — a Packaging.producesMainArtifact() API for Maven 4.1.0 that would let the JAR plugin explicitly signal "no main artifact", eliminating the need for detection in the deploy plugin.

Test plan

  • New test moduleSourceHierarchySkipsMainArtifactAtDeploy — sets up enabled source roots with a module, attaches a module JAR, sets main artifact path to a directory, verifies only POM + module JAR are deployed
  • All 50 existing tests pass unchanged

When a project uses module source hierarchy (<source><module>…), the
JAR plugin produces one JAR per JPMS module as attached artifacts and
never assigns a file to the main artifact — the deploy plugin then
fails because the main artifact path is a directory.

Auto-detect this case by checking whether any enabled source root
declares a module (via ProjectManager.getSourceRoots() /
SourceRoot.module()), and skip the main artifact from the deploy
request — deploying only the POM and the per-module JARs.

The existing allowIncompleteProjects fallback is preserved unchanged
for unrelated incomplete-project scenarios.

This is a workaround for Maven 4.0. The proper fix is tracked in
apache/maven#13396 (Packaging.producesMainArtifact() API for 4.1.0).

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

The allowIncompleteProjects branch (lines 455-461) warns and continues, but does not call toDeploy.remove(deployable) — unlike the adjacent usesModuleSourceHierarchy branch (line 454) which does.

Since toDeploy (not the original deployables list) is now passed to the deployer, an artifact with no valid file will still be included when allowIncompleteProjects is true. This is likely to cause a deployer-level failure at deploy time — the same outcome the warn-and-continue path is supposed to avoid.

Consider adding toDeploy.remove(deployable) in this branch as well, mirroring the pattern used in the usesModuleSourceHierarchy case.


This review was generated by an AI agent, Hermès on behalf of @gnodet.

Comment thread src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java Outdated
…arning

Two issues in the allowIncompleteProjects branch:
- The main artifact was not removed from toDeploy, causing the deployer
  to receive a directory path and fail — defeating the purpose of the
  warn-and-continue path
- The warning was split across multiple getLog().warn() calls; consolidate
  into a single call matching the install plugin style

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ The two issues flagged in the prior review are now fully addressed:

  • toDeploy.remove(deployable) is correctly called in the allowIncompleteProjects branch (commit fadc353), matching the usesModuleSourceHierarchy branch behavior — artifacts with a directory path are no longer sent to the deployer
  • The warning is consolidated into a single getLog().warn() call, consistent with the install plugin style

The auto-detection via SourceRoot.module().isPresent() is the right signal, the iteration-safety approach (mutable copy of deployables with the original iterated separately) is correct, and the test exercises the critical path end-to-end. Clean, well-scoped workaround for Maven 4.0 module source hierarchy deploy failures. 👍

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ Re-review after fadc353 — APPROVE

The prior finding (missing toDeploy.remove(deployable) in the allowIncompleteProjects branch) is fully addressed in commit fadc353. All other findings verified as non-issues.

Clean, well-scoped workaround for Maven 4.0 module source hierarchy deploy failures. The logic correctly handles the three cases:

  • Module source hierarchy detected → skip main artifact from deploy
  • allowIncompleteProjects=true → warn and skip (pre-existing lenient path)
  • Otherwise → throw MojoException (correct strictness)

This review was generated by an AI agent, Hermès on behalf of @gnodet.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants