CI/CD Build Patterns, Caching, Test Sharding, Artifact Promotion, and Ephemeral Build Agents: Configuration, Design Choices, and Tradeoffs
Choose CI build controls by the state they affect: dependency caches versus build caches, one job versus shards, persistent versus ephemeral agents, rebuild-per-environment versus immutable promotion, and provider YAML versus portable repository-owned scripts.
Learning objectives
- Choose dependency caches, build caches, or pipeline artifacts according to the state being reused.
- Evaluate shard count against setup cost, determinism, report aggregation, and resource limits.
- Compare persistent and ephemeral agents without assuming either is inherently secure or fast.
- Reject rebuild-per-environment when immutable promotion can preserve artifact identity.
- Keep portable build correctness in repository-owned scripts while limiting provider-specific YAML to orchestration.
Design rule. Every performance optimization must preserve source/toolchain identity, dependency trust, test evidence, and artifact checksum. If an optimization makes any of those harder to explain, its cost is larger than the saved seconds.
1. Dependency cache versus Build Cache
A dependency cache avoids redownloading external modules/plugins. A
Build Cache reuses outputs of cacheable tasks whose modeled inputs
produce the same cache key. They solve different bottlenecks and
carry different poisoning risks. Restoring dependencies cannot
legitimately make compileJava FROM-CACHE;
a Build Cache can.
| Choice | Good fit | Primary risk | Evidence |
|---|---|---|---|
| Dependency cache | Network-heavy dependency/plugin resolution. | Repository metadata staleness or untrusted cached artifacts if verification is weak. | Resolution logs, verification metadata, lockfiles. |
| Local Build Cache | Repeated work on one developer/agent. | Incorrect hits when task inputs are incomplete. |
Task outcome FROM-CACHE, cache-key diagnostics.
|
| Remote Build Cache | Trusted reusable task outputs across agents. | Poisoning if write authority is too broad. | Producer trust, cache key, task input model. |
| Pipeline artifact store | Immutable handoff between stages. | Wrong artifact/run selected. | Run ID + checksum + source/tool identity. |
3. Persistent versus ephemeral agents
Persistent agents can have warm local caches and long-lived processes, but they accumulate hidden state. Ephemeral agents make isolation easier to reason about but may pay more bootstrap cost. Neither model eliminates the need for Wrapper/JDK verification, secret scoping, or cache policy.
| Agent model | Benefit | Cost | Production guardrail |
|---|---|---|---|
| Persistent | Warm caches/daemons; lower startup cost. | State leakage, drift, harder incident cleanup. | Immutable images where possible, explicit cache dirs, periodic clean-room validation. |
| Ephemeral | Clear job boundary; easier reproducibility evidence. | Download/bootstrap cost; cache service dependency. | Verified Wrapper/JDK and explicitly restored approved caches. |
4. Rebuild per environment versus immutable promotion
Rebuilding for dev, staging, and production can appear “clean,” but it destroys artifact identity. The correct isolation boundary is environment configuration and deployment authorization, not compilation. Build one candidate, test it, hash/sign it, and promote or copy that same object. If policy requires environment-specific assembly, then those assemblies are distinct artifacts and need distinct identities—they should not masquerade as the same release.
5. Provider YAML versus portable build scripts
CI YAML should orchestrate jobs, permissions, artifacts, caches,
approvals, and runner placement. Build correctness—tasks, dependency
policy, test suite composition, reproducible packaging—belongs in
Maven/Gradle project configuration or repository-owned scripts. This
keeps ./gradlew ciTest jar or an equivalent Maven
command meaningful on a developer machine and another CI provider.
6. Trusted and untrusted pipeline classes
Pull requests from forks, protected branches, release tags, and scheduled dependency updates often have different trust levels. Design cache write authority, secret access, and publication rights accordingly. A useful policy is: untrusted jobs may read only carefully selected public/reviewed cache state; protected jobs may publish validated Build Cache entries and release artifacts. Exact CI features differ by platform, but the boundary remains.
7. Decision table for a mixed Maven/Gradle estate
| Question | Prefer | Why / observable behavior |
|---|---|---|
| Downloads dominate build time? | Dependency cache. | Fewer remote requests while compilation/tests still execute normally. |
| Compilation/tests are cacheable and repeated across trusted agents? | Remote Build Cache (Gradle) or equivalent controlled task-output strategy. | Eligible tasks can report restored outcomes instead of rerunning. |
| Need release handoff between stages? | Pipeline artifact/repository promotion. | Checksum ties downstream stage to exact upstream bytes. |
| Test suite is large and independent? | Deterministic shards. | Wall time can fall while shard manifests/reports prove coverage. |
| Small suite with high agent startup cost? | Single verification job. | Avoid duplicate bootstrap and report aggregation overhead. |
| Teams use multiple CI vendors? | Portable build scripts + thin provider adapters. | Same Wrapper commands run locally and across CI implementations. |
8. Worked scenario
A 20-module Gradle service takes 18 minutes: 3 minutes dependency
download on cold agents, 12 minutes tests, 3 minutes
compile/package. First, enable a verified dependency cache and
measure cold/warm differences. Second, split the 12-minute suite
into two balanced deterministic shards, preserving XML reports and a
coverage manifest. Third, export the single packaged artifact and
checksum. Do not add a broad cache containing
build/ or rebuild the JAR in deployment merely because
it seems simpler.
If later measurement shows compile tasks are stable/cacheable, introduce a protected remote Build Cache as a separate change. One variable at a time keeps performance causality visible.
9. Boundaries this chapter does not own
JDK image patching belongs to image/runner management; repository-manager retention and promotion rules belong to artifact-repository governance; branch protection and secret approval rules belong to CI-platform governance; deployment rollout belongs to delivery/platform courses. This chapter defines the build-tool contract those systems must preserve.
Knowledge check
Which cache can legitimately restore a Gradle task output?
The Gradle Build Cache, provided the task is cacheable and its modeled inputs produce the same cache key.
When can sharding make CI slower?
When duplicated checkout/JVM/dependency/report overhead is larger than the parallelizable test work.
Why is a persistent runner not automatically unsafe?
It can be governed with explicit caches, immutable images, and clean-room checks; the risk is hidden mutable state, not persistence by itself.
Why is a deployment-stage rebuild a new artifact identity?
Compilation/packaging can vary with toolchain, dependencies, timestamps, environment, or configuration, so byte identity is no longer guaranteed.
What belongs in CI YAML rather than build.gradle.kts?
Provider orchestration such as job permissions, runner selection, artifact handoff, approvals, and provider cache primitives.
Official references and version notes
- Gradle 9.7.1 release notes — pinned Gradle baseline.
- Gradle dependency caching — dependency-cache state and guidance for ephemeral builds.
- Gradle Build Cache — local/remote task-output cache and CI push/read trust model.
- Build Cache use cases — CI-produced cache entries and cross-machine reuse.
-
Gradle task outcomes
—
UP-TO-DATEversusFROM-CACHE. - Gradle on GitLab CI — current Wrapper-first CI guidance and cache considerations.
- Maven release history — Maven 3.9.16 GA baseline.
- Maven Wrapper 3.3.4 — current stable Wrapper baseline.
- Maven Surefire test goal — explicit test selection and failure behavior.
Version-sensitive statements were rechecked against primary documentation on 2026-08-24. Mandatory labs remain local/free; hosted CI, remote caches, artifact repositories, and secret stores are represented as optional production mappings only.
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.