Keep permanently pinned versions out of retention (fixes #141) #143

Merged
qwc merged 1 commit from fix/retention-protects-pins into main 2026-08-30 20:07:01 +02:00
Owner

Fixes #141. Stacked on #140 — base branch is feature/version-keep-pattern, so this diff shows only the pin fix. Merge #140 first and this retargets to main cleanly.

The bug

enforceRetentionPolicy decided what to delete from the keep rule and the version's age alone — it never looked at projects.pinned_version, and nothing else guarded the delete path. A pinned build that aged out and didn't match the keep rule was deleted like any other, leaving the project pinned to a version that no longer existed.

The dangling pin didn't even surface as an error: project.go:102 falls through to the newest version when the pinned tag is missing, so readers were quietly moved somewhere else.

The fix

A permanent pin now outranks the keep pattern. Pinning permanently is a statement that this is the version people should land on, which is the same claim the keep pattern makes — the two disagreeing is the surprise.

Temporary pins stay unprotected, per your call. That also matches what a temporary pin means: upload.go:221 clears it on the next upload, so it doesn't assert the version is worth keeping long-term — it just says "show this one for now".

Tests

Two cases in internal/handler/version_keep_pattern_test.go: a permanently pinned version surviving retention while a sibling of the same shape expires (so it's the pin doing the work, not the pattern), and a temporarily pinned version expiring like any other.

Docs

how-to/version-retention.md replaces the warning I wrote in #140 with the new behaviour, and how-to/pin-versions.md mentions the exemption under Permanent Pin — that's where someone deciding between pin types will be looking.


Assisted by Claude Opus 5.

Fixes #141. **Stacked on #140** — base branch is `feature/version-keep-pattern`, so this diff shows only the pin fix. Merge #140 first and this retargets to `main` cleanly. ## The bug `enforceRetentionPolicy` decided what to delete from the keep rule and the version's age alone — it never looked at `projects.pinned_version`, and nothing else guarded the delete path. A pinned build that aged out and didn't match the keep rule was deleted like any other, leaving the project pinned to a version that no longer existed. The dangling pin didn't even surface as an error: `project.go:102` falls through to the newest version when the pinned tag is missing, so readers were quietly moved somewhere else. ## The fix A **permanent** pin now outranks the keep pattern. Pinning permanently is a statement that this is the version people should land on, which is the same claim the keep pattern makes — the two disagreeing is the surprise. **Temporary pins stay unprotected**, per your call. That also matches what a temporary pin means: `upload.go:221` clears it on the next upload, so it doesn't assert the version is worth keeping long-term — it just says "show this one for now". ## Tests Two cases in `internal/handler/version_keep_pattern_test.go`: a permanently pinned version surviving retention while a sibling of the same shape expires (so it's the pin doing the work, not the pattern), and a temporarily pinned version expiring like any other. ## Docs `how-to/version-retention.md` replaces the warning I wrote in #140 with the new behaviour, and `how-to/pin-versions.md` mentions the exemption under Permanent Pin — that's where someone deciding between pin types will be looking. --- Assisted by Claude Opus 5.
Retention decided what to delete from the keep rule and the version's
age alone, never consulting projects.pinned_version. A pinned build that
aged out and did not match the keep rule was deleted, leaving the pin
naming a version that no longer existed — and since serving falls
through to the newest version when the pinned tag is missing, readers
were quietly moved elsewhere rather than seeing an error.

A permanent pin now outranks the keep pattern: it is a statement that
this is the version people should land on, which is the same claim the
pattern makes. Temporary pins stay unprotected — the next upload clears
them, so they do not assert the version is worth keeping.

Assisted-by: Claude Opus 5

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marcel M. Otte <marcel.otte@mmo.to>
qwc changed target branch from feature/version-keep-pattern to main 2026-08-30 20:06:48 +02:00
qwc merged commit 41382d6e96 into main 2026-08-30 20:07:01 +02:00
qwc deleted branch fix/retention-protects-pins 2026-08-30 20:07:01 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
qwc-open/asiakirjat!143
No description provided.