skip to content

When does an init.gradle (initialization) script run relative to settings.gradle, and what is each responsible for?

level: seniorimportance: should knowfreq 30%

answer

  1. init script runs before settings
  2. Gradle object vs Settings object
  3. ~/.gradle/init.d, -I flag
  4. machine/CI-wide vs per-build
  5. settingsEvaluated / projectsLoaded callbacks

basics

~10 s

Init scripts run first, before settings.gradle is evaluated, against a Gradle object — used for machine/CI-wide setup (mirrors, credentials, global plugins). settings.gradle runs next, against the Settings object, defining the build's project structure.

solid answer

~40 s

Both are part of the initialization phase but at different scopes. **Init scripts** (`~/.gradle/init.gradle(.kts)`, files in `~/.gradle/init.d/`, or `-I file`) run *first* and apply across *every* build on that machine/user/CI agent. They are evaluated against a `Gradle` object and are the place for environment-level concerns: artifact mirrors, repository credentials, enterprise build scans, or applying plugins to all builds — things you don't want committed in a project. **settings.gradle.kts** runs *after* init scripts and is *per-build*: evaluated against the `Settings` object, it defines `rootProject.name`, `include`/`includeBuild`, pluginManagement, and dependency management. Order: init scripts → settings evaluation → project hierarchy creation → configuration. Init scripts can hook lifecycle callbacks (e.g. `settingsEvaluated`, `projectsLoaded`) to inject behavior into the build they're decorating.

code

kotlin · 12 lines
kotlin
// ~/.gradle/init.gradle.kts  (runs before any settings.gradle.kts)
settingsEvaluated {
    // inject a corporate mirror for every build on this machine
    pluginManagement.repositories {
        maven { url = uri("https://corp-mirror/plugins") }
    }
}
projectsLoaded {
    gradle.rootProject {
        logger.lifecycle("Initialized: ${'$'}name")
    }
}

go deeper

for a junior

Awareness that init scripts exist and run early is enough.

for a middle

Place init scripts before settings and name common uses (mirrors, scans).

for a senior

Explain the Gradle vs Settings receivers, discovery locations, and lifecycle callbacks like settingsEvaluated/projectsLoaded.

for a principal

Design CI-agent init scripting for org-wide governance (mirrors, scans, credentials) without touching project repos.

## Two layers of initialization The initialization phase has two distinct inputs that run in a fixed order: 1. **Init scripts** (Gradle-wide / machine scope) 2. **The settings script** (per-build scope) ## Init scripts Init scripts are discovered from several locations and all run *before* settings: - `-I <file>` / `--init-script <file>` on the command line - `~/.gradle/init.gradle` or `~/.gradle/init.gradle.kts` - every `.gradle`/`.gradle.kts` file in `~/.gradle/init.d/` - `$GRADLE_HOME/init.d/` They are evaluated against the **`Gradle`** object (the build invocation), not `Settings` or `Project`. Because they apply to *all* builds on the agent, they're ideal for: ```kotlin // ~/.gradle/init.gradle.kts settingsEvaluated { pluginManagement { repositories { maven { url = uri("https://corp-mirror/repo") } } } } allprojects { repositories { // inject a corporate mirror into every project } } ``` Typical uses: corporate artifact mirrors, credentials kept out of version control, enabling Build Scans / Develocity, enforcing global conventions on CI. ## settings.gradle.kts After init scripts run, Gradle evaluates the per-build settings file against the **`Settings`** object, declaring project structure and build-wide resolution. This is committed to the repo because it defines *this build*. ## Lifecycle callbacks Init scripts and settings can register callbacks that fire later in initialization/configuration: - `settingsEvaluated { }` — after settings is fully evaluated - `projectsLoaded { }` — after the Project hierarchy is created - `projectsEvaluated { }` — after all projects are configured (end of configuration) These let global tooling decorate a build without editing its scripts. ## Why the split Init scripts are **environment** policy (not in the repo); settings is **build** definition (in the repo). Running init first means the environment can shape how settings and resolution behave — e.g., redirect repositories before the build's own pluginManagement is read.

  • Which object is the receiver of an init script?
    The Gradle object (the build invocation), unlike settings which uses the Settings object and build scripts which use Project.
  • Why keep mirrors/credentials in an init script rather than settings.gradle.kts?
    Init scripts live outside the repo (machine/CI scope), so environment-specific or secret config isn't committed and applies uniformly to all builds on the agent.
  • Name a lifecycle callback that fires right after the project hierarchy is built.
    projectsLoaded { } fires after the Project hierarchy is created (post-settings, pre-configuration).

saying these in an interview costs you the question

  • Saying init scripts run after settings.gradle (they run before).
  • Putting secrets/credentials in committed settings.gradle.kts.
  • Confusing the Gradle object receiver of init scripts with the Settings object.

context