Skip to content

Prune stale ephemeral Docker Hub tags weekly - #349

Merged
velaraptor-runpod merged 1 commit into
mainfrom
feat/prune-stale-docker-tags
Sep 28, 2026
Merged

velaraptor-runpod merged 1 commit into
mainfrom
feat/prune-stale-docker-tags

Conversation

@velaraptor-runpod

Copy link
Copy Markdown
Contributor

Summary

CI pushes a unique image tag per run and nothing ever deletes them:
test-<sha> on every push to main, test-<model_slug>-<run_id> per PR smoke test, and dev-<branch> per branch. The repo currently holds 211 tags, 112 of them ephemeral leftovers (verified live via dry run).

  • scripts/prune_docker_tags.py — deletes test-* / dev-* tags not updated in the last --min-age-days (default 14) via the Docker Hub API (there is no native tag-retention policy). Releases (v1.2.3 / 1.2.3) and latest match no configured prefix, so they are protected by construction. --dry-run needs no credentials.
  • .github/workflows/prune-docker-tags.yml — weekly schedule (Mondays 04:17 UTC) plus workflow_dispatch with min_age_days and dry_run inputs. Reuses the existing DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secrets.
  • tests/test_prune_docker_tags.py — unit tests plus an end-to-end run against a local stub Docker Hub server that records real HTTP traffic.
  • Docs updated in docs/conventions.md and .github/CONTRIBUTING.md.

Safety

  • An empty --prefix previously made name.startswith("") true for every tag, releases included — now rejected before any network call.
  • Tag names are URL-quoted in the delete request.
  • Unparseable/missing timestamps are kept rather than assumed old.

Test plan

  • python -m pytest tests → 114 passed (on this branch's origin/main base).
  • Verified the tests catch regressions: removing the prefix filter fails 7 tests; disabling the empty-prefix guard fails 2.
  • Live read-only dry run against runpod/worker-v1-vllm → 211 tags, 112 candidates, releases preserved.
  • Run the workflow once manually with dry_run: true to confirm the CI path and secret scope before the first real deletion.

Note: the delete path is exercised against a stub server, not the real API (no credentials in the dev environment), and the schedule only arms once this lands on the default branch. DOCKERHUB_TOKEN must carry delete scope on the repository.

CI pushes a unique image tag per run — `test-<sha>` on every push to main,
`test-<model_slug>-<run_id>` per PR smoke test — and a `dev-<branch>` tag per
branch. Nothing ever deletes them, so the repository has accumulated 211 tags,
112 of them ephemeral leftovers.

Add scripts/prune_docker_tags.py plus a weekly workflow that removes `test-*`
/ `dev-*` tags not updated in the last 14 days. Releases (`v1.2.3` / `1.2.3`)
and `latest` match no configured prefix, so they are protected by
construction; an empty prefix is rejected outright since it would match every
tag. Deletes go through the Docker Hub API (there is no native retention
policy), using the existing DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secrets.

The workflow also supports manual runs with a `dry_run` input to preview the
deletion list.
@velaraptor-runpod
velaraptor-runpod merged commit 9643c85 into main Sep 28, 2026
12 checks passed
@velaraptor-runpod
velaraptor-runpod deleted the feat/prune-stale-docker-tags branch September 28, 2026 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants