When does an init.gradle (initialization) script run relative to settings.gradle, and what is each responsible for?
answer
- init script runs before settings
- Gradle object vs Settings object
- ~/.gradle/init.d, -I flag
- machine/CI-wide vs per-build
- settingsEvaluated / projectsLoaded callbacks
basics
~10 sInit 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 sBoth 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// ~/.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
Awareness that init scripts exist and run early is enough.
Place init scripts before settings and name common uses (mirrors, scans).
Explain the Gradle vs Settings receivers, discovery locations, and lifecycle callbacks like settingsEvaluated/projectsLoaded.
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.