Artifacts, Retention, and Fingerprints
Scenario: A deployment rebuilds the approved branch and ships bytes different from those tests validated.
What actually gets shipped should never be a guess
Here's a question every delivery pipeline needs a confident answer to: when your team says "we deployed version 1.4.2 to production," can you point to the exact file that was tested, and prove it's the exact file that's now running? If the honest answer is "probably, I think so," that's a real gap this section closes.
Analogy: Think of a wax seal on an old letter. Once a letter is sealed, you can tell with certainty whether it's been opened and tampered with since sealing - the seal is a promise about this specific physical object, not about "a letter like this one." An artifact with a recorded checksum works the same way: it's a promise about one specific set of bytes, verifiable later, not a promise about "whatever code is currently on the main branch that produced something similar." Overwriting a mutable tag like latest is the opposite of a wax seal - it's like relabeling a different letter with the same address and expecting nobody to notice it's not the original.
The core discipline in this whole module is: build once, seal it (checksum it), and carry that exact sealed thing all the way through testing and release - never quietly swap in a similar-looking replacement along the way.
Pipeline example
stage('Package') { steps { sh './package.sh'; archiveArtifacts artifacts: 'dist/*.tgz', fingerprint: true } }
Artifacts identify one specific build output
Release artifacts should be immutable and should carry, at minimum, the source revision, the build identity (which job, which number), the toolchain used, and a checksum. archiveArtifacts copies matched files into Jenkins' own build storage; fingerprint: true additionally records checksums used later to relate producers and consumers of the same file across different jobs. Configure "empty match" and "success only" behavior deliberately: diagnostic files can matter most precisely after a failure (so don't gate them on success), while an actual release package should generally not be archived at all following an invalid or aborted package-building stage.
[Pipeline] archiveArtifacts
Archiving artifacts
Recording fingerprints
$ sha256sum dist/app-1.4.2.tgz
9f86d081884c7d659a2feaa0c55ad015...
That checksum is the "wax seal" from the analogy above, made concrete - anyone downstream can recompute it against the file they actually received and confirm it's bit-for-bit the same file this build produced, not a rebuilt or substituted copy.
Jenkins storage versus a real binary repository
Jenkins' own archive works well for reports and modest-sized outputs. A dedicated binary repository (like Artifactory, Nexus, or a container registry) offers much stronger lifecycle management, distribution, signing, vulnerability-scanning metadata, and access policy specifically built for release artifacts. Do not treat overwriting a mutable coordinate like latest as your only publishing mechanism - publish versioned or content-addressed bytes (an actual version number or digest) as the durable, immutable record, and maintain a separate promotion pointer (like "production currently points at 1.4.2") that can move without ever overwriting the immutable thing it points to.
Retain the full provenance chain, deliberately
Build discarders bound how long build records and archived files are kept on the controller; fingerprint cleanup and the retention policy of an external repository need to be kept in alignment, or you can end up with a repository that still has the binary but a Jenkins build record that's already been purged and can no longer answer "which commit and which test run produced this." If a producing Jenkins build's own record expires before the product's actual support window ends, durable external metadata must independently still be able to connect the deployed digest back to its source commit, its test results, and any approvals it required.
A pitfall: promotion that quietly rebuilds instead of just promoting
A promotion job should accept an artifact digest, verify its signature and any required policy gates, and then mark or copy the existing bytes forward into the next environment - it must never recompile the branch as part of "promoting" it, since that produces genuinely different bytes than whatever was actually tested, even from identical source. During an incident, always compare the deployed digest against the tested digest directly - matching version numbers or friendly tags prove absolutely nothing once a mutable coordinate like latest has been overwritten at some point in between, which is exactly the scenario that leads to "but the version number says it should be fine" confusion during a live outage.
Goal: Practice the concrete behavior in jenkins-artifact-promotion. Learn sections have no Jenkins terminal; the Jenkins lab opens the real shared service in a new full-screen tab inside your private folder.