Pin to the Last-Good Version With an Exit Plan
A version pin with a trigger, rationale, and unpin condition looks complete, but proving the regression is real and the target is not EOL is the real work.
We pinned to alpine:3.20 with a textbook exit note: trigger, rationale, unpin condition. All three fields filled in. Perfect. Except the “regression” (a bug introduced by an update) wasn’t real, and 3.20 was already EOL (End of Life — no longer patched).
Pinning past an upstream regression is fine. Pinning silently is the trap. A pin with no exit note becomes a stale freeze nobody remembers to lift. Record three things next to the pin:
- Trigger: what forced the move (“go.mod → 1.25 pulled a newer Alpine / libvips”)
- Why this version: what’s known-good and how you verified it
- Unpin condition: the concrete event that lets you drop it
The exit condition is what separates a deliberate temporary pin from accidental rot.
Before you pin, prove the regression is real. A pin inherits the correctness of the diagnosis beneath it. Verify with a production-shaped input first (see A test result is FACT only about its input). Pinning past a non-bug freezes you for nothing.
Then check if “last-good” is EOL. The newest version that passes your test may already be end-of-life, trading a real CVE stream (publicly disclosed security fixes) for the fix (see An EOL base image silently no-ops security upgrades).
Both gates were skipped, and either one would have stopped the episode on its own: Gate 1 because the regression wasn’t real, Gate 2 because 3.20 was EOL. The exit note (the one part done properly) was the least important part.
A pin’s exit plan is the easiest part to write; proving you have something worth pinning is the real work.
Sources:
Related: Back to the chain reaction overview, or see a test result is FACT only about its input and EOL base image risks.