Gradle Installation, Wrapper, CLI, Settings, Build Scripts, and Project Bootstrap: Guided Hands-On Workflow and Core Operations
Bootstrap a small Java build once with a trusted Gradle installation, pin and verify Gradle 9.7.1 through the Wrapper, then inspect tasks, projects, properties, tests, generated output, and cache locations through the project-owned entry point.
Bootstrap a small Java build once with a trusted Gradle installation, pin and verify Gradle 9.7.1 through the Wrapper, then inspect tasks, projects, properties, tests, generated output, and cache locations through the project-owned entry point.
Learning objectives
- Bootstrap a disposable Java application with Gradle 9.7.1 and Java 17 target configuration.
- Generate a Wrapper pinned to 9.7.1 and configure the official distribution SHA-256.
- Verify both Wrapper distribution metadata and the Wrapper JAR before first project-owned execution.
- Use Wrapper-only commands to inspect projects, tasks, selected properties, tests, and build outputs.
-
Observe Gradle User Home, project
.gradle/, daemon, dependency-cache, andbuild/state separately. - Clean up only disposable lab state.
1. Scenario and bootstrap rule
You are creating a new JVM repository. There is no Wrapper yet, so one trusted Gradle installation must create the initial project/Wrapper files. That one-time bootstrap use is different from the repository’s normal operating rule.
Rule: use a reviewed system Gradle only to bootstrap or repair the Wrapper. Once the Wrapper is generated and verified, all build/test/discovery commands use the Wrapper.
The lab uses an isolated GRADLE_USER_HOME inside the
disposable project. It never deletes or edits your normal
~/.gradle.
2. Preflight: record the machine and installed bootstrap tool
# POSIX — run outside any untrusted Gradle repository
java -version
gradle --version
# Expected chapter baseline:
# Gradle 9.7.1
# JVM 21.x (or another Gradle-supported JVM 17..26)
# PowerShell
java -version
gradle --version
If the machine has no trusted Gradle installation, install Gradle
9.7.1 through Gradle’s official installation path or your
organization’s controlled package channel. Do not borrow an unknown
gradle-wrapper.jar from another repository.
3. Create the disposable project with an isolated Gradle User Home
# POSIX
mkdir wrapper-lab
cd wrapper-lab
export GRADLE_USER_HOME="$PWD/.lab-gradle-home"
# Non-interactive stable bootstrap. Build Init also creates Wrapper files.
gradle init \
--type java-application \
--dsl kotlin \
--test-framework junit-jupiter \
--package dev.academy.bootstrap \
--project-name wrapper-lab \
--no-split-project \
--java-version 17 \
--use-defaults \
--no-incubating
--no-incubating keeps the generated baseline on stable
features. --no-split-project avoids introducing
multi-project structure in the bootstrap lesson. Build Init
generates source/build scripts and Wrapper files; inspect what your
pinned Gradle generated rather than assuming future
init output is byte-for-byte identical.
4. Inspect generated source before executing the Wrapper
printf '%s
' '--- files ---'
find . -maxdepth 3 -type f -not -path './.lab-gradle-home/*' | sort
printf '%s
' '--- settings ---'
sed -n '1,160p' settings.gradle.kts
printf '%s
' '--- build ---'
sed -n '1,220p' build.gradle.kts
printf '%s
' '--- wrapper properties before hardening ---'
cat gradle/wrapper/gradle-wrapper.properties
At this point the files are ordinary inputs you can review. Do not
run ./gradlew merely because it exists. First pin the
exact distribution and validate the executable Wrapper JAR.
5. Regenerate the Wrapper with exact version and distribution checksum
gradle :wrapper \
--gradle-version 9.7.1 \
--distribution-type bin \
--gradle-distribution-sha256-sum acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a
cat gradle/wrapper/gradle-wrapper.properties
The expected distribution URL is
https://services.gradle.org/distributions/gradle-9.7.1-bin.zip
and the expected distributionSha256Sum is
acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a. The checksum is reviewed data, not something to derive from the
downloaded ZIP after trusting that same download.
6. Verify the Wrapper JAR before first Wrapper execution
actual=$(sha256sum gradle/wrapper/gradle-wrapper.jar | awk '{print $1}')
expected="7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d"
printf 'expected=%s
actual=%s
' "$expected" "$actual"
test "$actual" = "$expected"
$expected = "7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d"
$actual = (Get-FileHash gradle\wrapper\gradle-wrapper.jar -Algorithm SHA256).Hash.ToLower()
"expected=$expected"
"actual=$actual"
if ($actual -ne $expected) { throw "Wrapper JAR checksum mismatch" }
If the checksum differs, stop. Determine whether the JAR came from a different known Gradle version; do not “fix” the expected hash to match an unexplained binary.
7. Switch to the project-owned entry point
# POSIX
./gradlew --version
./gradlew -q projects
./gradlew tasks --all
./gradlew help --task build
The first Wrapper invocation may download and unpack Gradle 9.7.1
into $GRADLE_USER_HOME/wrapper/dists. The configured
SHA-256 is checked before the distribution is trusted. Subsequent
invocations can reuse that verified distribution from this isolated
home.
8. Inspect selected project properties without dumping secret-bearing state into logs
# Disposable lab contains no secrets; filter to known benign properties.
./gradlew properties --console=plain | grep -E '^(name|group|version):' || true
# Prefer focused task help when you only need task configuration/usage.
./gradlew help --task test
properties can reveal project properties supplied from
build logic, command line, or user state. In real CI, do not upload
an unreviewed full property dump if credentials or tokens may have
been represented as Gradle properties.
9. Run tests and build through the Wrapper; inspect evidence
./gradlew clean test build --console=plain
find build -maxdepth 3 -type f | sort | sed -n '1,120p'
find build/test-results -type f -name '*.xml' -print
find build/libs -type f -print
For a single-project Java application, test reports normally appear
below build/test-results/test/ and HTML reports below
build/reports/tests/test/; archives appear below
build/libs/. These paths are generated outputs, not
dependency caches.
10. Prove where Gradle stored each kind of state
printf '%s
' '--- project-local state ---'
find .gradle -maxdepth 2 -type d 2>/dev/null | sort | sed -n '1,80p'
printf '%s
' '--- isolated user home ---'
find "$GRADLE_USER_HOME" -maxdepth 2 -type d | sort | sed -n '1,100p'
printf '%s
' '--- wrapper distributions ---'
find "$GRADLE_USER_HOME/wrapper/dists" -maxdepth 3 -type d 2>/dev/null | sort | sed -n '1,80p'
./gradlew --status
You should be able to point to separate directories for the Wrapper distribution, dependency/cache state, daemon state, project-local Gradle state, and build outputs. That separation is the basis for later cache and performance chapters.
11. Challenge: choose the correct control
A teammate says, “CI already has Gradle 9.8 installed, so I changed
the job from ./gradlew build to
gradle build to avoid downloading 9.7.1.” What should
you change?
Expected reasoning: restore Wrapper invocation. If downloading is the concern, cache/provision the reviewed Wrapper distribution or upgrade the Wrapper through a reviewed change. Do not silently substitute the runner’s tool version for the repository contract.
12. Verification checklist and cleanup
-
./gradlew --versionreports Gradle 9.7.1 and the expected runtime JVM. -
gradle-wrapper.propertiescontains the exact distribution URL and reviewed SHA-256. -
gradle-wrapper.jarmatches the official 9.7.1 Wrapper-JAR checksum. -
testandbuildsucceeded through the Wrapper. -
Generated outputs are under
build/; user-home state is under the isolated.lab-gradle-home.
# Still inside wrapper-lab
./gradlew --stop || true
cd ..
rm -rf wrapper-lab
Only the disposable project and its embedded Gradle User Home are removed. Your normal Gradle User Home is untouched.
Knowledge check
Why does this lab use system Gradle at all?
A brand-new repository has no Wrapper yet. A trusted installed Gradle is needed to run Build Init/Wrapper generation. After verification, normal work switches to the project Wrapper.
Why pin both the distribution version and SHA-256?
The version names the intended engine; the SHA-256 verifies that the downloaded ZIP bytes match the reviewed Gradle release.
Why verify gradle-wrapper.jar separately?
It is executable bootstrap code and is not authenticated by
distributionSha256Sum.
What is wrong with uploading a full
./gradlew properties log from a real CI
job?
Project properties can include environment- or user-supplied values. A broad dump may expose sensitive configuration; inspect only the properties you actually need.
Why does cleanup avoid deleting the normal
~/.gradle directory?
Normal user caches and configuration are unrelated state and may contain valuable or sensitive settings. The lab isolates state so cleanup can delete only the lab home.
13. Bridge to design choices
The bootstrap works. Lesson 3 asks which choices belong in a long-lived repository: Kotlin versus Groovy DSL, wrapper-only policy, shared developer caches versus isolated CI homes, and how much of Build Init’s generated shape should become an organizational convention.
Official references and version notes
- Gradle 9.7.1 Release Notes — 9.7.1 is the August 19, 2026 patch release recommended over 9.7.0.
- Gradle Wrapper — Wrapper files, generation, distribution URL, checksum verification, and upgrade behavior.
- Gradle distribution and Wrapper JAR checksums — official SHA-256 reference.
- Compatibility Matrix — Gradle 9.7.1 runtime JVM support.
- Build Init Plugin — supported project types and non-interactive init options.
-
Gradle-managed Directories and Caches
— Gradle User Home, project
.gradle, build outputs, daemon logs, and dependency caches. - Gradle Daemon — client JVM, daemon JVM, status, logs, and daemon JVM criteria.
- Settings File Basics and Build File Basics.
Version snapshot: These lessons were generated for August 24, 2026 with Gradle 9.7.1 as the pinned lab release. Re-check the official release and compatibility pages before copying version-specific pins into a future production repository.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.