skip to content

How do you enable dependency locking and generate the lockfile in a Gradle build?

level: middleimportance: must knowfreq 50%

answer

  1. lockAllConfigurations() opt-in
  2. activateDependencyLocking() per-config
  3. dependencies --write-locks generates
  4. one gradle.lockfile per project
  5. LockMode.STRICT requires state

basics

~10 s

Add a dependencyLocking { lockAllConfigurations() } block, then run a resolving task with --write-locks (e.g. ./gradlew dependencies --write-locks). Gradle writes the resolved versions to gradle.lockfile, which you commit.

solid answer

~40 s

Locking is opt-in. The simplest activation is in the build script: ```kotlin dependencyLocking { lockAllConfigurations() } ``` This marks every configuration's resolution state as **lockable**. You then **generate** the lockfile by resolving while passing `--write-locks`. A common idiom is `./gradlew dependencies --write-locks` because the `dependencies` task resolves everything, but any build that resolves the locked configurations works (e.g. `./gradlew build --write-locks`). Gradle writes one `gradle.lockfile` per project. From then on, ordinary builds (without the flag) **verify** resolution against the lockfile and fail on a mismatch. To re-generate after intentionally changing dependencies you re-run `--write-locks`; to bump only specific modules you use `--update-locks group:module`. In multi-project builds each subproject gets its own lockfile, so you typically generate across all projects at once.

code

bash · 5 lines
bash
# 1) build.gradle.kts:  dependencyLocking { lockAllConfigurations() }
# 2) generate the lockfile for every configuration:
./gradlew dependencies --write-locks
# 3) commit gradle.lockfile, then ordinary builds verify against it:
./gradlew build

go deeper

for a junior

Recall the two steps: add the block, run a task with --write-locks.

for a middle

Explain lockAllConfigurations vs per-configuration activation, why dependencies is used, and that only resolved configurations are written.

for a senior

Cover multi-project generation, LockMode.STRICT, and that verification happens on every normal build.

for a principal

Define org policy: which configurations to lock, enforcing STRICT mode, and a repeatable lock-regeneration step in CI.

## Two ways to enable **Per-build, all configurations** (most common): ```kotlin dependencyLocking { lockAllConfigurations() } ``` **Per-configuration** (fine-grained), via the configuration's `resolutionStrategy`: ```kotlin configurations.named("runtimeClasspath") { resolutionStrategy.activateDependencyLocking() } ``` Use the per-configuration form when you only want to lock, say, runtime classpaths and not buildscript or test-tooling configurations. ## Generating the lockfile Enabling locking does **not** create a file. You must resolve at least once with the write flag: ```bash ./gradlew dependencies --write-locks ``` - `dependencies` is convenient because it forces resolution of (almost) all configurations, so one command fills the whole lockfile. - You can attach `--write-locks` to any task that triggers resolution; only the configurations actually resolved during that run get written. - For multi-project builds, run a task that touches every subproject (or `./gradlew allDependencies`-style aggregation) so each project's `gradle.lockfile` is produced. ## What gets written Gradle 6+ writes a single `gradle.lockfile` per project at the project root. Each entry maps a `group:artifact:version` to the list of configurations that resolved it, with an `empty=` line for configurations that resolved to nothing. Commit this file. ## Verifying vs. writing | Command | Behaviour | |---|---| | `./gradlew build` | Resolves and **verifies** against the lockfile; fails on mismatch | | `./gradlew build --write-locks` | Resolves and **overwrites** lock entries for the resolved configurations | | `./gradlew build --update-locks g:m` | Allows only `g:m` to change, rewrites just those entries | ## Strict mode By default, a configuration that is *enabled for locking but has no lock state yet* simply records state on the next write. You can require that every locked configuration must have lock state by enabling `LockMode.STRICT`: ```kotlin dependencyLocking { lockMode.set(LockMode.STRICT) } ``` In strict mode, resolving a lockable configuration with no lockfile entry fails the build, preventing accidental un-locked resolution.

  • Does adding the dependencyLocking block by itself create a lockfile?
    No. Enabling locking only marks configurations as lockable. You must resolve once with --write-locks to actually produce gradle.lockfile.
  • Why is the `dependencies` task often used with --write-locks?
    It forces resolution of essentially all configurations in one go, so a single run populates the whole lockfile instead of only the configurations a narrower task happens to resolve.
  • What does LockMode.STRICT add?
    It makes resolving a lockable configuration that has no recorded lock state a build failure, so you can't accidentally resolve unlocked.

saying these in an interview costs you the question

  • Thinking the lockfile is auto-created when you add the block.
  • Assuming one `--write-locks` run on a single task captures every configuration — only resolved ones are written.
  • Forgetting to commit gradle.lockfile.

context