How do I publish my plugin to the Plugin Portal using version 1.0+?
NOTE: If you are using an older (0.X) version of the plugin, please switch to the older version of this page.
NOTE: If you are using version 1.0.X of the plugin, please update to at least version 1.1.0, which contains critical bug fixes.
NOTE: If you have previously published Gradle plugins via Bintray, please read this information.
NOTE: Before publishing a plugin, make sure you agree to the Terms of Use.
Portal Setup
Create an account.
You can quickly and easily create a new account via the registration page.
You can use the same account to publish as many plugins as you like.
Create an API key.
Once logged in, you can get your API key via the “API Keys” tab of your profile page.
You can use the same API key to publish as many plugins as you like.
Local Setup
Once you've created an API key, the “API Keys” tab of your profile page will provide a snippet that you can copy & paste into your Gradle user properties file.
The default location for the Gradle user properties file is
$USER_HOME/.gradle/gradle.properties
,
where $USER_HOME
refers to your user home directory.
NOTE: There is also an experimental task, “login“, that is part of the plugin publishing plugin, which automates this step.
Alternatively, you can provide the API key via GRADLE_PUBLISH_KEY
and GRADLE_PUBLISH_SECRET
environment variables.
This approach might be useful for CI/CD pipelines.
Publication
The Plugin Publishing plugin provides tasks that upload your plugin to the Plugin Portal. It can also be used to publish updated versions of your plugin. This plugin is not part of the Gradle distribution but is itself hosted on the Plugin Portal.
Once configured, your plugin can be published by simply running the publishPlugins
task of your plugin's build.
Detailed instructions can be found in the Gradle docs for plugin publishing.
Take care to select the version matching the actual Gradle version you are using, but not older than v7.6 (that is
the version when the manual starts focusing on more modern versions of the plugin, ie. 1.0 or higher).
Helper plugins
Plugin Development plugin
Starting with version 1.0.0, the Plugin Development plugin becomes a mandatory component of the Plugin Publish plugin and is automatically applied with it. Further info on how it interacts with the Maven Publish plugin (also auto-applied by the Plugin Publish plugin) can be found here.
Maven Publish plugin
Starting with Plugin Publish plugin v1.0.0 the only
supported way of generating the publication metadata (think Maven GAV coordinates, i.e. group, artifact, version)
for Gradle plugins is via the Maven Publish plugin.
In fact, the maven-publish
plugin is auto-applied when applying plugin-publish
.
The simultaneous presence of the Maven Publish and Plugin Development plugins, both auto-applied, triggers the configuration of specific Maven publications which will be published to the Plugin Portal. More information on it can be found here.
Signing plugin
Starting with version 1.0.0 the Plugin Publish plugin can automatically sign the artifacts it publishes to the Portal. All artifact included in the main & marker Maven publications will be included, not just jars, POMs & Gradle Module Metadata files. This functionality is turned on by simply applying the Signing plugin.
Shadow plugin
Starting with version 1.0.0 the Plugin Publish plugin can automatically
interact with the com.github.johnrengelman.shadow plugin, if applied.
It will automatically publish the jar produced by the shadowJar
task, as the main artifact. Note that this interaction
requires the usage of Gradle v6.0.1 or later, in order to work properly.
Breaking changes
Starting from version 1.0.0, the Plugin Publish plugin is only compatible with Gradle 4.10.3 or later (due to relying on maven publication).
Making the Maven Publish plugin mandatory triggers the following API changes:
- The
mavenCoordinates
block is no longer defined and can’t be used to override publication GAV coordinates. The coordinates are always based on the Maven publication’s GAV (which defaults to theProject
’s group, name & version). - The
withDependencies
block is no longer defined; all dependencies come from the Java component and how we define dependencies for Java libraries.
Examples
Plugin Publish plugin v1.0.0 simplifies the configuration of
plugin publishing by merging the pluginBundle
block into the gradlePlugin
one.
These simplifications however require backing support in the Gradle API, so are only available when using the Plugin Publish Plugin with Gradle v7.6 or later.
build.gradle.kts
// First, apply the publishing plugin
plugins {
// Apply the Plugin Publish plugin to make plugin publication possible
// The Plugin Publish plugin will in turn auto-apply the Gradle Plugin Development Plugin (java-gradle-plugin)
// and the Maven Publish plugin (maven-publish)
id("com.gradle.plugin-publish") version "1.3.0"
// Apply the signing plugin (signing) if you want the published artifacts of your plugin be automatically signed.
// Apply the shadow plugin (com.github.johnrengelman.shadow) if you want to automatically make the main jar
// of your plugin be a fat one, shadowing its dependencies.
// Apply more plugins, if needed, for example the kotlin plugin for a plugin written in Kotlin
// or the groovy plugin if the plugin uses Groovy.
}
// If your plugin has any external dependencies, users might need to declare repositories in their
// build settings so that Gradle can download them when using the plugins DSL.
repositories {
mavenCentral()
}
// The project version will be used as your plugin version when publishing.
version = "1.2"
group = "io.github.johndoe"
// Use java-gradle-plugin to generate plugin descriptors and specify both global and individual plugin properties.
// The names of the blocks inside "plugins" need to be unique, they will identify the plugins being configured.
// All properties are mandatory.
gradlePlugin {
website.set("https://github.com/johndoe/GradlePlugins")
vcsUrl.set("https://github.com/johndoe/GradlePlugins")
plugins {
create("greetingsPlugin") {
id = "io.github.johndoe.greeting"
implementationClass = "io.github.johndoe.gradle.GreetingPlugin"
displayName = "Gradle Greeting plugin"
description = "Gradle plugin to say hello!"
tags.set(listOf("search", "tags", "for", "your", "hello", "plugin"))
}
create("goodbyePlugin") {
id = "io.github.johndoe.goodbye"
implementationClass = "io.github.johndoe.gradle.GoodbyePlugin"
displayName = "Gradle Goodbye plugin"
description = "Gradle plugin to say goodbye!"
tags.set(listOf("search", "tags", "for", "your", "goodbye", "plugin"))
}
}
}
build.gradle
// First, apply the publishing plugin
plugins {
// Apply the Plugin Publish plugin to make plugin publication possible.
// The Plugin Publish plugin will in turn auto-apply the Gradle Plugin Development Plugin (java-gradle-plugin)
// and the Maven Publish plugin (maven-publish).
id 'com.gradle.plugin-publish' version '1.3.0'
// Apply the signing plugin (signing) if you want the published artifacts of your plugin be automatically signed.
// Apply the shadow plugin (com.github.johnrengelman.shadow) if you want to automatically make the main jar
// of your plugin be a fat one, shadowing its dependencies.
// Apply more plugins, if needed, for example the kotlin plugin for a plugin written in Kotlin
// or the groovy plugin if the plugin uses Groovy.
}
// If your plugin has any external dependencies, users might need to declare repositories in their
// build settings so that Gradle can download them when using the plugins DSL.
repositories {
mavenCentral()
}
// The project version will be used as your plugin version when publishing.
version = '1.2'
group = 'io.github.johndoe'
// Use java-gradle-plugin to generate plugin descriptors and specify both global and individual plugin properties.
// The names of the blocks inside 'plugins' need to be unique, they will identify the plugins being configured.
// All properties are mandatory.
gradlePlugin {
website = 'https://github.com/johndoe/GradlePlugins'
vcsUrl = 'https://github.com/johndoe/GradlePlugins'
plugins {
greetingsPlugin {
id = 'io.github.johndoe.greeting'
implementationClass = 'io.github.johndoe.gradle.GreetingPlugin'
displayName = 'Gradle Greeting plugin'
description = 'Gradle plugin to say hello!'
tags.set(['search', 'tags', 'for', 'your', 'hello', 'plugin'])
}
goodbyePlugin {
id = 'io.github.johndoe.goodbye'
implementationClass = 'io.github.johndoe.gradle.GoodbyePlugin'
displayName = 'Gradle Goodbye plugin'
description = 'Gradle plugin to say goodbye!'
tags.set(['search', 'tags', 'for', 'your', 'goodby', 'plugin'])
}
}
}
Approval
When a new plugin is published it will go through a manual review process. This usually happens only for the initial version. The plugin publishing plugin will tell you if your plugin is pending acceptance when you publish.
NOTE: Any change of Maven group or plugin ID will cause the manual approval process to be triggered again.
A Gradle engineer will inspect the metadata and decide whether to make it visible on the Portal or request changes to it. If your plugin requires changes before it can be accepted, you will be contacted via the email address associated with your account. You will also receive an email when your plugin is accepted.
All plugins must adhere to the following rules:
Plugins must have some functionality
"Hello world" type submissions, or any other plugin not having some minimal useful functionality will be rejected.
Plugins should be useful to a wide audience
Plugins that are too specific to a particular use case or company will be rejected. Consider publishing it to a private Maven or Ivy repository if that is the case.
Plugins should be documented
There should be a description
specifying the intent of the plugin.
Tags
should be set to describe the categories the plugin covers.
The project URL
should point to the documentation in English, to the project sources, or both.
The VCL URL
should point to the plugin sources.
Plugins should ideally be open-source, unless there is a good reason to do otherwise.
Proprietary plugin authors should reach out to us.
Plugin IDs should trace back to the author
The group and artifact must reasonably represent the organization, person, and the plugin.
If a GitHub user johndoe
publishes a plugin called myplugin
, then an acceptable plugin ID would be io.github.johndoe.myplugin
.
If it contains dashes, they should be used as is, e.g. io.github.john-doe.myplugin
.
Note that while plugin ID and group ID should have the dashes, the package name should contain underscores instead, according to Java Language Specification.
NOTE: com.github
is no longer accepted as a prefix, in order to align with the
Maven Central policy.
Another example would be a corporate plugin, let's say from mybusiness.com
; then the plugin ID should look like com.mybusiness.pluginname
.
In this case, the author should also submit the plugin via a corporate account/email address.
We prefer group (as opposed to individual) addresses, to highlight that the organization (or a sub-group of it) is the owner of the plugin.
We will ask for proof of the domain ownership in the form of a TXT record added to the DNS entry.
The plugin ID and group ID should share the same top-level namespace
We require plugins to have a shared prefix in their ID and group coordinate.
Only final versions should be published
We will reject SNAPSHOT versions because it's not possible to override them anyways.
Plugins should be published from non-forked repositories
There shouldn't be multiple variants of the same plugin published on the Portal. Plugin developers should try to work with the original author(s) to get their changes/improvements integrated. Some exceptions are acceptable, for example, when the original repository is abandoned, and it doesn't accept contributions.
Plugins should comply with the Gradle Code of Conduct
Please refer to our CoC.
Troubleshooting
Publication Failed
The problems described here happen during plugin publication and usually lead to the failure of the publication process.
The GitHub group ID prefix can't be com.github
Github has introduced a new, dedicated domain (github.io
) for it’s Pages service,
back in 2013 (see here).
This year they have stopped automatically forwarding from the old, legacy domain (github.com
)
to this new one.
Maven Central has then announced that they will react to this and that they will no longer allow
com.github
as a valid group ID prefix (see here).
The Gradle Plugin Portal has also adopted this convention, so please use the io.github
prefix in your plugin configurations.
Plugin version can't be SNAPSHOT
The Plugin Portal doesn't allow plugins to be published with versions ending in
SNAPSHOT
, because they wouldn't behave as expected. All versions are considered
fixed, so re-publishing of the same version wouldn't be possible, thus the whole concept of
snapshots would be meaningless.
Please use fixed versions instead.
Approval Denied
The problems described here happen after the successful publication of the first version of a plugin, if the plugin gets flagged for manual approval by the Portal administrators, and they reject the plugin for various reasons. They will send you an email with the reasons for the rejection.
Ownership can't be established
One typical scenario of this problem is when a plugin gets published from a GitHub (or similar) repository, but the GitHub account can't be linked to the Plugin Portal account doing the publishing. The solution to this is to either use a Plugin Portal account linked to a GitHub account (you can log into the Plugin Portal via your GitHub account).
Another typical scenario is when a plugin belonging to an organization is being published, but the publishing Plugin Portal account can't be linked to the organization. In such cases you might be asked to prove ownership of the organization's domain by adding some random TXT DNS record to your organization's domain host. Portal administrators will contact you and provide you with the exact record.
Plugin is based on a forked repository
Having multiple variants of the same plugin, published from forked, potentially diverging repositories could lead to a lot of confusion, so it's generally not encouraged. If you find yourself in this situation, we encourage you to submit your contributions as Pull Requests to the original repository.
The exception to this rule are abandoned repositories, where indeed forking and taking ownership is the only option.
Plugin is lacking public documentation
One typical situation when this problem arises is when the website or VCS URLs provided during plugin publication point to a broken or inaccessible destination. Another one is when the URLs point to, for example, a public GitHub repository, but there is no documentation there (empty README file) or none of it is in English.
The problem with the lack of documentation is that it makes the adoption of the plugin by the community very unlikely.
The solution to this problem is to either make the documentation publicly available, or, if your plugin is indeed private, consider publishing it to a private artifact repository.
You're done!
Your plugin is now part of the Gradle Plugin Portal and can be put to use by Gradle users all over the world.
Thank you for contributing.