Skip to content

Add count-based release retention (keep newest N per channel)

Placeholder ppxd requested to merge feat/release-retention-count into main

Summary

  • Add an Items unit to RetentionPolicyUnit so a lifecycle can keep a limited number of releases per channel instead of a time window. Purely additive (ordinal 4) — existing units keep their values.
  • When Items is active, RetentionPolicyEnforcer keeps the newest N releases per channel and cascade-deletes the rest: each pruned release takes its deployments + server-task data (task, activity log, task log, interruptions, checkpoints) + completions + ReleaseSelectedPackage rows with it, then its process/variable snapshots are ref-count-GC'd (a snapshot still referenced by a surviving release is kept).
  • Currently-deployed releases and releases with an in-progress (non-terminal) deployment are always preserved, even beyond N.
  • The existing time-based path is unchanged; its guarded release/package delete is now factored into a shared helper used by both paths.

Safety / non-breaking

  • Opt-in: the unit only takes effect when a lifecycle disables keep-forever. The default (ReleaseRetentionKeepForever = true) prunes nothing.
  • A non-positive keep count is treated as keep-forever (no-op), never "delete everything".
  • Pruned deployments are captured at read time and deleted by id; the release/package delete re-checks for referencing deployments at delete time. A release that gains a deployment concurrently is skipped rather than orphaned, and an in-flight deploy is never killed.
  • Children are deleted before the release/deployment anchor, so a mid-sequence crash leaves the anchor for the next run to retry idempotently.
  • No schema change — the unit is stored as the existing integer enum column.

Test plan

  • Unit (RetentionPolicyEnforcerTests): GetReleasesExceedingCount matrix — keep-N-per-channel, per-channel independence, preserved-beyond-window, fewer-than-N, CreatedDate tie broken by id, empty, all-preserved, keep-zero contract; plus a pin that Items makes per-environment deployment pruning a no-op (cleanup defers to the release cascade).
  • Integration (ReleaseRetentionCountTests, real Postgres): oldest-beyond-N pruned with snapshot GC; full deployment cascade (deployment + task data + completion + packages + snapshot); currently-deployed preserved beyond N; in-progress deployment preserved beyond N; per-channel keep-N; shared snapshot kept by ref-count; keep-forever prunes nothing; keep-count-zero prunes nothing.
  • Full unit suite green (5752/5752).
  • All retention integration tests green (19/19: time-based + task-cleanup + count-based).
  • Full solution builds with 0 errors.

Merge request reports

Loading