Publishing Plugins to the Gradle Plugin Portal
Publishing your plugin is the primary way to make it available to other builds. While you can publish to private repositories to restrict access, publishing to the Gradle Plugin Portal makes your plugin discoverable and usable worldwide.
Account setup
Before publishing, create a Gradle Plugin Portal account and generate an API key:
-
Register at the Portal registration page.
-
Retrieve your API key from the “API Keys” tab in your profile.
You can also retrieve your API key using the login task when the plugin-publish plugin is applied.
|
Provide the credentials as Gradle properties (gradle.publish.key and gradle.publish.secret), usually in $HOME/.gradle/gradle.properties, or supply them via environment variables (GRADLE_PUBLISH_KEY and GRADLE_PUBLISH_SECRET), which is convenient for CI/CD.
Adding the Plugin Publish Plugin
Add the com.gradle.plugin-publish plugin to your build:
plugins {
id("com.gradle.plugin-publish") version "2.2.1"
}
plugins {
id 'com.gradle.plugin-publish' version '2.2.1'
}
The latest version is listed on the Gradle Plugin Portal.
| Since version 1.0.0, the Plugin Publish Plugin automatically applies the Java Gradle Plugin Development Plugin (for building plugins) and the Maven Publish Plugin (for generating metadata). Older versions required applying these plugins manually. |
Configuring the Plugin Publish Plugin
Configure the plugin in build.gradle(.kts):
group = "io.github.johndoe" (1)
version = "1.0" (2)
gradlePlugin { (3)
website = "<substitute your project website>" (4)
vcsUrl = "<uri to project source repository>" (5)
// ... (6)
}
group = 'io.github.johndoe' (1)
version = '1.0' (2)
gradlePlugin { (3)
website = '<substitute your project website>' (4)
vcsUrl = '<uri to project source repository>' (5)
// ... (6)
}
| 1 | Set group to identify your published artifacts. |
| 2 | Set version for the plugin release. |
| 3 | Use the gradlePlugin block to define plugin metadata. |
| 4 | Add your project website. |
| 5 | Add a source repository link. |
| 6 | Provide per-plugin details; see the next section. |
| The group and artifact must reasonably represent the organization, person, and the plugin. |
Define plugin-specific properties inside the gradlePlugin {} block:
gradlePlugin { (1)
// ... (2)
plugins { (3)
register("greetingsPlugin") { (4)
id = "<your plugin identifier>" (5)
displayName = "<short displayable name for plugin>" (6)
description = "<human-readable description of what your plugin is about>" (7)
tags = listOf("tags", "for", "your", "plugins") (8)
implementationClass = "<your plugin class>"
}
}
}
gradlePlugin { (1)
// ... (2)
plugins { (3)
register('greetingsPlugin') { (4)
id = '<your plugin identifier>' (5)
displayName = '<short displayable name for plugin>' (6)
description = '<human-readable description of what your plugin is about>' (7)
tags.set(['tags', 'for', 'your', 'plugins']) (8)
implementationClass = '<your plugin class>'
}
}
}
| 1 | Plugin specific configuration also goes into the gradlePlugin block. |
| 2 | This is where we previously added global properties. |
| 3 | Each plugin you publish will have its own block inside plugins. |
| 4 | The name of a plugin block must be unique for each plugin you publish; this is a property used only locally by your build and will not be part of the publication. |
| 5 | Set the unique id of the plugin, as it will be identified in the publication. |
| 6 | Set the plugin name in human-readable form. |
| 7 | Set a description to be displayed on the portal. It provides useful information to people who want to use your plugin. |
| 8 | Specifies the categories your plugin covers. It makes the plugin more likely to be discovered by people needing its functionality. |
For example, take a look at the configuration for the GradleTest plugin:
gradlePlugin {
website = "https://github.com/ysb33r/gradleTest"
vcsUrl = "https://github.com/ysb33r/gradleTest.git"
plugins {
register("gradletestPlugin") {
id = "org.ysb33r.gradletest"
displayName = "Plugin for compatibility testing of Gradle plugins"
description = "A plugin that helps you test your plugin against a variety of Gradle versions"
tags = listOf("testing", "integrationTesting", "compatibility")
implementationClass = "org.ysb33r.gradle.gradletest.GradleTestPlugin"
}
}
}
gradlePlugin {
website = 'https://github.com/ysb33r/gradleTest'
vcsUrl = 'https://github.com/ysb33r/gradleTest.git'
plugins {
register('gradletestPlugin') {
id = 'org.ysb33r.gradletest'
displayName = 'Plugin for compatibility testing of Gradle plugins'
description = 'A plugin that helps you test your plugin against a variety of Gradle versions'
tags.addAll('testing', 'integrationTesting', 'compatibility')
implementationClass = 'org.ysb33r.gradle.gradletest.GradleTestPlugin'
}
}
}
Sources and Javadoc
The Plugin Publish Plugin automatically creates and publishes Javadoc and sources JARs.
Signing artifacts
From version 1.0.0, applying the signing plugin automatically signs plugin artifacts.
Shadow dependencies
From version 1.0.0, applying com.gradleup.shadow automatically creates fat JARs for plugins.
Declaring compatibility with Gradle features
The Gradle Plugin Portal highlights plugins that declare support for opt-in Gradle features with compatibility badges and more. Users are often hesitant to enable a feature like Configuration Cache or Isolated Projects when they can’t tell whether their plugins support it. Declaring compatibility removes that uncertainty, making your plugin more discoverable and boosting its ranking in Portal search results.
| Declaring compatibility with Isolated Projects requires Plugin Publish Plugin v2.2.1 or later. There is currently no IP-compatible badge available. |
Add a compatibility block to each plugin declaration inside gradlePlugin { plugins { … } }:
// Kotlin DSL requires importing the extension
import org.gradle.plugin.compatibility.compatibility
plugins {
id("com.gradle.plugin-publish") version "2.2.1"
}
group = "io.github.johndoe"
version = "1.0"
gradlePlugin {
website = "https://github.com/johndoe/greetings"
vcsUrl = "https://github.com/johndoe/greetings.git"
plugins {
create("greetingsPlugin") {
id = "io.github.johndoe.greeting"
implementationClass = "example.GreetingPlugin"
displayName = "Gradle Greeting plugin"
description = "Gradle plugin to say hello!"
tags = listOf("hello", "greeting")
compatibility {
features {
configurationCache = true
isolatedProjects = true
}
}
}
}
}
plugins {
id 'com.gradle.plugin-publish' version '2.2.1'
}
group = 'io.github.johndoe'
version = '1.0'
gradlePlugin {
website = 'https://github.com/johndoe/greetings'
vcsUrl = 'https://github.com/johndoe/greetings.git'
plugins {
greetingsPlugin {
id = 'io.github.johndoe.greeting'
implementationClass = 'example.GreetingPlugin'
displayName = 'Gradle Greeting plugin'
description = 'Gradle plugin to say hello!'
tags.set(['hello', 'greeting'])
// Groovy DSL requires passing `it` as the receiver
compatibility(it) {
features {
configurationCache = true
isolatedProjects = true
}
}
}
}
}
Set each feature to true to declare support or false to declare that the plugin does not support the feature.
Declaring a feature as unsupported is useful information for your users; there is no penalty for doing so.
|
Publishing a plugin without a compatibility declaration is deprecated as of Plugin Publish Plugin v2.1.0 and produces a deprecation warning during publish. The Gradle Plugin Portal plans to reject undeclared submissions in a future version, so declaring compatibility now future-proofs your publish pipeline. |
Once a feature is declared for a plugin, subsequent versions of that plugin must continue to declare it. Attempting to remove a compatibility declaration in a later version causes the publish request to fail.
Publishing the plugin
To validate a Plugin Portal publication (no upload):
$ ./gradlew publishPlugins --validate-only
To publish to the Gradle Plugin Portal:
$ ./gradlew publishPlugins
You can also pass credentials on the command line:
$ ./gradlew publishPlugins -Pgradle.publish.key=<key> -Pgradle.publish.secret=<secret>
Your plugin will then go through the approval process. This process can take a few days.
After approval, your plugin appears on the Portal and is available for anyone to use.
Plugins published without Gradle Plugin Portal
If you published a plugin without using the Java Gradle Plugin Development Plugin, the publication will lack the Plugin Marker Artifact required by the plugins DSL.
To use such a plugin, add a resolutionStrategy block inside pluginManagement {} in the consuming project’s settings.gradle(.kts):
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == "org.example") {
useModule("org.example:custom-plugin:${requested.version}")
}
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'org.example') {
useModule("org.example:custom-plugin:${requested.version}")
}
}
}