skip to content

How do you centralize plugin versions using the plugins {} sub-block inside pluginManagement, and how do build scripts then apply those plugins?

level: middleimportance: should knowfreq 50%

answer

  1. plugins {} inside pluginManagement sets versions only
  2. does not apply
  3. build script applies id with no version
  4. single edit updates all modules
  5. conflicts if version also in build script

basics

~10 s

Declare id("...") version "x" once in pluginManagement { plugins { } } in settings. Then each build script applies the plugin with just the id and no version.

solid answer

~40 s

Inside `pluginManagement {}` you can add a `plugins {}` sub-block that declares plugin ids together with their **versions** in one central place. This does **not** apply the plugins — it only fixes the version. Then every project's build script applies the plugin via the normal `plugins {}` DSL using only the id (`id("...")`) with no `version`. Gradle looks the version up from the settings-level declaration. This keeps versions consistent across a multi-project build and means a single edit in settings updates everyone. It is a structural/DSL convenience; the actual resolution still goes through the configured plugin repositories. Note this is distinct from a version catalog's `[plugins]` table, though both aim at version centralization.

code

kotlin · 12 lines
kotlin
// settings.gradle.kts
pluginManagement {
    repositories { gradlePluginPortal() }
    plugins {
        id("org.jetbrains.kotlin.jvm") version "2.0.20"
    }
}

// app/build.gradle.kts
plugins {
    id("org.jetbrains.kotlin.jvm")   // no version — taken from settings
}

go deeper

for a junior

Know that you can put plugin versions in one place and apply by id elsewhere.

for a middle

Explain that it sets versions only, build scripts apply without a version, and conflicts arise if both specify a version.

for a senior

Compare with version-catalog [plugins] and recommend a consistent project-wide convention.

for a principal

Define org policy: single source of truth for plugin versions, drift prevention, and CI enforcement across teams.

## The problem it solves In a multi-module build, if each `build.gradle.kts` writes `id("org.jetbrains.kotlin.jvm") version "2.0.20"`, the version string is duplicated everywhere. Bumping it means editing many files and risking drift (two modules on different versions of the same plugin can cause subtle classpath problems). ## The settings-level plugins {} block `pluginManagement {}` accepts a `plugins {}` sub-block whose **only** job is to associate a plugin id with a version build-wide: ```kotlin // settings.gradle.kts pluginManagement { repositories { gradlePluginPortal() } plugins { id("org.jetbrains.kotlin.jvm") version "2.0.20" id("com.github.ben-manes.versions") version "0.51.0" } } ``` This declaration **does not apply** anything — no project gets the Kotlin plugin from this alone. It simply registers the version. ## Applying from build scripts Each build script then applies by id, **omitting** the version: ```kotlin // app/build.gradle.kts plugins { id("org.jetbrains.kotlin.jvm") // version comes from settings } ``` Gradle resolves the version from the settings declaration. If a build script *does* specify a version while one is also set in settings, that is an error (conflicting versions for the same plugin). ## Relationship to version catalogs Gradle also offers **version catalogs** (`gradle/libs.versions.toml` with a `[plugins]` table) which can centralize plugin versions and are applied like `alias(libs.plugins.kotlinJvm)`. The `pluginManagement { plugins { } }` approach predates and complements catalogs; many modern builds prefer the catalog for plugins but the settings `plugins {}` block remains valid and is common for convention/shared-build setups. ## Key distinctions - `pluginManagement { plugins { } }` — sets versions, does not apply. - `plugins { }` in a build script — applies (and, when version omitted, borrows the settings version). - Both are the `plugins {}` DSL but in different scripts with different meaning.

  • Does declaring a plugin in pluginManagement { plugins { } } apply it to any project?
    No. It only fixes the version centrally. A project must still apply it via the plugins {} DSL in its own build script.
  • What happens if a build script specifies a version for a plugin that already has one in settings?
    Gradle reports a conflict — the same plugin id is given two versions. Remove the version from the build script and let it inherit from settings.

saying these in an interview costs you the question

  • Claiming the settings plugins {} block applies the plugin everywhere
  • Specifying versions in both settings and build scripts
  • Confusing the settings plugins {} block with the build-script plugins {} block

context