skip to content

What metadata must you configure before `publishPlugins` will accept a plugin, and where does each piece go in the build script?

level: middleimportance: must knowfreq 45%

answer

  1. website + vcsUrl on extension
  2. id, implementationClass per plugin
  3. displayName, description, tags
  4. group/version = coordinates + marker version
  5. validate-only catches gaps

basics

~10 s

On the gradlePlugin extension: website and vcsUrl. On each plugin entry: id, implementationClass, displayName, description, and tags. The Portal rejects publishes missing these.

solid answer

~30 s

The Portal enforces a minimum metadata set, configured through the **`gradlePlugin`** extension contributed by `com.gradle.plugin-publish`/`java-gradle-plugin`. **Project/extension-level** (shared by all plugins in the build): **`website`** and **`vcsUrl`** — both required by the Portal so listings link to docs and source. **Per-plugin** (inside `plugins { create("x") { … } }`): **`id`** (the dotted plugin ID), **`implementationClass`** (FQN of your `Plugin<Project>`), **`displayName`**, **`description`**, and **`tags`** (search keywords). Project `group` and `version` supply the Maven coordinates and marker version. Credentials (`gradle.publish.key`/`secret`) aren't part of `gradlePlugin` but are required to authenticate. Running `publishPlugins --validate-only` surfaces any missing field before upload.

code

kotlin · 13 lines
kotlin
gradlePlugin {
    website = "https://example.com/greeting"
    vcsUrl = "https://github.com/example/greeting.git"
    plugins {
        create("greeting") {
            id = "com.example.greeting"
            implementationClass = "com.example.GreetingPlugin"
            displayName = "Greeting Plugin"
            description = "Adds a configurable greeting task"
            tags = listOf("greeting", "hello", "sample")
        }
    }
}

go deeper

for a junior

Name the obvious fields: id and implementationClass.

for a middle

Distinguish extension-level (website/vcsUrl) from per-plugin (displayName/description/tags) metadata and how coordinates derive from the project.

for a senior

Tie metadata to the marker version and use --validate-only as a CI gate.

for a principal

Standardize metadata conventions (tags taxonomy, vcsUrl policy) across an org's plugin catalog.

## Where metadata lives All publishing metadata flows through the **`gradlePlugin`** extension. It has two layers: ### Extension-level (once per build) - **`website`** — URL to the plugin's homepage/docs. Required by the Portal. - **`vcsUrl`** — URL to the source repository. Required by the Portal. ### Per-plugin (inside `plugins { … }`) Each declared plugin needs: - **`id`** — the plugin ID consumers use in `plugins { id("…") }`. Must follow reverse-domain dotted form and is namespaced on the Portal. - **`implementationClass`** — fully-qualified name of the class implementing `Plugin<Project>` (or `Plugin<Settings>`). - **`displayName`** — human-readable title for the Portal listing. - **`description`** — short summary shown on the listing and in search. - **`tags`** — list of keywords improving discoverability. ### Coordinates come from the project The implementation artifact's Maven coordinates are `project.group:project.name:project.version`. The **plugin marker** version also tracks `project.version`, so set `group` and `version` explicitly. ## Authentication is separate Metadata describes *what* you publish; the **API key/secret** authorize *that you may*. Provide `gradle.publish.key`/`gradle.publish.secret` via `~/.gradle/gradle.properties` or env vars. ## Example ```kotlin group = "com.example" version = "2.1.0" gradlePlugin { website = "https://example.com/greeting" vcsUrl = "https://github.com/example/greeting.git" plugins { create("greeting") { id = "com.example.greeting" implementationClass = "com.example.GreetingPlugin" displayName = "Greeting" description = "Adds a greeting task" tags = listOf("greeting", "hello") } } } ``` ## Validation `./gradlew publishPlugins --validate-only` runs the Portal's validation rules locally — missing `website`, `vcsUrl`, `description`, or empty `tags` cause it to fail fast, which is ideal as a CI pre-publish gate.

  • Why are `website` and `vcsUrl` set on the extension rather than per plugin?
    They describe the project/source as a whole, which the Portal applies to all plugins published from that build. Tags, displayName, and description are per-plugin because each plugin has its own listing.
  • Which project properties become the implementation artifact's coordinates?
    `project.group`, `project.name`, and `project.version` map to groupId:artifactId:version; the marker version also follows `project.version`.

saying these in an interview costs you the question

  • Listing the API key as part of `gradlePlugin` metadata — credentials are separate.
  • Forgetting `vcsUrl`/`website` are mandatory.
  • Saying `tags` are optional decoration — empty tags fail validation.

context