Domain 3 β€” Module 2 of 12 17%
9 of 27 overall
Domain 3: Design and implement build and release pipelines Free ⏱ ~6 min read

Versions and Artifacts: Build Once, Promote the Same Bytes

Separate SemVer and CalVer from pipeline run numbers, and carry a uniquely identified artifact through every environment.

The label must identify the actual parcel

If a courier reuses one tracking number for three parcels, the number stops being useful. The same happens when a pipeline publishes every build as latest and a deployment downloads whichever one exists at the time.

A version helps consumers reason about compatibility or release date. A build/run identifier tells you which execution produced an output. A checksum or content digest identifies bytes. These are complementary, not competing concepts.

IdentifierAnswersDoes not prove
SemVer 2.3.1Intended compatibility relative to a declared APITests or correctness
CalVer such as 2026.10.1Release time under a documented conventionBackward compatibility
Pipeline run IDWhich producer execution ranWhich environment received it
Git commitWhich source revision was selectedReproducible dependency resolution
Artifact digestWhether bytes matchWhether those bytes are safe

CalVer has several valid conventions; define yours rather than assuming every date-like label has the same meaning.

Choose compatibility rules intentionally

Under SemVer, a normal MAJOR.MINOR.PATCH version communicates incompatible API changes, backward-compatible additions, and backward-compatible fixes respectively, within the specification’s assumptions. Version zero and prereleases have additional caveats. A number is only useful if the publisher follows its contract.

Dependency ranges trade update convenience against control. A lockfile records a resolved graph for supported package managers, while a range expresses permitted versions. Commit the appropriate lockfile and use the package manager’s reproducible installation mode in CI, such as npm ci for a project with a valid npm lockfile.

Locking does not remove the need for updates. Use reviewed dependency updates, compatibility tests, and vulnerability response rather than letting an unreviewed restore silently choose a new production dependency.

Do not assume SemVer build metadata is supported by every registry format. Azure Artifacts Universal Packages, for example, have their own version restrictions. Validate the package format before turning a pipeline string into a publish command.

Carry provenance through a pipeline

For an illustrative Azure Pipelines run, a unique human-readable run name can include date and revision:

name: $(Date:yyyyMMdd).$(Rev:r)

steps:
- script: npm ci
  displayName: Restore locked dependencies
- script: npm test
  displayName: Test
- script: npm run build
  displayName: Build
- publish: dist
  artifact: booking-web

This example assumes an existing Node toolchain, lockfile, test/build scripts, and a dist output. It is not a universal build for every repository. Rev uniqueness is tied to the run-number format’s changing components; the numeric pipeline run ID is still the robust execution reference.

Publish a manifest with the source commit, producer run ID, dependency lock identity, package/container version, and digest where applicable. Keep configuration names, not secret values, in that manifest.

In a dependent job, downloading the current run’s named artifact keeps build and release connected:

steps:
- download: current
  artifact: booking-web

For a separate release pipeline, select the exact producer pipeline and run, not simply β€œlatest successful” at deployment time. Otherwise test and production can receive different outputs while displaying the same release name.

Separate environment configuration from binaries

Build once, then apply approved environment-specific configuration at deployment/runtime. Rebuilding for production can change dependencies, timestamps, or generated content and invalidates the claim that production received the tested artifact.

Some applications embed environment configuration during compilation. If so, state that constraint and test the actual resulting production artifact; do not claim byte-for-byte promotion when the process deliberately rebuilds.

Container tags can be mutable. A deployment pinned to a digest has a stronger content identity than a tag that can move. A digest still needs provenance and scanning.

Knowledge Check

Staging tested artifact from run 410. Production later downloads 'latest successful', now run 412. What is the defect?

Try it: explain an artifact without opening its source

Prerequisites: a small local project with a lockfile and build output, or read access to an existing sandbox pipeline. CI and registry storage may be billed if you run them.

Create a simple release manifest from actual values in your sandbox: commit, run ID if available, version convention, and SHA-256 of one output file. Repeat the hash without rebuilding. Then identify where a deployment would select that exact output. Do not invent a run ID if no pipeline ran.

Expected observation: the hash is stable for unchanged bytes, and the manifest distinguishes source identity, execution identity, compatibility label, and deployment destination.

Cleanup: remove only your local exercise manifest/output if not needed. If you published a test artifact, use the platform’s run-retention process; do not delete a shared release run.

Question

Does CalVer promise backward compatibility?

Click or press Enter to reveal answer

Decision check: can we delete the producing run?

Azure Pipeline artifacts are associated with their run. Deleting the run deletes those artifacts, so preserve required release outputs using an appropriate retention strategy before deleting evidence.

Read the source