ascheman opened a new issue, #12770:
URL: https://github.com/apache/maven/issues/12770

   
   ### Summary
   
   When a plugin has no version anywhere in the effective model, Maven 4 
resolves it from the
   repository's `RELEASE` metadata. In Maven's version semantics a 
`4.0.0-beta-N` **is** a release
   (it is not a `SNAPSHOT`), so Maven 4 selects a pre-release plugin that was 
compiled against an
   unstable Maven 4 API — and the build dies with a linkage error.
   
   Maven 3 does not have this problem: it runs a plugin compatibility check, 
rejects the
   incompatible version and falls back to the newest usable one.
   
   ### Reproducer
   
   Minimal showcase with CI: 
https://github.com/aschemaven/maven4-unversioned-plugin-pick
   
   Three files: a POM with no parent, no `<build>`, no `<pluginManagement>` and 
no plugin version
   anywhere, one trivial class, and a workflow running the *same* command on 
three setups.
   
   ```bash
   mvn source:jar        # nothing pinned anywhere
   ```
   
   `maven-source-plugin` is not part of any lifecycle binding, so the version 
has to come from
   metadata. Central currently publishes:
   
   ```xml
   <latest>4.0.0-beta-1</latest>
   <release>4.0.0-beta-1</release>
   ```
   
   **Apache Maven 4.0.0-rc-6** (`6a8189b24518daa120539fa41ce12f2b48ec09a8`), 
JDK 17, empty local
   repository:
   
   ```
   [INFO] --- source:4.0.0-beta-1:jar (default-cli) @ unversioned-plugin-pick 
---
   [ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar
           (default-cli) on project unversioned-plugin-pick: Execution 
default-cli of goal
           org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar failed:
           An API incompatibility was encountered while executing
           org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1:jar:
           java.lang.NoSuchMethodError: 'java.util.List
           org.apache.maven.api.services.ProjectManager.getCompileSourceRoots(
           org.apache.maven.api.Project, org.apache.maven.api.ProjectScope)'
   ```
   
   **Apache Maven 3.9.16** and **3.10.0-rc-1**, same project, same command, 
same JDK:
   
   ```
   [WARNING] Ignoring incompatible plugin version 4.0.0-beta-1:
             The plugin 
org.apache.maven.plugins:maven-source-plugin:4.0.0-beta-1
             has unmet prerequisites:
   [INFO] Latest version of plugin org.apache.maven.plugins:maven-source-plugin 
failed compatibility check
   [INFO] Looking for compatible RELEASE version of plugin 
org.apache.maven.plugins:maven-source-plugin
   [INFO] Selected plugin org.apache.maven.plugins:maven-source-plugin:3.4.0
   [INFO] BUILD SUCCESS
   ```
   
   Maven 3 only escapes *this* case by accident. The beta declares Maven 4 
prerequisites, so the
   compatibility check rejects it. The version selection itself ignores 
pre-release qualifiers on
   every line: with a plugin whose pre-release *is* compatible (staged 
repository, stable `1.0` and
   pre-release `2.0-beta-1`, metadata naming `2.0-beta-1` as `<release>`), 
**3.9.16 and 4.0.0-rc-6
   both select `2.0-beta-1`**. That is the staged scenario of the integration 
test below.
   
   The CI workflow encodes exactly this contrast — `unversioned` green on 
3.9.16 and 3.10.0-rc-1, **red** on 4.0.0-rc-6,
   `pinned-workaround` green — and runs weekly, so it keeps reflecting whatever 
Central currently
   calls `RELEASE`.
   
   ### Why this is worth fixing rather than waiting it out
   
   The symptom disappears once a stable `maven-source-plugin` 4.x is released, 
but the mechanism
   stays: any plugin whose newest published version is a pre-release becomes a 
trap for every
   build that does not pin. Two changes made this more likely than it used to 
be:
   
   1. The Maven 3 super POM pinned four commonly CLI-invoked plugins in 
`pluginManagement`
      (`maven-antrun-plugin`, `maven-assembly-plugin`, 
`maven-dependency-plugin`,
      `maven-release-plugin`). Maven 3.10 and 4.x dropped that block, so more 
plugins now fall
      through to `RELEASE` resolution.
   2. The compatibility fallback that saves the Maven 3 run is not a guard 
against pre-releases —
      it only checks the plugin's declared prerequisites. Under Maven 4 the 
beta's prerequisites are
      formally satisfied (it *is* Maven 4), so nothing catches the API break 
and the user gets a raw
      `NoSuchMethodError` naming an internal API method, with no hint that a 
version selection
      caused it.
   
   ### Fix
   
   Branches (fork, ready to become PRs — `https://github.com/aschemaven/maven`):
   
   * `bugfix/unversioned-plugin-prerelease` — off `master` (4.1)
   * `backport/40x-unversioned-plugin-prerelease` — off `maven-4.0.x`
   
   `DefaultPluginVersionResolver` is byte-identical on both lines, so the 
change cherry-picks cleanly.
   
   What it does: when a plugin has no declared version, prefer a version 
*without* a pre-release
   qualifier whenever the repository offers one; fall back to pre-releases, 
then snapshots, so a
   plugin that has only ever published pre-releases still resolves.
   
   A pre-release is recognised through the version scheme itself rather than a 
list of qualifier
   names: such a qualifier sorts *before* the version it qualifies (`1.0-beta-1 
< 1.0`), while a
   build or vendor qualifier does not (`1.0-jre > 1.0`).
   
   Alternatives that were considered and are *not* in the patch, but may be 
worth having as well:
   
   1. Report a comprehensible failure when an auto-selected plugin throws
      `NoSuchMethodError`/`NoClassDefFoundError` against 
`org.apache.maven.api.*` — name the version
      selection as the likely cause instead of surfacing the linkage error 
alone.
   2. Re-introduce super POM `pluginManagement` pins for the handful of plugins 
commonly invoked from
      the CLI without a version (Maven 3.10 and 4.x dropped the block that 
Maven 3.9 still has).
   
   ### Integration test
   
   `MavenITghUnversionedPluginPrereleaseTest` + 
`its/core-it-suite/src/test/resources/gh-unversioned-plugin-prerelease/`.
   
   It does not depend on live Central metadata: the test stages its own plugin 
repository offering a
   stable `1.0` and a pre-release `2.0-beta-1`, with 
`<release>2.0-beta-1</release>` in the metadata —
   the same shape Central has today for `maven-source-plugin`. The project 
declares the plugin without
   a version and the test asserts the marker file written by `1.0`.
   
   Verified:
   
   | distribution | result |
   |---|---|
   | `master` + fix | IT passes; full core IT suite green (1052 tests, 0 
failures) |
   | `master` without fix | IT fails: `Expected file was not found: 
target/touch-stable.txt` (the beta ran) |
   | `maven-4.0.x` + fix | see the backport branch |
   
   The IT class and resource directory are named after this issue once it has a 
number.
   


-- 
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]

Reply via email to