How do I use the Plugin Publishing Plugin?

The ability to publish a Gradle plugin to the Plugin Portal is provided by the Gradle “Plugin Publishing” plugin. This plugin is not part of the Gradle distribution, but is available from the Plugin Portal.

Once configured, your plugin can be published by simply running the publishPlugins task of your plugin's build.

Please follow the submission instructions before using the plugin, in order to perform the necessary one-time configuration of your Gradle environment.

Acceptance rules

When new a plugin is published it will go through a manual review process. This usually happens only for the initial version. A Gradle engineer will inspect the metadata and decide whether to publish it to the portal or request changes to it. Note that any change of Maven group or plugin ID will cause the approval process to be triggered again.

All plugins must adhere to the following rules.

Group shouldn't start with gradle.plugin

Under certain circumstances (read on for details), the publishing plugin will use the project group, prefixed with gradle.plugin as the maven coordinate group for your plugin. For example, if your project has group com.foo, the maven coordinate group of the plugin will be gradle.plugin.com.foo. We no longer accept the usage of the gradle.plugin prefix in group values.

The plugin-publish plugin will not do the prefixing described above in case it's used in collaboration with the maven-publish plugin. This is now the recommended setup (see Gradle docs for plugin publishing), so prefixing should no longer happen.

Another way of disabling the automatic prefixing is setting the group via a mavenCoordinates block. See the Full Example below. We will reject plugins if they have a group starting with gradle.plugin so you need to adapt the legacy setup.

Plugins must have some functionality

"Hello world" type submissions will be rejected.

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, 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

If a GitHub user johndoe publishes a plugin called myplugin, then an acceptable plugin ID would be io.github.johndoe.myplugin. com.github is no longer accepted as a prefix 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 via his or hers corporate account, ie. a mybusiness.com email address.

If we cannot link to the domain, we will ask for proof, in the form of a TXT record added to the DNS entry.

Only final versions should be published

SNAPSHOT versions will be rejected, because they can't be overridden anyways.

Plugins should be published from non-forked repositories

There shouldn't be multiple variants of the same plugin published to 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.

Configuration examples

build.gradle (Simple Example)

// First, apply the publishing plugin
plugins {
  id "com.gradle.plugin-publish" version "0.16.0"
  id "java-gradle-plugin"
  // Apply other plugins here, e.g. the kotlin plugin for a plugin written in Kotlin
  // or the groovy plugin if the plugin uses Groovy
}

// If your plugin has any external java dependencies, Gradle will attempt to
// download them from JCenter for anyone using the plugins DSL
repositories {
  mavenCentral()
}

// Unless overridden in the pluginBundle config DSL, the project version will
// be used as your plugin version when publishing
version = "1.2"
group = "com.foo.myplugin"

// Use java-gradle-plugin to generate plugin descriptors and specify plugin ids
gradlePlugin {
  plugins {
    greetingsPlugin {
      id = 'org.samples.greeting'
      implementationClass = 'org.gradle.GreetingPlugin'
    }
  }
}

// The configuration example below shows the minimum required properties
// configured to publish your plugin to the plugin portal
pluginBundle {
  website = 'https://www.gradle.org/'
  vcsUrl = 'https://github.com/gradle/gradle'
  description = 'Greetings from here!'
  tags = ['greetings', 'salutations']

  plugins {
    greetingsPlugin {
      // id is captured from java-gradle-plugin configuration
      displayName = 'Gradle Greeting plugin'
    }
  }
}

build.gradle (Full Example)

// First, apply the publishing plugin
plugins {
  id "com.gradle.plugin-publish" version "0.16.0"
  id "java-gradle-plugin"
  // Apply other plugins here, e.g. the kotlin plugin for a plugin written in Kotlin
  // or the groovy plugin if the plugin uses Groovy
}

// If your plugin has any external java dependencies, Gradle will attempt to
// download them from JCenter for anyone using the plugins DSL
repositories {
  mavenCentral()
}

// Use java-gradle-plugin to generate plugin descriptors and specify plugin ids
gradlePlugin {
  plugins {
    greetingsPlugin {
      id = 'org.samples.greeting'
      implementationClass = 'org.gradle.GreetingPlugin'
    }
    goodbyePlugin {
      id = 'org.samples.goodbye'
      implementationClass = 'org.gradle.GoodbyePlugin'
    }
  }
}

pluginBundle {
  // These settings are set for the whole plugin bundle
  website = 'https://www.gradle.org/'
  vcsUrl = 'https://github.com/gradle/gradle'

  // tags and description can be set for the whole bundle here, but can also
  // be set / overridden in the config for specific plugins
  description = 'Greetings from here!'

  // The plugins block can contain multiple plugin entries.
  //
  // The name for each plugin block below (greetingsPlugin, goodbyePlugin)
  // does not affect the plugin configuration, but they need to be unique
  // for each plugin.

  // Plugin config blocks can set the id, displayName, version, description
  // and tags for each plugin.

  // id and displayName are mandatory.
  // If no version is set, the project version will be used.
  // If no tags or description are set, the tags or description from the
  // pluginBundle block will be used, but they must be set in one of the
  // two places.

  plugins {

    // first plugin
    greetingsPlugin {
      // id is captured from java-gradle-plugin configuration
      displayName = 'Gradle Greeting plugin'
      tags = ['individual', 'tags', 'per', 'plugin']
      version = '1.2'
    }

    // another plugin
    goodbyePlugin {
      // id is captured from java-gradle-plugin configuration
      displayName = 'Gradle Goodbye plugin'
      description = 'Override description for this plugin'
      tags = ['different', 'for', 'this', 'one']
      version = '1.3'
    }
  }

  // Optional overrides for Maven coordinates.
  // If you have an existing plugin deployed to Bintray and would like to keep
  // your existing group ID and artifact ID for continuity, you can specify
  // them here.
  //
  // As publishing to a custom group requires manual approval by the Gradle
  // team for security reasons, we recommend not overriding the group ID unless
  // you have an existing group ID that you wish to keep. If not overridden,
  // plugins will be published automatically without a manual approval process.
  //
  // You can also override the version of the deployed artifact here, though it
  // defaults to the project version, which would normally be sufficient.

  mavenCoordinates {
    groupId = "org.samples.override"
    artifactId = "greeting-plugins"
    version = "1.4"
  }
}

build.gradle.kts (Kotlin Example)

// First, apply the publishing plugin
plugins {
  id("com.gradle.plugin-publish") version "0.16.0"
  `java-gradle-plugin`
  // Apply other plugins here, e.g. the kotlin plugin for a plugin written in Kotlin
  // or the groovy plugin if the plugin uses Groovy
}

// If your plugin has any external java dependencies, Gradle will attempt to
// download them from JCenter for anyone using the plugins DSL
repositories {
  mavenCentral()
}

// Use java-gradle-plugin to generate plugin descriptors and specify plugin ids
gradlePlugin {
  plugins {
    create("greetingsPlugin") {
      id = "org.samples.greeting"
      implementationClass = "org.gradle.GreetingPlugin"
    }
    create("goodbyePlugin") {
      id = "org.samples.goodbye"
      implementationClass = "org.gradle.GoodbyePlugin"
    }
  }
}

pluginBundle {
  // These settings are set for the whole plugin bundle
  website = "https://www.gradle.org/"
  vcsUrl = "https://github.com/gradle/gradle"

  // tags and description can be set for the whole bundle here, but can also
  // be set / overridden in the config for specific plugins
  description = "Greetings from here!"

  // The plugins block can contain multiple plugin entries.
  //
  // The name for each plugin block below (greetingsPlugin, goodbyePlugin)
  // does not affect the plugin configuration, but they need to be unique
  // for each plugin.

  // Plugin config blocks can set the id, displayName, version, description
  // and tags for each plugin.

  // id and displayName are mandatory.
  // If no version is set, the project version will be used.
  // If no tags or description are set, the tags or description from the
  // pluginBundle block will be used, but they must be set in one of the
  // two places.

  (plugins) {

    // first plugin
    "greetingsPlugin" {
      // id is captured from java-gradle-plugin configuration
      displayName = "Gradle Greeting plugin"
      tags = listOf("individual", "tags", "per", "plugin")
      version = "1.2"
    }

    // another plugin
    "goodbyePlugin" {
      // id is captured from java-gradle-plugin configuration
      displayName = "Gradle Goodbye plugin"
      description = "Override description for this plugin"
      tags = listOf("different", "for", "this", "one")
      version = "1.3"
    }
  }

  // Optional overrides for Maven coordinates.
  // If you have an existing plugin deployed to Bintray and would like to keep
  // your existing group ID and artifact ID for continuity, you can specify
  // them here.
  //
  // As publishing to a custom group requires manual approval by the Gradle
  // team for security reasons, we recommend not overriding the group ID unless
  // you have an existing group ID that you wish to keep. If not overridden,
  // plugins will be published automatically without a manual approval process.
  //
  // You can also override the version of the deployed artifact here, though it
  // defaults to the project version, which would normally be sufficient.

  mavenCoordinates {
    groupId = "org.samples.override"
    artifactId = "greeting-plugins"
    version = "1.4"
  }
}