ghcr-cleanup-manager 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +356 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/cleanup-summary/_cleanup-summary-markdown.d.ts +5 -0
- package/dist/cleanup-summary/_cleanup-summary-markdown.js +224 -0
- package/dist/cleanup-summary/_cleanup-summary.d.ts +56 -0
- package/dist/cleanup-summary/_cleanup-summary.js +59 -0
- package/dist/cleanup-summary/index.d.ts +2 -0
- package/dist/cleanup-summary/index.js +2 -0
- package/dist/cli/_args.d.ts +7 -0
- package/dist/cli/_args.js +41 -0
- package/dist/cli/_cleanup-command.d.ts +1 -0
- package/dist/cli/_cleanup-command.js +142 -0
- package/dist/cli/_db-merge-command.d.ts +1 -0
- package/dist/cli/_db-merge-command.js +41 -0
- package/dist/cli/_github-output.d.ts +10 -0
- package/dist/cli/_github-output.js +13 -0
- package/dist/cli/_json-output.d.ts +1 -0
- package/dist/cli/_json-output.js +11 -0
- package/dist/cli/_logger.d.ts +10 -0
- package/dist/cli/_logger.js +26 -0
- package/dist/cli/_older-than.d.ts +5 -0
- package/dist/cli/_older-than.js +42 -0
- package/dist/cli/_planner-options.d.ts +20 -0
- package/dist/cli/_planner-options.js +83 -0
- package/dist/cli/_scan-command.d.ts +1 -0
- package/dist/cli/_scan-command.js +39 -0
- package/dist/cli/_tag-selector-resolver.d.ts +3 -0
- package/dist/cli/_tag-selector-resolver.js +132 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +52 -0
- package/dist/config/_service-constants.d.ts +3 -0
- package/dist/config/_service-constants.js +3 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +9 -0
- package/dist/core/_digest-tag.d.ts +2 -0
- package/dist/core/_digest-tag.js +12 -0
- package/dist/core/_github-package-owner.d.ts +11 -0
- package/dist/core/_github-package-owner.js +45 -0
- package/dist/core/_http-error.d.ts +6 -0
- package/dist/core/_http-error.js +33 -0
- package/dist/core/_types.d.ts +54 -0
- package/dist/core/_types.js +8 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +4 -0
- package/dist/db/_cleanup-run-writer.d.ts +10 -0
- package/dist/db/_cleanup-run-writer.js +113 -0
- package/dist/db/_db-merge-cleanup-copy.d.ts +7 -0
- package/dist/db/_db-merge-cleanup-copy.js +172 -0
- package/dist/db/_db-merge-history.d.ts +2 -0
- package/dist/db/_db-merge-history.js +15 -0
- package/dist/db/_db-merge-repository.d.ts +8 -0
- package/dist/db/_db-merge-repository.js +95 -0
- package/dist/db/_db-merge-scan-copy.d.ts +10 -0
- package/dist/db/_db-merge-scan-copy.js +70 -0
- package/dist/db/_db-merge-types.d.ts +44 -0
- package/dist/db/_db-merge-types.js +1 -0
- package/dist/db/_github-actions-run-url.d.ts +1 -0
- package/dist/db/_github-actions-run-url.js +9 -0
- package/dist/db/_manifest-reachability.d.ts +2 -0
- package/dist/db/_manifest-reachability.js +158 -0
- package/dist/db/_scan-writer.d.ts +20 -0
- package/dist/db/_scan-writer.js +184 -0
- package/dist/db/_schema.d.ts +2 -0
- package/dist/db/_schema.js +19 -0
- package/dist/db/_snapshot-repository.d.ts +24 -0
- package/dist/db/_snapshot-repository.js +86 -0
- package/dist/db/_sql-placeholders.d.ts +2 -0
- package/dist/db/_sql-placeholders.js +16 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.js +13 -0
- package/dist/db/planner/_planner-direct-target-root-options.d.ts +11 -0
- package/dist/db/planner/_planner-direct-target-root-options.js +1 -0
- package/dist/db/planner/_planner-direct-target-root-tag-filters.d.ts +7 -0
- package/dist/db/planner/_planner-direct-target-root-tag-filters.js +41 -0
- package/dist/db/planner/_planner-direct-target-roots-combined-sql.d.ts +7 -0
- package/dist/db/planner/_planner-direct-target-roots-combined-sql.js +189 -0
- package/dist/db/planner/_planner-direct-target-roots-combined.d.ts +4 -0
- package/dist/db/planner/_planner-direct-target-roots-combined.js +10 -0
- package/dist/db/planner/_planner-direct-target-roots-tagged.d.ts +4 -0
- package/dist/db/planner/_planner-direct-target-roots-tagged.js +117 -0
- package/dist/db/planner/_planner-direct-target-roots.d.ts +8 -0
- package/dist/db/planner/_planner-direct-target-roots.js +17 -0
- package/dist/db/planner/_planner-direct-target-tags.d.ts +6 -0
- package/dist/db/planner/_planner-direct-target-tags.js +54 -0
- package/dist/db/planner/_planner-latest-scan.d.ts +10 -0
- package/dist/db/planner/_planner-latest-scan.js +20 -0
- package/dist/db/planner/_planner-output.d.ts +5 -0
- package/dist/db/planner/_planner-output.js +111 -0
- package/dist/db/planner/_planner-plan-artifacts-blocked-roots-sql.d.ts +1 -0
- package/dist/db/planner/_planner-plan-artifacts-blocked-roots-sql.js +110 -0
- package/dist/db/planner/_planner-plan-artifacts-closure-sql.d.ts +1 -0
- package/dist/db/planner/_planner-plan-artifacts-closure-sql.js +188 -0
- package/dist/db/planner/_planner-plan-artifacts-supported-untag-only-sql.d.ts +1 -0
- package/dist/db/planner/_planner-plan-artifacts-supported-untag-only-sql.js +86 -0
- package/dist/db/planner/_planner-plan-artifacts.d.ts +7 -0
- package/dist/db/planner/_planner-plan-artifacts.js +109 -0
- package/dist/db/planner/_planner-repository.d.ts +44 -0
- package/dist/db/planner/_planner-repository.js +105 -0
- package/dist/db/planner/_planner-sql.d.ts +12 -0
- package/dist/db/planner/_planner-sql.js +46 -0
- package/dist/db/planner/_planner-tag-selectors.d.ts +8 -0
- package/dist/db/planner/_planner-tag-selectors.js +57 -0
- package/dist/db/planner/_planner-types.d.ts +144 -0
- package/dist/db/planner/_planner-types.js +49 -0
- package/dist/db/planner/index.d.ts +3 -0
- package/dist/db/planner/index.js +2 -0
- package/dist/execute/_http.d.ts +7 -0
- package/dist/execute/_http.js +48 -0
- package/dist/execute/_manifest-detach.d.ts +4 -0
- package/dist/execute/_manifest-detach.js +31 -0
- package/dist/execute/_package-version-delete-client.d.ts +4 -0
- package/dist/execute/_package-version-delete-client.js +34 -0
- package/dist/execute/_package-version-page-client.d.ts +14 -0
- package/dist/execute/_package-version-page-client.js +64 -0
- package/dist/execute/_package-version-tag-source-client.d.ts +12 -0
- package/dist/execute/_package-version-tag-source-client.js +65 -0
- package/dist/execute/_plan-executor.d.ts +3 -0
- package/dist/execute/_plan-executor.js +69 -0
- package/dist/execute/_registry-manifest-client.d.ts +12 -0
- package/dist/execute/_registry-manifest-client.js +79 -0
- package/dist/execute/_registry-token-client.d.ts +4 -0
- package/dist/execute/_registry-token-client.js +37 -0
- package/dist/execute/_types.d.ts +34 -0
- package/dist/execute/_types.js +1 -0
- package/dist/execute/_untag-client.d.ts +2 -0
- package/dist/execute/_untag-client.js +30 -0
- package/dist/execute/index.d.ts +5 -0
- package/dist/execute/index.js +3 -0
- package/dist/ingest/github/_manifest-client.d.ts +14 -0
- package/dist/ingest/github/_manifest-client.js +108 -0
- package/dist/ingest/github/_manifest-ingest.d.ts +3 -0
- package/dist/ingest/github/_manifest-ingest.js +90 -0
- package/dist/ingest/github/_manifest-kind.d.ts +26 -0
- package/dist/ingest/github/_manifest-kind.js +65 -0
- package/dist/ingest/github/_package-metadata-load.d.ts +5 -0
- package/dist/ingest/github/_package-metadata-load.js +45 -0
- package/dist/ingest/github/_package-version-page-load.d.ts +13 -0
- package/dist/ingest/github/_package-version-page-load.js +55 -0
- package/dist/ingest/github/_packages-client.d.ts +10 -0
- package/dist/ingest/github/_packages-client.js +76 -0
- package/dist/ingest/github/_parallel-paginated-ingest.d.ts +12 -0
- package/dist/ingest/github/_parallel-paginated-ingest.js +49 -0
- package/dist/ingest/github/_registry-token-client.d.ts +6 -0
- package/dist/ingest/github/_registry-token-client.js +67 -0
- package/dist/ingest/github/_shared.d.ts +28 -0
- package/dist/ingest/github/_shared.js +70 -0
- package/dist/ingest/github/index.d.ts +11 -0
- package/dist/ingest/github/index.js +29 -0
- package/package.json +78 -0
- package/resources/sql/schema/001_schema.sql +222 -0
- package/resources/sql/views/001_v_latest_scan_per_package.sql +27 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
|
|
6
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [v1.1.0] - 2026-06-14
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Renamed the project from ghcr-manager to ghcr-cleanup-manager because the old repo name was not showing up in GitHub
|
|
15
|
+
Marketplace searches for "ghcr clean" and "ghcr cleanup".
|
|
16
|
+
- Kept the current behavior unchanged for this release; this version is intended as the first release under the new
|
|
17
|
+
name.
|
|
18
|
+
|
|
19
|
+
## [v1.0.8] - 2026-06-11
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Marketplace-facing action metadata and README opening copy now lead more directly with GHCR cleanup terminology.
|
|
24
|
+
- User-facing docs and related metadata now use the product name `GHCR Cleanup Manager` more consistently.
|
|
25
|
+
- The main README's visualizer demo section now also points to Docker-based visualizer usage.
|
|
26
|
+
|
|
27
|
+
## [v1.0.7] - 2026-06-08
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Added a release-published Docker image for `ghcr-cleanup-manager-visualizer` on GHCR, tagged as `vX.Y.Z`, `vX`, and
|
|
32
|
+
`latest`.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- The visualizer release image now defaults to container-friendly startup behavior and is smoke-tested through the real
|
|
37
|
+
server entrypoint during release publishing.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Cleanup now blocks selected `sha-tag` helper roots when they still point into retained manifests, so signature helper
|
|
42
|
+
artifacts needed by surviving images are no longer deleted as ordinary untagged roots.
|
|
43
|
+
- `exclude-tags` in cleanup is now tag-scoped instead of root-scoped, so excluding one sibling tag no longer silently
|
|
44
|
+
protects the whole root from partial untagging.
|
|
45
|
+
|
|
46
|
+
## [v1.0.6] - 2026-06-07
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- Fixed the published `ghcr-cleanup-manager-visualizer` npm package so the visualizer UI loads correctly when run via
|
|
51
|
+
`npx ghcr-cleanup-manager-visualizer`.
|
|
52
|
+
|
|
53
|
+
## [v1.0.5] - 2026-06-07
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- Fixed the published `ghcr-cleanup-manager-visualizer` npm package so `npx ghcr-cleanup-manager-visualizer` starts the
|
|
58
|
+
visualizer server correctly.
|
|
59
|
+
|
|
60
|
+
## [v1.0.4] - 2026-06-06
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- Added user-facing cleanup behavior documentation, including the tag-based protection model, graph-aware cleanup
|
|
65
|
+
explanation, and digest-pull caveats.
|
|
66
|
+
- Added a visualizer grid toggle so graphs can be aligned for screenshots.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- Visualizer screenshots and graph-related docs were refreshed.
|
|
71
|
+
- The visualizer graph area now uses a simpler, cleaner white background.
|
|
72
|
+
- Cleanup summary Markdown now uses an updated index icon label in its rendered output.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- Fixed the published `ghcr-cleanup-manager-visualizer` npm package so `npx ghcr-cleanup-manager-visualizer` runs
|
|
77
|
+
correctly under Node.
|
|
78
|
+
|
|
79
|
+
## [v1.0.3] - 2026-06-05
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- Added npm package keywords for both `ghcr-cleanup-manager` and `ghcr-cleanup-manager-visualizer` to improve package
|
|
84
|
+
discovery.
|
|
85
|
+
|
|
86
|
+
## [v1.0.2] - 2026-06-05
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- Visualizer compare mode now prefers the older/base scan for manifest details and labels, so unchanged manifests keep
|
|
91
|
+
platform metadata such as `arch:` even when the newer scan no longer has the descriptor context.
|
|
92
|
+
|
|
93
|
+
## [v1.0.1] - 2026-06-05
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
|
|
97
|
+
- The GitHub release job now grants correct permissions.
|
|
98
|
+
|
|
99
|
+
## [v1.0.0] - 2026-06-05
|
|
100
|
+
|
|
101
|
+
`v1.0.0` is the first stable `v1.x` release of `ghcr-cleanup-manager`.
|
|
102
|
+
|
|
103
|
+
This milestone reflects the current project shape after repeated live testing, cleanup-planner tuning, visualizer
|
|
104
|
+
refinement, and a full documentation pass.
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
|
|
108
|
+
- Added one merged graph-scenario SQLite database to the GitHub release assets as
|
|
109
|
+
`ghcr-cleanup-manager-release-scenarios.sqlite`, so users can explore real before/after cleanup cases immediately in
|
|
110
|
+
the visualizer.
|
|
111
|
+
- Added dedicated user docs for live test scenarios, package setup, and the workflow-to-visualizer path.
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
- The release workflow now builds and attaches the merged scenario DB as part of the GitHub release publish flow.
|
|
116
|
+
- Visualizer docs are now centered on one canonical `visualizer/README.md`, with richer screenshots and a release-asset
|
|
117
|
+
quick-demo path.
|
|
118
|
+
- README and companion docs now explain the stable action/CLI/visualizer workflows more directly, including permission
|
|
119
|
+
guidance for dry-runs versus live cleanup and explicit Node.js 24 requirements for local npm installs.
|
|
120
|
+
- Visualizer node labeling was clarified so manifest metadata is easier to interpret during graph inspection.
|
|
121
|
+
|
|
122
|
+
## [0.9.10] - 2026-06-04
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
|
|
126
|
+
- Cleanup planning for large package databases is much faster while preserving the existing cleanup behavior.
|
|
127
|
+
- On a large validation package with more than 100k manifests, dry-run planning and summary generation dropped from more
|
|
128
|
+
than 20 minutes to roughly 15 seconds.
|
|
129
|
+
|
|
130
|
+
### Fixed
|
|
131
|
+
|
|
132
|
+
- Internal GHCR validation workflows now avoid GitHub's "cannot delete the last tagged version" failure mode during
|
|
133
|
+
temporary-tag cleanup.
|
|
134
|
+
|
|
135
|
+
## [0.9.9] - 2026-05-30
|
|
136
|
+
|
|
137
|
+
No additional user-facing changes were introduced beyond `0.9.8`.
|
|
138
|
+
|
|
139
|
+
This version number exists because a release attempt consumed `0.9.9` on npm.org, so later publishes must continue from
|
|
140
|
+
a newer version.
|
|
141
|
+
|
|
142
|
+
## [0.9.8] - 2026-06-03
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
|
|
146
|
+
- Added dedicated graph-matrix GHCR scenarios and workflows to exercise shared-image, multi-arch, cosign, and
|
|
147
|
+
attestation cleanup cases in isolation.
|
|
148
|
+
- Added a local manifest-graph visualizer with browser UI for `ghcr-cleanup-manager` SQLite databases, including
|
|
149
|
+
manifest details, zoom controls, one-hop expansion, and scan-to-scan compare mode.
|
|
150
|
+
- Added a separately publishable npm package, `ghcr-cleanup-manager-visualizer`, plus user-facing visualizer
|
|
151
|
+
documentation.
|
|
152
|
+
- Added repo-local manual visualizer demo scripts for seeding and updating GHCR packages during graph investigation.
|
|
153
|
+
|
|
154
|
+
### Changed
|
|
155
|
+
|
|
156
|
+
- Cleanup planning was reworked around the current graph model, including direct SQL-backed tagged/untagged root
|
|
157
|
+
selection, graph-scoped closure walking, and refined `untag-only` vs `fully-deletable` decisions for complex
|
|
158
|
+
multi-arch, cosign, and attestation shapes.
|
|
159
|
+
- Large planner SQL bodies were split into smaller internal modules, and direct-target root selection logic was split
|
|
160
|
+
into smaller planner helpers.
|
|
161
|
+
- Orphaned digest-tag resolution now uses a direct latest-scan query instead of relying on older helper views.
|
|
162
|
+
- Manifest platform display now derives from descriptor data in the visualizer instead of relying on manifest-level
|
|
163
|
+
platform fields.
|
|
164
|
+
- Cross-architecture terminology is now consistently named `multi-arch` across runtime, tests, and docs.
|
|
165
|
+
- The root action and public CLI surface are now centered on `scan` and `cleanup` only.
|
|
166
|
+
|
|
167
|
+
### Fixed
|
|
168
|
+
|
|
169
|
+
- Fixed digest-tag helper-edge direction and root-detection behavior so helper-tagged artifacts no longer interfere with
|
|
170
|
+
normal cleanup root semantics.
|
|
171
|
+
- Fixed shared-graph cleanup handling so selected indexes and helper-linked artifacts are deleted or retained according
|
|
172
|
+
to surviving real tags instead of simplistic descendant-only closure rules.
|
|
173
|
+
|
|
174
|
+
### Removed
|
|
175
|
+
|
|
176
|
+
- The public `untag` CLI command, root-action mode, and dedicated direct-untag workflow coverage were removed. Internal
|
|
177
|
+
tag detachment for partial-tag cleanup matches remains part of `cleanup`.
|
|
178
|
+
- Several older cleanup helper views were removed after the planner rewrite moved the live logic into direct SQL query
|
|
179
|
+
paths.
|
|
180
|
+
|
|
181
|
+
## [0.9.7] - 2026-05-23
|
|
182
|
+
|
|
183
|
+
### Added
|
|
184
|
+
|
|
185
|
+
- The root action now prepares `cleanup` and `untag` CLI arguments through `tools/prepare-action-args.mjs`, keeping
|
|
186
|
+
printed and executed argument lists aligned.
|
|
187
|
+
- Cleanup planning now traverses recursively beyond `sha256-*` helper-tag manifest links as well, if deeper helper
|
|
188
|
+
chains ever occur.
|
|
189
|
+
|
|
190
|
+
### Changed
|
|
191
|
+
|
|
192
|
+
- Cleanup dry-run output and GitHub step summaries were reworked to explain the plan more clearly, including a filters
|
|
193
|
+
table and clearer counts for tags, images, and cross-arch manifests.
|
|
194
|
+
- Informational manifest classification was tuned so only real multi-arch roots are labeled `multi_arch_manifest`, while
|
|
195
|
+
helper-tagged indexes remain `index_manifest`.
|
|
196
|
+
- `merge-run-artifacts` now uses a simpler current-run download flow with direct artifact download handling.
|
|
197
|
+
- Cleanup selected-tag audit and DB-merge metadata handling were tightened alongside the summary/output refactor.
|
|
198
|
+
|
|
199
|
+
### Fixed
|
|
200
|
+
|
|
201
|
+
- `delete-orphaned-images` now carries orphaned `sha256-*` digest-tag targets through planner selection instead of
|
|
202
|
+
dropping them at the normal non-digest tag boundary.
|
|
203
|
+
- Fully deletable cleanup execution now deletes the planned closure package versions instead of deleting only the root
|
|
204
|
+
package version.
|
|
205
|
+
|
|
206
|
+
## [0.9.6] - 2026-05-21
|
|
207
|
+
|
|
208
|
+
### Added
|
|
209
|
+
|
|
210
|
+
- Cleanup audit now persists concrete selected tags in `cleanup_selected_tags`.
|
|
211
|
+
- Cleanup schema docs now include a readable cleanup-decision view plus example SQL queries for audit inspection.
|
|
212
|
+
- GHCR digest-tag helper relations are now modeled explicitly in scan data and manifest reachability.
|
|
213
|
+
|
|
214
|
+
### Changed
|
|
215
|
+
|
|
216
|
+
- Cleanup summary JSON now exposes derived affected manifests for fully deletable roots.
|
|
217
|
+
- Cleanup Markdown now reads displayed counts from the summary arrays instead of carrying duplicate count fields.
|
|
218
|
+
- Cleanup decision audit fields are now constrained more tightly in SQLite and TypeScript, including `selection_mode`,
|
|
219
|
+
`selection_reason`, and related block reason codes.
|
|
220
|
+
- Digest-tag helper artifacts are now classified on `tags.is_digest_tag` and excluded from normal user-facing tag
|
|
221
|
+
selection and output.
|
|
222
|
+
- Digest-tag helper terminology was simplified across code and SQL surfaces.
|
|
223
|
+
- Schema docs now include a table of contents and collapsible example query blocks for easier GitHub browsing.
|
|
224
|
+
|
|
225
|
+
### Fixed
|
|
226
|
+
|
|
227
|
+
- Fixed remote action path handling for artifact upload and merge helper actions.
|
|
228
|
+
- Cleanup reachability now follows digest-tag helper edges recursively, matching helper-artifact cascades more closely.
|
|
229
|
+
|
|
230
|
+
## [0.9.5] - 2026-05-21
|
|
231
|
+
|
|
232
|
+
### Changed
|
|
233
|
+
|
|
234
|
+
- Renamed `upload-db-artifact` to `upload-artifacts`.
|
|
235
|
+
- Raised cleanup summary defaults to 100 matched tags and 100 roots per section.
|
|
236
|
+
|
|
237
|
+
## [0.9.4] - 2026-05-21
|
|
238
|
+
|
|
239
|
+
### Changed
|
|
240
|
+
|
|
241
|
+
- The root action now exposes `summary-json-path` instead of `summary-json`, so command summaries are consumed by file
|
|
242
|
+
path rather than as a large action output payload.
|
|
243
|
+
|
|
244
|
+
### Fixed
|
|
245
|
+
|
|
246
|
+
- The GitHub Action now passes cleanup and untag summary JSON between steps by file path instead of large environment
|
|
247
|
+
payloads, avoiding GitHub template-memory and argument-length failures on large cleanup runs.
|
|
248
|
+
|
|
249
|
+
## [0.9.3] - 2026-05-21
|
|
250
|
+
|
|
251
|
+
### Changed
|
|
252
|
+
|
|
253
|
+
- Cleanup selector planning now composes tagged and untagged selector families in one SQL-backed planner path.
|
|
254
|
+
- Cleanup CLI help and docs now describe the composed selector model, including tagged selectors combined with
|
|
255
|
+
`delete-untagged`.
|
|
256
|
+
|
|
257
|
+
### Fixed
|
|
258
|
+
|
|
259
|
+
- `exclude-tag` now works correctly when a tagged selector family is combined with `delete-untagged`.
|
|
260
|
+
|
|
261
|
+
## [0.9.2] - 2026-05-21
|
|
262
|
+
|
|
263
|
+
### Changed
|
|
264
|
+
|
|
265
|
+
- The action input is now `token`, and the repo now uses `GITHUB_TOKEN` consistently in docs and helper scripts.
|
|
266
|
+
|
|
267
|
+
## [0.9.1] - 2026-05-21
|
|
268
|
+
|
|
269
|
+
### Fixed
|
|
270
|
+
|
|
271
|
+
- The GitHub Action now installs, builds, and runs from its own checkout path instead of the caller repository path.
|
|
272
|
+
|
|
273
|
+
## [0.9.0] - 2026-05-21
|
|
274
|
+
|
|
275
|
+
`0.9.0` is the first stable pre-`1.0` release of `ghcr-cleanup-manager`.
|
|
276
|
+
|
|
277
|
+
### Added
|
|
278
|
+
|
|
279
|
+
- `cleanup` as the main GHCR maintenance flow for both the GitHub Action and the companion CLI.
|
|
280
|
+
- `untag` as a direct tag-removal mode that works without a scan database.
|
|
281
|
+
- `db-merge` and `merge-run-artifacts` support for combining scan databases across packages and workflow runs.
|
|
282
|
+
- Support for both organization-owned and user-owned GitHub Container Registry packages.
|
|
283
|
+
- Cleanup summary JSON output plus GitHub step summary rendering for action runs.
|
|
284
|
+
- Broad live and scenario-based workflow coverage for cleanup, untag, and cross-owner behavior.
|
|
285
|
+
- User-facing documentation for action usage, CLI usage, DB merge workflows, schema orientation, and SQL recipes.
|
|
286
|
+
|
|
287
|
+
### Changed
|
|
288
|
+
|
|
289
|
+
- The GitHub Action now builds and runs the repo-local CLI directly instead of installing `ghcr-cleanup-manager` from
|
|
290
|
+
npm at runtime.
|
|
291
|
+
- The primary maintenance surface is now `cleanup` with `dry-run` semantics, with `scan` and `untag` as supporting
|
|
292
|
+
command modes.
|
|
293
|
+
- The action input and artifact flow were refined around scan databases, cleanup summaries, and optional post-cleanup
|
|
294
|
+
rescan behavior.
|
|
295
|
+
- Documentation was reorganized around action-first usage, with deeper companion docs for CLI and database workflows.
|
|
296
|
+
- Release validation and workflow gating were tightened around exact version references, changelog readiness, and live
|
|
297
|
+
scenario checks.
|
|
298
|
+
|
|
299
|
+
### Removed
|
|
300
|
+
|
|
301
|
+
- Built-in database artifact encryption and decryption support.
|
|
302
|
+
|
|
303
|
+
### Fixed
|
|
304
|
+
|
|
305
|
+
- Digest-selector scenario handling and related workflow wiring for `ghcr-cleanup-manager`.
|
|
306
|
+
- Latest-scan based verification for cleanup and untag test flows.
|
|
307
|
+
- User-owner cleanup workflow behavior and related test setup details.
|
|
308
|
+
- Numerous workflow, artifact-handling, and planner-audit edge cases discovered during pre-release hardening.
|
|
309
|
+
|
|
310
|
+
## [0.0.6] - 2026-04-30
|
|
311
|
+
|
|
312
|
+
### Changed
|
|
313
|
+
|
|
314
|
+
- Internal workflow/debug wiring.
|
|
315
|
+
|
|
316
|
+
## [0.0.5] - 2026-04-30
|
|
317
|
+
|
|
318
|
+
### Changed
|
|
319
|
+
|
|
320
|
+
- Publish to npmjs by trusted publisher
|
|
321
|
+
|
|
322
|
+
## [0.0.4] - 2026-04-30
|
|
323
|
+
|
|
324
|
+
### Changed
|
|
325
|
+
|
|
326
|
+
- Publish to npmjs
|
|
327
|
+
|
|
328
|
+
## [0.0.3] - 2026-04-30
|
|
329
|
+
|
|
330
|
+
### Changed
|
|
331
|
+
|
|
332
|
+
- Released on GitHub marketplace as public action
|
|
333
|
+
|
|
334
|
+
## [0.0.1] - 2026-04-30
|
|
335
|
+
|
|
336
|
+
### Added
|
|
337
|
+
|
|
338
|
+
- Initial public release of `ghcr-cleanup-manager` as a GitHub Action plus companion CLI.
|
|
339
|
+
- GHCR scan flow that loads package versions, tags, manifests, descriptors, and manifest graph edges into SQLite.
|
|
340
|
+
- Manifest reachability precomputation (`manifest_reachability`) for fast graph-based analysis queries.
|
|
341
|
+
- Raw payload storage for GitHub package-version items and GHCR manifests (`package_version_payloads`,
|
|
342
|
+
`manifest_payloads`).
|
|
343
|
+
- Scan lifecycle tracking with scan history (`package_scans`) and status transitions (`running|completed|failed`).
|
|
344
|
+
- Immutable per-scan UUID (`package_scans.scan_uuid`) for robust duplicate detection across merged databases.
|
|
345
|
+
- Optional action artifact upload for scan DB export (`upload-db-artifact`, optional retention override).
|
|
346
|
+
- Manual workflow for interactive scan runs (`.github/workflows/manual-run.yml`).
|
|
347
|
+
- Missing-manifest investigation SQL recipes (`docs/queries/missing-manifests-queries.md`) and schema/terminology docs.
|
|
348
|
+
|
|
349
|
+
### Changed
|
|
350
|
+
|
|
351
|
+
- Enforced stricter repository conventions:
|
|
352
|
+
- source/test tree mirroring
|
|
353
|
+
- cross-folder imports via folder `index.ts`
|
|
354
|
+
- internal source naming (`_*.ts`)
|
|
355
|
+
- Hardened CI/workflows with explicit token permissions and immutable action reference checks.
|
|
356
|
+
- Refined action/runtime flow to focus on scan + DB export behavior for this release.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stefan Kuhn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# GHCR Cleanup Manager
|
|
2
|
+
|
|
3
|
+
[](https://github.com/marketplace/actions/ghcr-manager)
|
|
4
|
+
[](https://github.com/ghcr-manager/ghcr-cleanup-manager/releases)
|
|
5
|
+
[](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases)
|
|
6
|
+
[](https://github.com/ghcr-manager/ghcr-cleanup-manager/actions/workflows/ci_change-validation.yml)
|
|
7
|
+
|
|
8
|
+
GHCR Cleanup Manager is a GHCR cleanup action for GitHub Container Registry packages.
|
|
9
|
+
|
|
10
|
+
GHCR Cleanup Manager is a GitHub Action for:
|
|
11
|
+
|
|
12
|
+
- clean GHCR packages: including tagged and untagged images
|
|
13
|
+
- preview cleanup: with `dry-run` before making changes
|
|
14
|
+
- scan GHCR packages: into SQLite database artifacts
|
|
15
|
+
- visualize GHCR package graphs: and their changes with the
|
|
16
|
+
[ghcr-cleanup-manager-visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md)
|
|
17
|
+
|
|
18
|
+
It is built for safe GHCR cleanup on real OCI package graphs, including multi-arch images, attestations, cosign
|
|
19
|
+
signatures, and other referrers that simpler GHCR cleanup actions often mishandle.
|
|
20
|
+
|
|
21
|
+
[](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/images/visualizer/graph-2images-cosign--wide.png)
|
|
22
|
+
|
|
23
|
+
_Example graph compare view: red-bordered manifests are present in the older scan and removed in the newer one._
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
For a first run, start with `cleanup` in `dry-run` mode.
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
jobs:
|
|
31
|
+
cleanup:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
packages: read
|
|
36
|
+
actions: write
|
|
37
|
+
concurrency:
|
|
38
|
+
group: ghcr-cleanup-manager__OWNER__PACKAGE
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v6
|
|
41
|
+
|
|
42
|
+
- name: Preview GHCR cleanup
|
|
43
|
+
id: ghcr-cleanup-manager
|
|
44
|
+
uses: ghcr-manager/ghcr-cleanup-manager@v1.1.0
|
|
45
|
+
with:
|
|
46
|
+
command: cleanup
|
|
47
|
+
token: ${{ github.token }}
|
|
48
|
+
owner: OWNER
|
|
49
|
+
package: PACKAGE
|
|
50
|
+
dry-run: true
|
|
51
|
+
delete-untagged: true
|
|
52
|
+
keep-n-tagged: "10"
|
|
53
|
+
exclude-tags: |
|
|
54
|
+
latest
|
|
55
|
+
upload-artifacts: true
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> Permission notes:
|
|
59
|
+
>
|
|
60
|
+
> - `scan` and `cleanup` dry-runs need `packages: read`
|
|
61
|
+
> - live `cleanup` that mutates GHCR needs `packages: write`
|
|
62
|
+
> - artifact upload needs `actions: write`
|
|
63
|
+
|
|
64
|
+
After the run:
|
|
65
|
+
|
|
66
|
+
1. Open the GitHub step summary for the action run.
|
|
67
|
+
2. Review which tags matched and which roots would be deleted, untagged, or blocked.
|
|
68
|
+
3. Only download the DB artifact if you need deeper inspection.
|
|
69
|
+
|
|
70
|
+
## Commands
|
|
71
|
+
|
|
72
|
+
The action supports two commands:
|
|
73
|
+
|
|
74
|
+
- `cleanup`: Cleans using filters; use `dry-run` to preview the result
|
|
75
|
+
- `scan`: Scans one package and uploads the resulting DB artifact
|
|
76
|
+
|
|
77
|
+
### Purpose of commands
|
|
78
|
+
|
|
79
|
+
- `cleanup`: Normal entry point for registry maintenance
|
|
80
|
+
- `scan`: For investigation and audit
|
|
81
|
+
|
|
82
|
+
## Common Usage
|
|
83
|
+
|
|
84
|
+
### Preview cleanup
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.0
|
|
88
|
+
with:
|
|
89
|
+
command: cleanup
|
|
90
|
+
token: ${{ github.token }}
|
|
91
|
+
owner: OWNER
|
|
92
|
+
package: PACKAGE
|
|
93
|
+
dry-run: true
|
|
94
|
+
delete-tags: |
|
|
95
|
+
pr-.*
|
|
96
|
+
use-regex: true
|
|
97
|
+
older-than: 30 days
|
|
98
|
+
keep-n-tagged: "5"
|
|
99
|
+
exclude-tags: |
|
|
100
|
+
latest
|
|
101
|
+
stable
|
|
102
|
+
upload-artifacts: true
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Apply cleanup
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.0
|
|
109
|
+
with:
|
|
110
|
+
command: cleanup
|
|
111
|
+
token: ${{ github.token }}
|
|
112
|
+
owner: OWNER
|
|
113
|
+
package: PACKAGE
|
|
114
|
+
delete-untagged: true
|
|
115
|
+
keep-n-tagged: "10"
|
|
116
|
+
upload-artifacts: true
|
|
117
|
+
scan-after-cleanup: true
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
If `scan-after-cleanup` is `true`, `cleanup` performs a second scan so the uploaded DB reflects post-mutation state.
|
|
121
|
+
|
|
122
|
+
Note: the second scan only runs if cleanup actually makes changes.
|
|
123
|
+
|
|
124
|
+
Live cleanup permission note: change the workflow permission from `packages: read` to `packages: write` before turning
|
|
125
|
+
off `dry-run`.
|
|
126
|
+
|
|
127
|
+
### Scan one package
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.0
|
|
131
|
+
with:
|
|
132
|
+
command: scan
|
|
133
|
+
token: ${{ github.token }}
|
|
134
|
+
owner: OWNER
|
|
135
|
+
package: PACKAGE
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`scan` always uploads a DB artifact.
|
|
139
|
+
|
|
140
|
+
## Inputs
|
|
141
|
+
|
|
142
|
+
<!-- markdownlint-disable MD013 MD060 -->
|
|
143
|
+
|
|
144
|
+
| Input | Description | Cmds | Required | Default |
|
|
145
|
+
| ---------------------------- | ----------------------------------- | ---- | -------- | ------------------------------ |
|
|
146
|
+
| `command` | `scan` or `cleanup` | all | Yes | |
|
|
147
|
+
| `token` | GitHub token for API calls | all | Yes | `${{ github.token }}` |
|
|
148
|
+
| `owner` | Package owner | all | Yes | |
|
|
149
|
+
| `package` | Package name | all | Yes | |
|
|
150
|
+
| `db-path` | Local SQLite DB path | s,c | No | |
|
|
151
|
+
| `upload-artifacts` | Upload DB and summary artifacts | s,c | No | `false` |
|
|
152
|
+
| `scan-after-cleanup` | Run a second scan after cleanup | c | No | `false` |
|
|
153
|
+
| `db-artifact-retention-days` | Override artifact retention days | s,c | No | `${{ github.retention_days }}` |
|
|
154
|
+
| `delete-tags` | Newline-separated tags to delete | c | No | |
|
|
155
|
+
| `exclude-tags` | Newline-separated tags to exclude | c | No | |
|
|
156
|
+
| `keep-n-tagged` | Keep newest tagged roots | c | No | |
|
|
157
|
+
| `keep-n-untagged` | Keep newest untagged roots | c | No | |
|
|
158
|
+
| `delete-untagged` | Delete untagged roots | c | No | `false` |
|
|
159
|
+
| `delete-ghost-images` | Delete ghost multi-arch roots | c | No | `false` |
|
|
160
|
+
| `delete-partial-images` | Delete partial multi-arch roots | c | No | `false` |
|
|
161
|
+
| `delete-orphaned-images` | Delete orphaned digest-derived tags | c | No | `false` |
|
|
162
|
+
| `older-than` | Age cutoff for cleanup selectors | c | No | |
|
|
163
|
+
| `use-regex` | Use regex for cleanup tag selectors | c | No | `false` |
|
|
164
|
+
| `dry-run` | Show changes without mutating GHCR | c | No | `false` |
|
|
165
|
+
| `log-level` | CLI log level | all | No | `info` |
|
|
166
|
+
|
|
167
|
+
<!-- markdownlint-enable MD013 MD060 -->
|
|
168
|
+
|
|
169
|
+
`Cmds`: `s` = `scan`, `c` = `cleanup`
|
|
170
|
+
|
|
171
|
+
Cleanup command notes:
|
|
172
|
+
|
|
173
|
+
- Tagged selector families may be combined with `delete-untagged`.
|
|
174
|
+
- `exclude-tags` requires at least one tagged selector family.
|
|
175
|
+
- `delete-untagged` and `keep-n-untagged` cannot be combined.
|
|
176
|
+
- `older-than` takes one integer plus one unit.
|
|
177
|
+
- Supported `older-than` units: `minutes`, `hours`, `days`, `weeks`, `months`, `years`.
|
|
178
|
+
- Example values: `30 days`, `2 hours`, `1 month`.
|
|
179
|
+
|
|
180
|
+
## Outputs
|
|
181
|
+
|
|
182
|
+
| Output | Description |
|
|
183
|
+
| ------------------- | ------------------------------------ |
|
|
184
|
+
| `db-path` | SQLite DB path on the runner |
|
|
185
|
+
| `summary-json-path` | Summary JSON file path for `cleanup` |
|
|
186
|
+
|
|
187
|
+
## Artifacts
|
|
188
|
+
|
|
189
|
+
When artifacts are enabled:
|
|
190
|
+
|
|
191
|
+
- `scan` always uploads one SQLite DB artifact
|
|
192
|
+
- `cleanup` optionally uploads the DB artifact and a cleanup summary JSON artifact
|
|
193
|
+
|
|
194
|
+
Current naming:
|
|
195
|
+
|
|
196
|
+
| Artifact type | Filename pattern |
|
|
197
|
+
| -------------------- | --------------------------------------------------- |
|
|
198
|
+
| scan or cleanup DB | `${OWNER}__${PACKAGE}.sqlite` |
|
|
199
|
+
| cleanup summary JSON | `${OWNER}__${PACKAGE}.sqlite--cleanup-summary.json` |
|
|
200
|
+
|
|
201
|
+
## Documentation Map
|
|
202
|
+
|
|
203
|
+
- [GitHub Action usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/action-usage.md): action
|
|
204
|
+
commands, including `cleanup` and `scan`
|
|
205
|
+
- [Cleanup behavior](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cleanup-behavior.md): how
|
|
206
|
+
cleanup protects retained tags and handles shared graphs
|
|
207
|
+
- [ghcr-cleanup-manager-visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md):
|
|
208
|
+
local graph inspection and scan-to-scan comparison
|
|
209
|
+
- [Multi-package workflows](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/db-merge-workflows.md):
|
|
210
|
+
cleaning up multiple packages with one combined DB
|
|
211
|
+
- [SQLite schema guide](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/schema-description.md):
|
|
212
|
+
practical explanation of the SQLite schema
|
|
213
|
+
- [CLI usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cli-usage.md): companion CLI usage
|
|
214
|
+
|
|
215
|
+
## Explore A Real Scenario DB
|
|
216
|
+
|
|
217
|
+
The release assets also include one merged SQLite DB from GHCR Cleanup Manager's live scenario workflows. You can use it
|
|
218
|
+
as a quick visualizer demo and as a compact way to inspect dozens of real cleanup and graph cases.
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
curl -LO https://github.com/ghcr-manager/ghcr-cleanup-manager/releases/latest/download/ghcr-cleanup-manager([^/s]*.sqlite)
|
|
222
|
+
npx ghcr-cleanup-manager-visualizer --db ./ghcr-cleanup-manager([^/s]*.sqlite)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Docker image available:
|
|
226
|
+
[visualizer Docker usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md#docker).
|
|
227
|
+
|
|
228
|
+
For a first look in the visualizer, start with:
|
|
229
|
+
|
|
230
|
+
- owner: `ghcr-cleanup-manager-test`
|
|
231
|
+
- package: select one with `2images` or `2multiarch` in the name
|
|
232
|
+
- tag search: `image` or `multiarch`
|
|
233
|
+
|
|
234
|
+
For more details, see [visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md)
|
|
235
|
+
and [test-scenarios](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/test/scenarios.md).
|
|
236
|
+
|
|
237
|
+
## Cleanup Behavior
|
|
238
|
+
|
|
239
|
+
Cleanup is tag-based for both selection and protection. Use tags to say what should be cleaned up, and use retained tags
|
|
240
|
+
to keep image and multi-arch graphs protected.
|
|
241
|
+
|
|
242
|
+
Manifests reachable from retained tags stay protected. Manifests no longer reachable from any retained tag may be
|
|
243
|
+
removed during cleanup. If you pull images by digest, make sure those digests are still reachable through tags that your
|
|
244
|
+
cleanup rules keep.
|
|
245
|
+
|
|
246
|
+
For the full explanation and graph examples, see
|
|
247
|
+
[cleanup-behavior](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cleanup-behavior.md).
|
|
248
|
+
|
|
249
|
+
## Project
|
|
250
|
+
|
|
251
|
+
Main project and issue tracker:
|
|
252
|
+
|
|
253
|
+
- Repository: <https://github.com/ghcr-manager/ghcr-cleanup-manager>
|
|
254
|
+
- Issues: <https://github.com/ghcr-manager/ghcr-cleanup-manager/issues>
|
|
255
|
+
|
|
256
|
+
## Similar Tools
|
|
257
|
+
|
|
258
|
+
- [ghcr-manager/ghcr-untag-action](https://github.com/ghcr-manager/ghcr-untag-action): focused tag removal without the
|
|
259
|
+
broader scan and cleanup workflow.
|
|
260
|
+
- [dataaxiom/ghcr-cleanup-action](https://github.com/dataaxiom/ghcr-cleanup-action): another GHCR cleanup action with a
|
|
261
|
+
similar problem focus.
|
|
262
|
+
- [mkoepf/ghcrctl](https://github.com/mkoepf/ghcrctl): CLI tooling for working with GHCR packages and graph deletions.
|