CI/CD Fundamentals · Module 04 of 12

Reproducible builds, dependencies and cache

Make builds deterministic first, then use dependency caches to improve speed without confusing cache data with release artifacts.

Learning objectives

By the end of this module, you should be able to:

  • Prefer lockfile-driven dependency installation.
  • Distinguish cache from build artifacts.
  • Design cache keys around dependency inputs rather than arbitrary branch names alone.

Reproducibility comes before speed

A pipeline should install the dependency versions described by the repository's lockfile and use controlled toolchain versions. A fast build that changes unpredictably between runs is not a reliable delivery signal.

Caches are performance hints

Dependency caches reduce repeated downloads. They are not authoritative release artifacts and should be safe to miss or recreate. Cache keys should change when the dependency inputs change.

Build outputs need identities

Package outputs with a version, commit SHA or other immutable identifier so a deployment can prove exactly which validated bits were released.

Worked examples

See the idea in practice.

Lockfile-oriented Node build

- uses: actions/setup-node@v7
  with:
    node-version: 22
    cache: npm
- run: npm ci
- run: npm test
  • npm ci consumes the lockfile instead of rewriting dependency resolution.
  • Caching accelerates downloads but the lockfile defines expected dependency versions.
Hands-on lab

Lab — Produce a deterministic artifact identity

Goal: Create a build artifact whose metadata records the source revision.

STEP 1

Create source and lock-style metadata

mkdir -p ~/gnu-cicd-labs/module04/src && cd ~/gnu-cicd-labs/module04
printf 'hello\n' > src/app.txt
printf 'deps=v1\n' > deps.lock
STEP 2

Create source identity

SOURCE_ID=$(sha256sum src/app.txt deps.lock | sha256sum | awk '{print $1}')
printf '%s\n' "$SOURCE_ID" > build-id.txt
STEP 3

Package build

tar -czf app-${SOURCE_ID:0:12}.tgz src deps.lock build-id.txt
STEP 4

Verify package identity

tar -tzf app-*.tgz | sort

Verify

  • The artifact contains source, dependency metadata and build-id.txt.
  • Its filename includes a deterministic identity derived from build inputs.

Expected outcome

  • The build output can be traced back to exact inputs.

If it fails

  • If shell substring syntax differs, use cut -c1-12 instead.
  • Do not include timestamps in an identity if you expect identical inputs to produce the same identifier.
Real-world connection

Traceable artifacts make rollback, audit and incident analysis much easier than deploying an ambiguous latest.zip.

Avoid these traps

Common mistakes

  • Treating a cache hit as proof of correctness.
  • Installing floating dependency versions in CI when a lockfile exists.
  • Publishing artifacts without a source/build identity.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1What should define Node dependency versions in a reproducible build?

The committed lockfile used by an appropriate deterministic install command such as npm ci.

2Is a dependency cache a release artifact?

No. It is a performance optimization that should be safe to rebuild.

3Why attach source identity to artifacts?

To trace deployed bits back to the exact validated inputs.

My Learning

Record your progress for this module.

Progress is saved in this browser immediately. When you sign in to My Learning, it can also sync across devices.

Not started

Attempt the core lab and knowledge checks before marking the module complete.