# Preparing to Publish Plugins

version 9.4.0

To share a Gradle plugin, package it into JAR files and generate the accompanying metadata so other builds can resolve and apply it.

Gradle’s publishing plugins add tasks and conventions to prepare artifacts and metadata for distribution to repositories such as a local Maven repository, Maven Central, JFrog Artifactory, or the Gradle Plugin Portal.

## Applying a Publishing Plugin

Apply one or more publishing plugins in your plugin project:

- For the Gradle Plugin Portal: Plugin Publish Plugin

- For Maven repositories (e.g., Maven Central, Artifactory, GitHub Packages): Maven Publish Plugin

- For Ivy repositories: Ivy Publish Plugin

    plugins {
        id("maven-publish")                                         // Maven
        id("ivy-publish")                                           // Ivy
        id("com.gradle.plugin-publish") version "<latest-version>"  // Plugin Portal
    }

Applying a publishing plugin registers tasks that assemble your plugin JAR(s) and generate metadata files (POM, Gradle Module Metadata, and the plugin marker module).

## Minimum Configuration

A plugin project must at least declare:

- A plugin ID and implementation class (so Gradle knows what to apply)

- A group and version (so the plugin can be published and resolved)

build.gradle.kts

    group = "org.example"
    version = "1.0"
    gradlePlugin {
        plugins.create("greeting") {
            id = "org.example.greeting"
            implementationClass = "org.example.GreetingPlugin"
        }
    }

build.gradle

    group = 'org.example'
    version = '1.0'
    gradlePlugin {
        plugins.create('greeting') {
            id = 'org.example.greeting'
            implementationClass = 'org.example.GreetingPlugin'
        }
    }

This lets Gradle generate the plugin marker module (`org.example.greeting.gradle.plugin`) and other metadata required by repositories and consumers.

## Local Publishing and Testing

Before publishing remotely, publish to a local Maven directory:

build.gradle.kts

    publishing {
        repositories {
            maven { url = uri(layout.buildDirectory.dir("local-repo")) }
        }
    }

build.gradle

    publishing {
        repositories {
            maven { url = layout.buildDirectory.dir('local-repo') }
        }
    }

Run:

    ./gradlew publish

Gradle writes plugin artifacts and metadata to `build/local-repo`:

    build/local-repo/
    └── org/
        └── example/
            ├── greeting/
            │   └── 1.0.0/
            │       ├── greeting-1.0.0.jar                 // compiled plugin classes
            │       ├── greeting-1.0.0.jar.sha1            // checksum (SHA-1)
            │       ├── greeting-1.0.0.jar.sha256          // checksum (SHA-256)
            │       ├── greeting-1.0.0.module              // Gradle Module Metadata (variants, capabilities, deps)
            │       ├── greeting-1.0.0.module.sha1
            │       ├── greeting-1.0.0.module.sha256
            │       ├── greeting-1.0.0.pom                 // Maven POM: GAV + dependencies
            │       ├── greeting-1.0.0.pom.sha1
            │       ├── greeting-1.0.0.pom.sha256
            │       └── greeting-1.0.0-sources.jar         // optional (java { withSourcesJar() })
            │           ├── greeting-1.0.0-sources.jar.sha1
            │           └── greeting-1.0.0-sources.jar.sha256
            │
            └── org.example.greeting.gradle.plugin/
                └── 1.0.0/
                    ├── org.example.greeting.gradle.plugin-1.0.0.module         // plugin marker metadata
                    ├── org.example.greeting.gradle.plugin-1.0.0.module.sha1
                    ├── org.example.greeting.gradle.plugin-1.0.0.module.sha256
                    ├── org.example.greeting.gradle.plugin-1.0.0.pom            // plugin marker POM
                    ├── org.example.greeting.gradle.plugin-1.0.0.pom.sha1
                    └── org.example.greeting.gradle.plugin-1.0.0.pom.sha256

You’ll see:

- Plugin JAR(s) — compiled classes

- `.pom` — Maven metadata (coordinates, dependencies)

- `.module` — Gradle Module Metadata (variants, capabilities)

- Plugin marker module — enables `plugins { id("…") }` resolution by plugin ID

- Optional sources JAR — if enabled via `withSourcesJar()`

- Checksums — integrity files (many repos prefer SHA-256/SHA-512)

To consume locally, point the consumer project’s `pluginManagement` to the local repo:

settings.gradle.kts

    pluginManagement {
        repositories {
            maven {
                url = uri("../plugin/build/local-repo")
            }
            gradlePluginPortal()
        }
    }

settings.gradle

    pluginManagement {
        repositories {
            maven {
                url = uri('../plugin/build/local-repo')
            }
            gradlePluginPortal()
        }
    }

Consumers can then apply your plugin by ID without publishing to a public repository.

## Validating

To validate a Plugin Portal publication (no upload):

    $ ./gradlew publishPlugins --validate-only