Skip to content

✨ feat(policy): evaluate repository retention plans#609

Open
gaborbernat wants to merge 3 commits into
tox-dev:mainfrom
gaborbernat:feat/evaluate-repo-retention-plans-481
Open

✨ feat(policy): evaluate repository retention plans#609
gaborbernat wants to merge 3 commits into
tox-dev:mainfrom
gaborbernat:feat/evaluate-repo-retention-plans-481

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Jul 18, 2026

Copy link
Copy Markdown
Member

Operators need to know which artifacts a retention policy would keep and which it would remove before anything deletes them. This adds the evaluation half of that feature, reading one metadata snapshot, applying the configured rules, and returning an ordered plan. It computes and reports decisions only. Applying a plan, exposing it over HTTP or the CLI (#482), and reclaiming bytes stay out of scope, and this planner is built for #482 to consume without rebuilding it.

The engine lives in peryx-policy and stays ecosystem-neutral. A policy holds two ordered rule groups, keep and expire, with selectors for age, source, project prefix, keep-latest count, cache, trash, and orphan state. A keep rule wins over a matching expire rule, the precedence Google Artifact Registry cleanup policies define, and every decision names the rule that decided it. 📋 Candidates carry a caller-assigned version rank, so the engine orders keep-latest and its output without naming a package format; decisions sort by rank, then artifact, then digest, so repeating an evaluation over the same snapshot and policy produces byte-identical output. Each removal records its estimated bytes and the project's surviving versions, and the plan carries a policy version and a metadata frontier a later apply step reads to reject stale input.

The peryx-ecosystem-pypi adapter feeds that engine. It scans an index's hosted upload records in key order, groups each project's files, ranks their releases newest-first under PEP 440 (pre-release, local, and invalid legacy versions all get a documented position), and streams one project's decisions before reading the next. 🔒 The scan opens read transactions only and never enumerates backend blobs, so an interrupted evaluation writes no metadata or blob state. Evaluation stays linearithmic in the number of records, so a million-file repository plans in well under a second.

The ecosystem boundary sits at PyPI hosted uploads, the surface #481 scopes through PEP 440. The neutral engine is ready for an OCI adapter, but OCI carries no per-artifact publish time or yank state, so its age and visibility signals need a separate design; cached-page eviction and blob reclamation are their own concerns (#571-#573). This planner covers #481; the OCI adapter and the API and CLI surface remain follow-ups.

Closes #481

@gaborbernat gaborbernat added documentation Improvements or additions to documentation enhancement New feature or request labels Jul 18, 2026
@read-the-docs-community

read-the-docs-community Bot commented Jul 18, 2026

Copy link
Copy Markdown

@gaborbernat
gaborbernat enabled auto-merge (squash) July 18, 2026 03:17
@gaborbernat
gaborbernat disabled auto-merge July 18, 2026 03:18
@gaborbernat
gaborbernat enabled auto-merge (squash) July 18, 2026 03:18
@codspeed-hq

codspeed-hq Bot commented Jul 18, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 32 untouched benchmarks
⏩ 94 skipped benchmarks1


Comparing gaborbernat:feat/evaluate-repo-retention-plans-481 (2ba75cd) with main (9adc775)

Open in CodSpeed

Footnotes

  1. 94 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@gaborbernat
gaborbernat force-pushed the feat/evaluate-repo-retention-plans-481 branch from 3f13b9c to 5e98e34 Compare July 18, 2026 04:00
Add an ecosystem-neutral retention planner. A policy holds ordered
keep and expire rule groups; the engine evaluates one project's
candidates and returns a deterministic decision per artifact without
reading storage.

A keep rule wins over an expire rule, matching Google Artifact
Registry cleanup precedence, and each decision names the rule that
decided it. Candidates carry a caller-assigned version rank, so the
engine orders keep-latest and output without naming a package format.
Decisions sort by rank, artifact, then digest, so repeating an
evaluation yields byte-identical output.

A criterion bench plans a generated million-record repository to hold
evaluation linearithmic.

Refs tox-dev#481
Adapt an index's hosted upload records into neutral retention
candidates and stream their decisions. Uploads scan in key order, so a
project's files group without a second pass; the adapter ranks each
project's releases newest-first under PEP 440 and collapses equal
spellings to one rank.

The scan reads only indexed metadata, so an interrupted evaluation
writes nothing. The result carries the policy version and the metadata
frontier a later apply step needs to reject stale input.

Refs tox-dev#481
Describe the rule syntax, keep-over-expire precedence, PEP 440 version
ordering, byte estimates, snapshot and policy identity, the output
schema, and the side-effect-free contract.

Refs tox-dev#481
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate repository retention plans

1 participant