1+ #! /bin/bash
2+ set -euo pipefail
3+
4+ export VERSIONS_FILE=versions.json
5+ export SIGNATURES_FILE=versions-with-sigs.json
6+
7+
8+ # Verifies all required environment variables are set.
9+ check_env_vars () {
10+ : " ${ORG:? Missing ORG} "
11+ : " ${PACKAGE_NAME:? Missing PACKAGE_NAME} "
12+ : " ${PACKAGE_TYPE:? Missing PACKAGE_TYPE} "
13+ : " ${LOGIN_TOKEN:? Missing LOGIN_TOKEN} "
14+ : " ${VERSIONS_FILE:? Missing VERSIONS FILE NAME} "
15+ : " ${SIGNATURES_FILE:? Missing SIGNATURES FILE NAME} "
16+ }
17+
18+ # Uses curl to fetch all package versions from GitHub and save to ${VERSIONS_FILE}.
19+ fetch_versions () {
20+ curl -sSfL \
21+ -H " Accept: application/vnd.github+json" \
22+ -H " Authorization: Bearer ${LOGIN_TOKEN} " \
23+ -H " X-GitHub-Api-Version: 2022-11-28" \
24+ " https://api.github.com/orgs/${ORG} /packages/${PACKAGE_TYPE} /${PACKAGE_NAME} /versions" > " ${VERSIONS_FILE} "
25+ }
26+
27+ # Builds a newline-separated string of all version names in ${VERSIONS_FILE}.
28+ get_all_names () {
29+ jq -r ' .[].name' " ${VERSIONS_FILE} "
30+ }
31+
32+ # Helper function to print the signature SHA for a given full_tag
33+ print_sig_sha () {
34+ local full_tag=" $1 "
35+ sig_sha=$( jq -r --arg t " $full_tag " ' .[] | select(.metadata.container.tags[]? == $t) | .name' " ${VERSIONS_FILE} " )
36+ echo -e " \033[1m$ sig_sha\033[0m"
37+ }
38+
39+ # Loops over entries and prints dangling signatures.
40+ scan_for_dangling_signatures () {
41+ local all_names
42+ all_names=$( get_all_names)
43+ local show_no_sig_tags=" ${SHOW_NO_SIG_TAGS:- false} "
44+ local show_assigned_sig_tags=" ${SHOW_ASSIGNED_SIG_TAGS:- true} "
45+ while read -r entry; do
46+ full_tag=$( jq -r ' .tags[]? | select(test("^sha256-.*\\.sig$"))' <<< " $entry" )
47+ if [[ -z " $full_tag " ]]; then
48+ if [[ " $show_no_sig_tags " == " true" ]]; then
49+ echo " -----------------"
50+ echo -e " \033[33mNo signature tag found\033[0m"
51+ echo " -----------------"
52+ echo " "
53+ fi
54+ continue
55+ fi
56+
57+ tag=${full_tag/ sha256-/ sha256: }
58+ tag=${tag% .sig}
59+ tag_name=$( jq -r ' .name' <<< " $entry" )
60+
61+ if [[ -n " $tag " ]] && ! grep -Fqx " $tag " <<< " $all_names" ; then
62+ echo " -----------------"
63+ echo " Signature: $full_tag "
64+ echo " Related Tag: $tag "
65+ echo " Tag Name: $tag_name "
66+ echo -e " Status: \033[31mORPHANED SIGNATURE ✗\033[0m"
67+ echo -e " \033[1mDangling Sig to delete:\033[0m $full_tag "
68+ print_sig_sha " $full_tag "
69+ # Find version ID for the signature to delete
70+ version_id=$( jq -r --arg t " $full_tag " ' .[] | select(.metadata.container.tags[]? == $t) | .id' " ${VERSIONS_FILE} " )
71+ if [[ -n " $version_id " && " $version_id " != " null" ]]; then
72+ curl -sSfL \
73+ -X DELETE \
74+ -H " Accept: application/vnd.github+json" \
75+ -H " Authorization: Bearer ${LOGIN_TOKEN} " \
76+ -H " X-GitHub-Api-Version: 2022-11-28" \
77+ " https://api.github.com/orgs/${ORG} /packages/${PACKAGE_TYPE} /${PACKAGE_NAME} /versions/${version_id} "
78+ echo " Deleted signature: $full_tag (version_id: $version_id )"
79+ else
80+ echo " Could not find version ID for signature $full_tag . Skipping deletion."
81+ fi
82+ echo " -----------------"
83+ echo " "
84+ else
85+ if [[ " $show_assigned_sig_tags " == " true" ]]; then
86+ echo " -----------------"
87+ echo " Signature: $full_tag "
88+ echo " Related Tag: $tag "
89+ echo " Tag Name: $tag_name "
90+ echo -e " Status: \033[32mSIGNATURE ASSIGNED TO IMAGE ✅\033[0m"
91+ jq -r ' .name' <<< " $entry"
92+ echo " -----------------"
93+ echo " "
94+ fi
95+ fi
96+ done < <( jq -cr ' .[] | {name, tags: (.metadata.container.tags // [])}' " ${VERSIONS_FILE} " )
97+ }
98+
99+ # Main execution sequence
100+ check_env_vars
101+ fetch_versions
102+ scan_for_dangling_signatures
103+
104+ echo " 🏁 Registry cleanup completed."
0 commit comments