skip to content

What is the difference between the `buildscript {}` block, `allprojects {}`, and `subprojects {}` in a root build, and where do plugin repositories belong?

level: seniorimportance: should knowfreq 35%

answer

  1. buildscript = build's own classpath
  2. allprojects/subprojects = project config
  3. two repo spaces: plugin vs dependency
  4. pluginManagement + dependencyResolutionManagement in settings
  5. FAIL_ON_PROJECT_REPOS forbids allprojects repos

basics

~10 s

buildscript {} configures the build's own classpath/repositories (where Gradle finds plugins to apply). allprojects {}/subprojects {} configure the projects (their dependencies, plugins, settings). They solve different problems and aren't interchangeable.

solid answer

~50 s

These blocks operate at different layers. `buildscript {}` declares repositories and dependencies for the **build script classpath itself** — the JARs needed to *apply* plugins or call APIs in the script — and historically that's where you'd put the repository hosting a plugin you apply with the legacy `apply plugin` mechanism. `allprojects {}`/`subprojects {}` configure the **projects** themselves: their production/test dependencies, applied plugins, `group`/`version`, repositories used to resolve *project* dependencies. People sometimes wrongly nest `repositories {}` for plugin resolution inside `allprojects {}`; that adds *project* repositories, not *plugin* repositories. In modern Gradle the cleaner answer is to declare plugin repositories in `settings.gradle.kts` under `pluginManagement { repositories { } }`, and project repositories ideally in `dependencyResolutionManagement { repositories { } }` in settings too. So the modern stack barely needs `buildscript {}` at all, and project repositories increasingly move out of `allprojects {}` into settings-level central declaration.

code

kotlin · 9 lines
kotlin
// settings.gradle.kts — the modern, central home
pluginManagement {
    repositories { gradlePluginPortal(); mavenCentral() }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories { mavenCentral() }
}
// With this, an allprojects { repositories { } } block would FAIL the build.

go deeper

for a junior

Just distinguish 'buildscript = where plugins come from for the script' vs 'allprojects/subprojects = configure the modules'.

for a middle

Explain the two repository spaces and that allprojects.repositories is for project dependencies, not plugins.

for a senior

Recommend pluginManagement + dependencyResolutionManagement in settings and explain how FAIL_ON_PROJECT_REPOS supersedes allprojects repositories.

for a principal

Standardize central repository governance across the org and treat per-project/allprojects repos as policy violations.

## Three different layers ### `buildscript {}` — the build script's own classpath A Gradle build script is compiled and run on a classpath. `buildscript {}` configures *that* classpath: ```kotlin buildscript { repositories { mavenCentral() } dependencies { classpath("com.example:some-plugin:1.2.3") } } apply(plugin = "com.example.some") ``` This is the **legacy** way to apply a plugin: put the plugin JAR on the buildscript classpath, then `apply` it. The modern `plugins { }` block replaces it and resolves plugins via the plugin portal / `pluginManagement`. ### `allprojects {}` / `subprojects {}` — configuring projects These don't touch the build classpath at all. They configure `Project` objects: their dependencies, plugins, extensions, tasks. A `repositories { }` inside `allprojects {}` adds repositories used to resolve **project dependencies** (Guava, Spring, etc.), not plugins. ## The repositories confusion There are two distinct repository spaces: | Space | Resolves | Modern home | |-------|----------|-------------| | Plugin repositories | plugins applied via `plugins {}` | `settings.gradle.kts` → `pluginManagement { repositories { } }` | | Dependency repositories | project dependencies | `settings.gradle.kts` → `dependencyResolutionManagement { repositories { } }` (or per-project) | Putting `repositories { mavenCentral() }` in `allprojects {}` populates the *dependency* space for every project. It does **not** make a plugin resolvable. That's a common mix-up. ## Why settings-level is preferred now `dependencyResolutionManagement` with `RepositoriesMode.FAIL_ON_PROJECT_REPOS` lets you declare repositories once, centrally, and forbid per-project (and `allprojects`) repository declarations — directly removing a major reason people used `allprojects { repositories { } }`. So the trajectory is: - Plugins → `pluginManagement` in settings (not `buildscript`). - Project repositories → `dependencyResolutionManagement` in settings (not `allprojects`). ```kotlin // settings.gradle.kts pluginManagement { repositories { gradlePluginPortal(); mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() } } ``` ## The takeaway for interviews Know the layering: `buildscript {}` = build's classpath (legacy plugin application), `allprojects/subprojects {}` = project configuration, and the modern best practice pushes both repository concerns into `settings.gradle.kts`. Conflating these is a classic mistake.

  • If a teammate puts `mavenCentral()` in `allprojects { repositories { } }` to fix a 'plugin not found' error, why won't it work?
    Plugins resolve from the *plugin* repository space (gradlePluginPortal / pluginManagement), not the project dependency space that allprojects.repositories populates. They'd need `pluginManagement { repositories { } }` in settings, or `buildscript { repositories { } }` for the legacy apply path.
  • What does `RepositoriesMode.FAIL_ON_PROJECT_REPOS` do to an `allprojects { repositories { } }` block?
    It makes the build fail if any project (including ones configured via allprojects) declares its own repositories, forcing all dependency repositories to be declared centrally in settings' dependencyResolutionManagement.

saying these in an interview costs you the question

  • Saying buildscript{} and allprojects{} are interchangeable.
  • Believing allprojects { repositories { } } makes a plugin resolvable.
  • Putting plugin repositories in dependencyResolutionManagement (wrong space).

context