Applying a plugin version inside a convention plugin

I would like to know how to have a convention plugin that applies some other plugins but I’m having a really hard time finding information about this online.

I have a multi module gradle setup and I have two gradle projects that both apply the kotlin plugin in their build script like this

// app1/build.gradle.kts and app2/build.gradle.kts
plugins {
  base
  java
  idea
  id("org.jetbrains.kotlin.jvm") as "1.6.10"
}
// Then some supporting implementation statements with supporting dependencies like kotlin-stdlib-jdk8 and kotlin-reflect

I would like to consolidate this logic into my convention plugin that is defined in buildSrc, however I am struggling to figure out how to do this. If I move the plugin definition into my buildSrc/src/main/kotlin/my-common-conventions.gradle.kts exactly as-is I get an error message that having the version defined in the convention plugin isn’t allowed. Invalid plugin request [id: 'org.jetbrains.kotlin.jvm', version: '1.6.10']. Plugin requests from precompiled scripts must not include a version number. Please remove the version from the offending request and make sure the module containing the requested plugin 'org.jetbrains.kotlin.jvm' is an implementation dependency of project ':buildSrc'. So I can remove the version number from the kotlin plugin and the it builds okay.

However, I want to know how I can pin the plugin definition to a specific version, and more than that I would like to know the best practice. I know that regular dependencies defined in the depenendencies block with implementation/api are included in the convention plugin, even when versions are specified. But somehow plugin versions in the convention plugin’s plugin block are different. How can we use a common configuration across projects that implements a plugin’s version number?

I had to do this exact thing.

buildSrc/build.gradle.kts needs to have the Maven dependencies of the plugins instead of the ID:

plugins {
    `kotlin-dsl`
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
}

// Not sure if this is necessary or not
// Add it if it is not able to find the dependencies
repositories {
    gradlePluginPortal()
}

Then in your convention plugin, you just omit the version.

You can find the correct Maven dependency in the legacy section of the plugin page:

https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm

An easier variant without needing to look up the artifact coordinates is to use the marker artifact.
implementation("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.10").
It is always <plugin id>:<plugin id>.gradle.plugin:<version>.

2 Likes

@Vampire Wow! I was totally unaware of that. That is fantastic. Looks like that is documented here:

https://docs.gradle.org/current/userguide/plugins.html

2 Likes

Thanks for the help guys!