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

Published pom leaks gradle-api dependency #89

Open
MarkRx opened this issue Oct 13, 2022 · 3 comments
Open

Published pom leaks gradle-api dependency #89

MarkRx opened this issue Oct 13, 2022 · 3 comments

Comments

@MarkRx
Copy link

MarkRx commented Oct 13, 2022

The generated pom & module files leak the gradle-api jar as a dependency when used in a compileOnly configuration. These should not be exported. This behavior differs from the java-gradle-plugin plugin.

Gradle: 6.9.2
Plugin: 1.6.8

build.gradle using dev.gradleplugins.java-gradle-plugin

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'dev.gradleplugins.java-gradle-plugin:dev.gradleplugins.java-gradle-plugin.gradle.plugin:1.6.8'
    }
}

group = 'com.myplugin'
version = '1.0.0'

apply plugin: 'dev.gradleplugins.java-gradle-plugin'
apply plugin: 'java'
apply plugin: 'maven-publish'


gradlePlugin {
    plugins {
        myPlugin {
            id = 'com.myplugin'
            implementationClass = 'com.myplugin.MyPlugin'
        }
    }
    compatibility {
        minimumGradleVersion = '4.10.3'
    }
}

dependencies {
    compileOnly gradleApi('4.10.3')
}

pom.xml using dev.gradleplugins.java-gradle-plugin

Observe how gradle-api is exported as a compile dependency. It should not be.

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!-- This module was also published with a richer model, Gradle metadata,  -->
  <!-- which should be used instead. Do not delete the following line which  -->
  <!-- is to indicate to Gradle or any Gradle module metadata file consumer  -->
  <!-- that they should prefer consuming it instead. -->
  <!-- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myplugin</groupId>
  <artifactId>gradle_testplugin</artifactId>
  <version>1.0.0</version>
  <dependencies>
    <dependency>
      <groupId>dev.gradleplugins</groupId>
      <artifactId>gradle-api</artifactId>
      <version>4.10.3</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

build.gradle using java-gradle-plugin

group = 'com.myplugin'
version = '1.0.0'

apply plugin: 'java-gradle-plugin'
apply plugin: 'java'
apply plugin: 'maven-publish'


gradlePlugin {
    plugins {
        myPlugin {
            id = 'com.myplugin'
            implementationClass = 'com.myplugin.MyPlugin'
        }
    }
}

dependencies {
    compileOnly gradleApi()
}

pom.xml using java-gradle-plugin

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!-- This module was also published with a richer model, Gradle metadata,  -->
  <!-- which should be used instead. Do not delete the following line which  -->
  <!-- is to indicate to Gradle or any Gradle module metadata file consumer  -->
  <!-- that they should prefer consuming it instead. -->
  <!-- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myplugin</groupId>
  <artifactId>gradle_testplugin</artifactId>
  <version>1.0.0</version>
</project>
@MarkRx
Copy link
Author

MarkRx commented Oct 13, 2022

This seems to be because the plugin adds the gradle-api dependency to the compileOnlyApi when using Gradle 6.7+ (see AddGradleApiDependencyToCompileOnlyApiConfiguration).

The compileOnlyApi configuration exports compile dependencies. The compileOnly configuration does not.

@lacasseio
Copy link
Member

I remember changing to compileOnlyApi because of the following logic, if someone depends on a plugin and builds against it, it should also use the same-ish Gradle API, given the plugin is highly opinionated to Gradle runtime. However, we could argue that this use case should be strictly confined to "plugin libraries", which is not a concept the Gradle team modelled. In theory, we depend on plugins for their API, which in turn uses Gradle APIs.

However, I think I see the problem. When the plugin is consumed, it will fetch dependencies of the compile scope from the plugin marker POM because that is how Gradle does it. Instead, we should keep the dependency on the module metadata (so straight consumers are happy) but remove the dependency from the plugin marker as it should be provided. Does that make sense?

I will add some tests to resolve only using the plugin marker and validate that we are pulling the Gradle API. Then, I will add configuration to the plugin marker.

One thing to note, there is no need to add compileOnly gradleApi(<minimum-gradle-version>). The plugin already adds the information under compileOnlyApi based on the minimumGradleVersion. You can force a specific API version by using gradleApiVersion (which is derived by default from minimumGradleVersion).

@MarkRx
Copy link
Author

MarkRx commented Jan 31, 2023

Here is a workaround:

publishing {
    publications {
        pluginMaven(MavenPublication) {
            // Workaround for https://github.com/gradle-plugins/toolbox/issues/89
            pom.withXml {
                def parent = asElement().getElementsByTagName("dependencies").item(0)
                def deps = parent.getElementsByTagName("dependency")
                def gradleApi = deps.find {
                    def groupId = it.getElementsByTagName("groupId").item(0).firstChild.nodeValue
                    def artifactId = it.getElementsByTagName("artifactId").item(0).firstChild.nodeValue
                    groupId.equals('dev.gradleplugins') && artifactId.equals('gradle-api')
                }
                parent.removeChild(gradleApi)
            }
        }
    }
}

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

No branches or pull requests

2 participants