Build once, and let the artifact be the unit that moves
Independent builds can differ even at the same commit. Promoting one artifact by digest makes it clear which bytes were tested, while configuration and runtime differences still need validation.
TL;DR: One build produces one artifact, addressed by content digest. That exact artifact moves through environments, and configuration is injected rather than baked in. A different build does not automatically inherit artifact-specific validation. Reproducible builds can produce identical digests; verify that equality rather than assuming it.
What rebuilding actually costs
Two builds of the same commit are not guaranteed to produce the same thing. A dependency resolved to a newer patch. A base image tag that moved. A build tool version that differs between runners. A timestamp or a build number compiled in.
Most of the time the difference is nothing. The rest of the time it is the incident, and it presents in the worst possible way: the tests passed, the same commit is deployed, and production behaves differently. Nobody suspects the build because the input was identical.
Build once and that entire class disappears. Not reduced, gone, because there is only one artifact and it is the one that was tested.
Address by digest, not by tag
A tag is a mutable pointer. myapp:1.4.2 today and myapp:1.4.2 next month may be different bytes, and latest may move frequently.
A digest is the content. Deploying by digest means the manifest names exactly what will run, a rollback names exactly what ran before, and a signature over the artifact continues to mean something. Every supply-chain control assumes this: provenance, attestation and admission policy are all statements about a specific artifact, and a mutable reference dissolves them.
Tags remain useful as human labels. They are not deployment references.
Configuration is injected, never baked
The corollary that teams get wrong. If the artifact contains the staging database URL, it cannot be the production artifact, and you are back to building per environment through the side door.
So configuration arrives at runtime: environment variables, a mounted file, a config service. The artifact is identical everywhere and its behaviour differs because its inputs differ. That is also what makes a promotion a pointer change rather than a build.
Secrets follow the same rule with more force. A secret baked into an image may remain in a layer, build history or cache even after a later layer deletes it. Anyone with access to that material may recover it. Revoke the exposed credential, clean up retained copies under policy, and rebuild without embedding its replacement.
What promotion becomes
An artifact that has been built once moves by having its digest referenced in the next environment's manifest. That is a small, reviewable diff, it is auditable, and it is reversible by referencing the previous digest.
The chain that follows is worth stating: because the artifact is immutable, the tests that ran against it stay meaningful; because it is addressed by digest, the deployment record is exact; because configuration is external, the same artifact can be the one that was validated. Each property depends on the one before it.
Where it gets hard
Compiled-in configuration in some frameworks, where the build genuinely needs an environment value. Fix it in the framework or accept per-environment builds for that component with the trade written down.
Multi-architecture images, where one tag points at an index of several digests. Reference the index digest and know that it is what you did.
Long-lived artifacts. An artifact deployed for eighteen months contains dependencies with vulnerabilities disclosed since. Immutability is not an argument against rebuilding on a schedule; it is an argument that a rebuild is a new artifact which goes through the pipeline again rather than being patched in place.
The test
Ask whether the bytes running in production were produced by the same build that passed the tests. If the honest answer is "probably", the pipeline is telling you something it cannot know.
Self-check
Two independently produced images have the same verified digest. Must they contain different bytes because they were rebuilt? No. Digest equality identifies the same content; the risk is assuming equality from a commit or tag alone. Environment-specific configuration still needs testing.