Azure / Azure/acr-cli

Proposal: Add Minimum and Maximum Retention Policies to Acr Purge

Open
#670 0 comments 2 reactions 0 assignees View on GitHub
enhancement
Dominant language
Go
Stars
70
Forks
52
Avg merge
3d 2h
Merged PRs (30d)
12

Description

**What is the problem you're trying to solve**

Customers need to combine age-based retention with minimum and maximum count limits.

For example, customers may want either of these behaviors:

- Delete tags older than 3 days or outside the 10 most recent matching tags.
- Delete tags older than 3 days only when they are outside the 10 most recent matching tags.

The existing `--keep` option does not express either policy consistently because it preserves items only from the set already eligible for age-based deletion. Changing its behavior would break existing purge configurations.

**Describe the solution you'd like**

Add explicit minimum and maximum retention options:

| Option | Behavior |
|---|---|
| `--min-tags N` | Protect the newest N matching tags from age-based deletion |
| `--max-tags N` | Retain no more than N matching tags per repository |
| `--min-untagged-manifests N` | Protect the newest N dangling manifests from age-based deletion |
| `--max-untagged-manifests N` | Retain no more than N dangling manifests per repository |

### Maximum retention: OR behavior

```sh
acr purge \
--registry example \
--filter "repository:.*" \
--ago 3d \
--max-tags 10
```

A matching tag is deleted when it is older than 3 days **or** outside the 10 most recent matching tags. This is a hard ceiling; fewer than 10 tags may remain after applying the age policy.

### Minimum retention: AND behavior

```sh
acr purge \
--registry example \
--filter "repository:.*" \
--ago 3d \
--min-tags 10
```

A matching tag is deleted only when it is older than 3 days **and** outside the 10 most recent matching tags. The newest 10 matching tags are protected from age-based deletion.

The same behavior applies independently to dangling manifests:

```sh
acr purge \
--registry example \
--untagged-only \
--ago 3d \
--min-untagged-manifests 20 \
--max-untagged-manifests 100
```

### Combining minimum and maximum retention

Minimum and maximum options may be combined:

```sh
acr purge \
--registry example \
--filter "repository:.*" \
--ago 3d \
--min-tags 10 \
--max-tags 50
```

This creates three retention zones:

1. The newest 10 matching tags are protected from age pruning.
2. Tags 11 through 50 are retained only while newer than 3 days.
3. Tags beyond 50 are deleted regardless of age.

Equivalent selection logic:

```text
delete :=
rank > maxTags
OR
(olderThanAgo AND rank > minTags)
```

**Compatibility and validation**

- Existing `--keep` behavior remains unchanged.
- `--keep` cannot be combined with the new count policies for the same resource.
- `--min-*` requires `--ago`, because it guards age-based deletion and does not select items independently.
- `--max-*` works with or without `--ago`.
- When both are supplied, the minimum must not exceed the maximum.
- Limits apply per repository and effective filter.
- Tag and dangling-manifest limits are independent.
- Items are ranked by `LastUpdateTime`, newest first, with deterministic tie-breaking.
- When using `--untagged`, manifest retention is evaluated after tag deletion.
- Locked items that prevent satisfying a maximum are reported clearly.
- Dry-run output identifies whether deletion is caused by age, maximum count, or both.

Repository-level conditions that determine whether purge runs at all, such as `--purge-if-tags-exceed`, are a separate feature and are not part of this retention proposal.

**Acceptance criteria**

- Age-only, minimum, maximum, and combined policies work for tags and dangling manifests.
- Minimum options provide AND behavior and maximum options provide OR behavior.
- Ranking works across paginated results.
- Existing filters and `--keep` behavior remain compatible.
- Invalid flag combinations produce clear errors.
- Tests cover pagination, filters, locked items, equal timestamps, and manifests made dangling during the purge.

Contributor guide

Open the contributing guide

Research direction

Start with the acr purge entry point and trace the existing --keep behavior, tag and dangling-manifest filtering, ranking, pagination, and dry-run reporting. Use the acceptance criteria as the definition of done: preserve compatibility, validate flag combinations, apply minimum/maximum policies independently, and cover pagination, filters, locked items, equal timestamps, and newly dangling manifests.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.