Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maven-publish: generated pom misses version for compileOnlyApi dependency when it is managed with a platform #25712

Closed
vlsi opened this issue Jul 11, 2023 · 10 comments
Labels
closed:question usage question or request for help

Comments

@vlsi
Copy link
Contributor

vlsi commented Jul 11, 2023

Expected Behavior

Gradle resolves compileOnlyApi dependency, so it should use the same version for the generated pom.xml.

Current Behavior

Currently, Gradle produces pom.xml without a version which triggers issues with Maven: #25705

Context (optional)

Steps to Reproduce

// settings.gradle.kts
rootProject.name = "gradle-issue-23268"

include("platform")
// build.gradle.kts
plugins {
    id("java-library")
    id("maven-publish")
}

repositories {
    mavenCentral()
}

project(":platform") {
    apply(plugin = "java-platform")
    // Follows https://docs.gradle.org/current/userguide/java_platform_plugin.html#ex-recommend-versions-in-a-platform-module
    dependencies {
        constraints {
            api("com.google.auto.service:auto-service-annotations:1.1.1")
        }
    }
}

dependencies {
    compileOnlyApi("com.google.auto.service:auto-service-annotations")
    // Follows https://docs.gradle.org/current/userguide/java_platform_plugin.html#ex-get-recommendations-from-a-platform
    api(platform(project(":platform")))
}

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["java"])
        }
    }
}

Test case: ./gradlew generatePomFileForMavenJavaPublication && cat build/publications/mavenJava/pom-default.xml

Actual output. The issue is that <version> is missing.

  <dependencies>
    <dependency>
      <groupId>com.google.auto.service</groupId>
      <artifactId>auto-service-annotations</artifactId>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

Gradle version

8.2.1

Build scan URL (optional)

https://gradle.com/s/xvtzfxb7oy75y

Your Environment (optional)

No response

@ov7a
Copy link
Member

ov7a commented Jul 12, 2023

Thank you for your interest in Gradle!

This is the intended behavior, and there’s no plan to change it. This issue will be closed.


Gradle also generates a dependencyManagement entry which should be sufficient:

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>gradle-issue-23268</groupId>
        <artifactId>platform</artifactId>
        <version>unspecified</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

If maven has an issue with this kind of file, then you can instruct Gradle to publish resolved version as described here.

@ov7a ov7a closed this as not planned Won't fix, can't repro, duplicate, stale Jul 12, 2023
@ov7a ov7a added closed:not-fixed Indicates the issue was not fixed and is not planned to be and removed a:bug labels Jul 12, 2023
@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

@ov7a , could you please clarify why this is not going to be fixed?

If maven has an issue with this kind of file, then you can instruct Gradle to publish resolved version as described here.

It does not help.

plugins {
    id("java-library")
    id("maven-publish")
}

repositories {
    mavenCentral()
}

project(":platform") {
    apply(plugin = "java-platform")
    // Follows https://docs.gradle.org/current/userguide/java_platform_plugin.html#ex-recommend-versions-in-a-platform-module
    dependencies {
        constraints {
            api("com.google.auto.service:auto-service-annotations:1.1.1")
        }
    }
}

dependencies {
    compileOnlyApi("com.google.auto.service:auto-service-annotations")
    // Follows https://docs.gradle.org/current/userguide/java_platform_plugin.html#ex-get-recommendations-from-a-platform
    api(platform(project(":platform")))
}

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["java"])
            versionMapping {
                usage("java-api") {
                    fromResolutionOf("runtimeClasspath")
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }
        }
    }
}

yields

  <dependencies>
    <dependency>
      <groupId>com.google.auto.service</groupId>
      <artifactId>auto-service-annotations</artifactId>
      <scope>compile</scope>
    </dependency>
  </dependencies>

In other words, auto-service-annotations goes without a version.

@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

Interestingly, the following two options result in resolved versions:

                usage("java-api") {
                    fromResolutionOf("compileClasspath")
                }

or

                usage("java-api") {
                    fromResolutionResult()
                }

So the culprit is:

  1. Users blindly copy-paste fromResolutionOf("compileClasspath") from the documentation. I have exactly the same in JMeter, and I thought it would resolve "the same versions as in runtime"
  2. Documentation does not mention what happens to the dependencies that are present on the compile classpath yet they are not present on the runtime classpath

It would probably be better to suggest a workable workaround in the documentation rather than something that creates invalid pom files.

What do you think of

            versionMapping {
                usage("java-api") {
                    fromResolutionResult()
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }

...

java {
    consistentResolution {
        useRuntimeClasspathVersions()
    }
}

@ov7a
Copy link
Member

ov7a commented Jul 12, 2023

@vlsi sounds reasonable. I'll reopen it as a documentation issue then.

@ov7a ov7a reopened this Jul 12, 2023
@ov7a ov7a added in:publishing-plugins ivy-publish maven-publish a:documentation Documentation content and removed closed:not-fixed Indicates the issue was not fixed and is not planned to be labels Jul 12, 2023
@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

My initial thought was like "I have fromResolutionOf("runtimeClasspath"), so I could drop <dependencyManagement> from the generated poms".
Apparently, that was a bad move.

@jvandort
Copy link
Member

To be honest, I'm surprised auto-service-annotations appears in the POM at all. I feel like the real bug here is that we are publishing this dependency. compileOnlyApi can't really be mapped to maven, as our two options for scopes are compile and runtime, both of which are placed on the runtime classpath of maven projects.

@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

@jvandort , @AutoService has @Retention(CLASS), so the annotation will be visible to the consumer's compiler. Of course, Java language specification says compilers should ignore "unknown" annotations, however, there were known cases when the compilers were failing. So the current best practice (e.g. Guava) is to include annotations into "compile" scope, that is why I expose it, and I expect that compileOnlyApi would be mapped to <scope>compile</scope> which is exactly what Gradle does.

However, now I would try a different approach: I keep the generated <dependencyManagement>, and I would probably drop versionMapping { ... fromResolutionResult...}. Basic checks show it produces workable pom files, however, I wonder how many clients would break as they would find the version numbers have moved from leaf poms to the boms.

@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

@ov7a , after a bit of thought, I think useRuntimeClasspathVersions is a yet another dimension, and generally speaking, people might want compiling against "older API versions" and test with "never APIs". So the generic recommendation should
probably be useCompileClasspathVersions rather than useRuntime....

So the sole fix here is to avoid the sample usage("java-api") { fromResolutionOf("compileClasspath") } in the documentation as it would leave compileOnlyApi unresolved which is surprising for those who configured fromResolutionOf....
In other words, make the sample like "imagine you want to have 'resolved' versions in the generated pom, then you could use the following".

The case for using fromResolutionOf(String) is probably a different one, and it is probably to be added as a separate example with its own justification.

@vlsi vlsi changed the title maven-publish: generated pom misses version for compileOnlyApi dependency when it is managed with a platform maven-publish: avoid recommending usage("java-api") { fromResolutionOf("compileClasspath") } in the documentation as it does not support compileOnlyApi Jul 12, 2023
@vlsi vlsi changed the title maven-publish: avoid recommending usage("java-api") { fromResolutionOf("compileClasspath") } in the documentation as it does not support compileOnlyApi maven-publish: generated pom misses version for compileOnlyApi dependency when it is managed with a platform Jul 12, 2023
@vlsi
Copy link
Contributor Author

vlsi commented Jul 12, 2023

@ov7a , I am closing the issue as the one with the original title is not really valid. A note for the readers: Gradle generates both "versionless dependency and dependencyManagement / import", and Maven is able to resolve that pom without issues.

At the same time, I think converting the discussion into "update documentation for maven-publish" would be confusing for everybody else, so I would rather open another issue for documentation purposes.

@ov7a
Copy link
Member

ov7a commented Jul 13, 2023

@vlsi ok, thank you!

@ov7a ov7a closed this as not planned Won't fix, can't repro, duplicate, stale Jul 13, 2023
@ov7a ov7a removed in:publishing-plugins ivy-publish maven-publish a:documentation Documentation content labels Jul 13, 2023
@ov7a ov7a added closed:question usage question or request for help and removed to-triage labels Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed:question usage question or request for help
Projects
None yet
Development

No branches or pull requests

4 participants
@vlsi @jvandort @ov7a and others