Caching
Why a build with nothing new to do does nothing, and the one cache that works differently.
There are two caches, and they work on different principles. The difference matters the first time one of them surprises you.
The invocation cache
Every step is a function from input content to output content. Ask for the same step with the same inputs and the node returns the answer it already has, without running anything.
This is exact rather than clever. There is no invalidation, because nothing can change underneath an input: different content is a different address, and a different address is a different question.
What it means day to day: after a build, rebuild costs nothing. Change one member and only what depended on it re-runs. Change a base image and everything built on it re-runs, which is correct and occasionally expensive.
bldr build --no-cache --name "cold" # skip the lookup, still store results
bldr cache stats--no-cache is the safe way to force a cold build. It skips the lookup for one
build and still stores what it computes, so it repopulates rather than
discarding.
Cache volumes
The other kind. A cache volume is a writable directory a pod gets, kept
between runs and written back when the pod exits. It is how cargo and npm
keep their incremental state.
The critical property: a volume carries a name, never content. The name is part of the pod's spec and therefore part of its cache key; the content is not.
That is the whole safety argument. A cache volume cannot change what a build produces, only how long producing it takes. If it could, the invocation cache would be unsound.
pod.cache(cacheVolume("my-member/cargo-target"), "/target");Namespacing is yours to do. Two builds naming the same volume mean the same volume, which is the point when they are the same build on two machines and a problem when they are not.
A cache invalidated by timestamp rather than by content needs
{ perImage: true }. Content baked into an image carries an mtime of zero,
because capture normalises it, while a cached build output carries the real
time it was written. A tool comparing the two concludes the baked file is older
and reuses what it built last time, even though the image changed underneath
it. Scoping the volume to the image makes an image change start cold, which is
what an image change means for a build directory anyway.