Basic

Pre-releases and release candidates

A pre-release is a build that is allowed to be wrong. It exists so you can test a change before you commit to it, and it is named so nobody mistakes it for the final artifact. The naming is the whole discipline.

What you will see

A fresh build with the final tag. Cache hits are fine; a rename is not.

About 1 min of reading

Try It

Build a candidate and prove it is not reachable

1

Build an rc

docker build -t app:v1.4.0-rc1 .

Before you run it, say out loud what it will print. Then open the answer.

What it prints
A tagged box named with the rc suffix.
2

Ask what latest points at

docker images --format '{{.Tag}}' | grep '^latest$'

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Empty, or a final version. If it points at an rc, the production pointer is wrong.
3

Compare the candidate to final

python -c "from packaging.version import Version as V; print(V('1.4.0-rc1') < V('1.4.0'))"

Before you run it, say out loud what it will print. Then open the answer.

What it prints
True. The ordering is defined, so a version floor excludes candidates automatically.
4

Promote by rebuilding

docker build -t app:v1.4.0 .

Before you run it, say out loud what it will print. Then open the answer.

What it prints
A fresh build with the final tag. Cache hits are fine; a rename is not.
Do not `docker tag app:v1.4.0-rc1 app:v1.4.0`. That renames the candidate and makes it indistinguishable from a tested release.

Data Flow

Candidate to final
1 Build v1.4.0-rc1
↓
2 Run the eval suite against rc1
↓
3 Fix and rebuild rc2 if it fails
↓
4 Rebuild as v1.4.0 only when the suite passes
Why this works
When an rc is worth it

When the change touches something a consumer cannot easily test: a wire format, a database layout, a dependency's version floor. If you can test the final version in one command, skip the rc.

The one rule that matters

No pre-release artifact may be reachable from a production pointer. If latest can point at an rc, the discipline has failed and the naming is doing nothing.

Examples

The suffix sorts first

1.4.0-rc1 < 1.4.0-rc2 < 1.4.0. A consumer that accepts '>=1.4.0' will not accept any rc. That is the guard that keeps a candidate out of production.

Tag the box, not the branch

docker build -t app:v1.4.0-rc1 . puts the label on the artifact. If only the git branch says rc, the artifact in the registry looks final.

Promote by rebuilding, not renaming

When rc2 passes, build v1.4.0 fresh. Renaming a box hides the fact that its inputs were never re-checked, and a rename is indistinguishable from a final release.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Writing a changelog people can act on
Previous Lesson
Writing a changelog people can act on
Next Lesson
Pinning a dependency floor
Pinning a dependency floor →