Skip to content

Commit 091627b

Browse files
authored
Merge pull request #1 from chipkent/initial
Initial implementation
2 parents 108d088 + 29dec7e commit 091627b

File tree

3 files changed

+118
-2
lines changed

3 files changed

+118
-2
lines changed

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,26 @@
1-
# action-cleanup_package
2-
GitHub Action to clean up unwanted GitHub packages
1+
# action-cleanup-package
2+
3+
This is a GitHub Action to delete GitHub packages. It is very useful to clean up unneeded Docker
4+
images in the GitHub Container Registry (ghcr.io) after a PR is closed.
5+
6+
```
7+
# Delete Docker images after PR merge
8+
#
9+
10+
name: 'Clean up Docker images from PR'
11+
12+
on:
13+
pull_request:
14+
types: [closed]
15+
16+
jobs:
17+
purge-image:
18+
name: Delete image from ghcr.io
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: chipkent/action-cleanup-package@v1.0.0
22+
with:
23+
package-name: ${{ github.event.repository.name }}
24+
tag: pr-${{ github.event.pull_request.number }}
25+
github-token: ${{ secrets.CI_ACTION_TOKEN }}
26+
```

action.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
name: 'Delete ghcr.io package tag'
3+
description: 'Delete a tagged package from ghcr.io'
4+
inputs:
5+
package-name:
6+
description: 'Package name'
7+
required: true
8+
tag:
9+
description: 'Package tag'
10+
required: true
11+
github-token:
12+
description: 'GitHub Personal Access Token with package deletion permissions.'
13+
required: true
14+
runs:
15+
using: "composite"
16+
steps:
17+
- uses: actions/setup-python@v2
18+
with:
19+
python-version: '3.8'
20+
- name: Install packages
21+
run: pip install requests
22+
- name: Delete image from ghcr.io
23+
run: python ${{ github.action_path }}/docker-cleanup.py ${{ inputs.package-name }} ${{ inputs.tag }} ${{ inputs.github-token }}

docker-cleanup.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Script to delete tagged docker images.
2+
# Usage: <package_name> <tag> <github_token>
3+
#
4+
5+
6+
import requests
7+
8+
9+
def get_package_versions(package_name, package_type):
10+
print("get_package_versions", package_name, package_type)
11+
# https://docs.github.com/en/rest/reference/packages#get-all-package-versions-for-a-package-owned-by-the-authenticated-user
12+
result = []
13+
done = False
14+
page = 1
15+
16+
while not done:
17+
response = session.get(f"https://api.github.com/user/packages/{package_type}/{package_name}/versions", params={"per_page" : 100, "page": page})
18+
response.raise_for_status()
19+
json = response.json()
20+
result.extend(json)
21+
done = len(json) != 100
22+
page += 1
23+
24+
return result
25+
26+
27+
def delete_package_version(package_name, package_type, id):
28+
print("delete_package_version", package_name, package_type, id)
29+
30+
# https://docs.github.com/en/rest/reference/packages#delete-a-package-version-for-the-authenticated-user
31+
response = session.delete(f"https://api.github.com/user/packages/{package_type}/{package_name}/versions/{id}")
32+
response.raise_for_status()
33+
34+
35+
def get_tagged_container(package_name, tag):
36+
print("get_tagged_container", package_name, tag)
37+
packages = get_package_versions(package_name, "container")
38+
return [version for version in packages if tag in version["metadata"]["container"]["tags"]]
39+
40+
41+
def delete_tagged_container(package_name, tag):
42+
print("delete_tagged_container", package_name, tag)
43+
tags = get_tagged_container(package_name, tag)
44+
45+
if tags:
46+
for tag in tags:
47+
delete_package_version(package_name, "container", tag["id"])
48+
else:
49+
raise Exception(f"No containers to delete: {package_name} {tag}")
50+
51+
52+
################################
53+
54+
import sys
55+
56+
if len(sys.argv) != 4:
57+
raise SystemExit("Usage: docker-cleanup.py <package_name> <tag> <github_token>")
58+
59+
package_name = sys.argv[1]
60+
tag = sys.argv[2]
61+
token = sys.argv[3]
62+
63+
print("package_name = ", package_name)
64+
print("tag = ", tag)
65+
66+
session = requests.Session()
67+
session.headers.update({"Authorization": f"token {token}", "Accept" : "application/vnd.github.v3+json"})
68+
delete_tagged_container(package_name, tag)
69+

0 commit comments

Comments
 (0)