Skip to content

Commit b46a5f2

Browse files
committed
ci: refactor attestation clean-up
1 parent 9913f7d commit b46a5f2

File tree

1 file changed

+35
-15
lines changed

1 file changed

+35
-15
lines changed

.github/workflows/image-cleanup.yml

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
schedule:
66
- cron: "0 0 * * 3"
77
workflow_dispatch:
8+
inputs:
9+
dry-run:
10+
default: false
11+
type: boolean
812

913
permissions: {}
1014

@@ -19,7 +23,7 @@ jobs:
1923
permissions:
2024
packages: read # is needed to list package versions
2125
steps:
22-
- uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
26+
- uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
2327
with:
2428
disable-sudo-and-containers: true
2529
egress-policy: audit
@@ -28,6 +32,7 @@ jobs:
2832
run: |
2933
set -Eeuo pipefail
3034
ORG="${GH_REPO%%/*}"
35+
3136
gh api "/orgs/${ORG}/packages/container/${GH_PACKAGE}/versions" \
3237
--paginate \
3338
--jq '.[].name' 2>/dev/null > digests.txt || touch digests.txt
@@ -60,7 +65,8 @@ jobs:
6065
with:
6166
delete-orphaned-images: true
6267
delete-untagged: true
63-
packages: amp-devcontainer,amp-devcontainer-cpp,amp-devcontainer-rust
68+
dry-run: ${{ inputs.dry-run == true }}
69+
packages: amp-devcontainer-base,amp-devcontainer-cpp,amp-devcontainer-rust
6470

6571
cleanup-attestations:
6672
name: 🔏 Cleanup Orphaned Attestations (${{ matrix.package }})
@@ -74,7 +80,7 @@ jobs:
7480
attestations: write # is needed to delete attestations
7581
packages: read # is needed to list remaining package versions after cleanup
7682
steps:
77-
- uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
83+
- uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
7884
with:
7985
disable-sudo-and-containers: true
8086
egress-policy: audit
@@ -91,21 +97,35 @@ jobs:
9197
ORG="${GH_REPO%%/*}"
9298
9399
# Get remaining digests after image cleanup
94-
current_digests=$(gh api "/orgs/${ORG}/packages/container/${GH_PACKAGE}/versions" \
100+
if ! gh api "/orgs/${ORG}/packages/container/${GH_PACKAGE}/versions" \
95101
--paginate \
96-
--jq '.[].name' 2>/dev/null || echo "")
102+
--jq '.[].name' > current-digests.txt; then
103+
echo "Package not found or API error, skipping attestation cleanup"
104+
exit 0
105+
fi
106+
107+
# Find orphaned digests (present before cleanup but no longer in current)
108+
orphaned=$(comm -23 <(grep -v '^$' digests.txt | sort -u) <(sort -u current-digests.txt))
109+
110+
if [[ -z "$orphaned" ]]; then
111+
echo "No orphaned digests found"
112+
exit 0
113+
fi
114+
115+
count=$(echo "$orphaned" | wc -l)
116+
echo "Found ${count} orphaned digests"
117+
echo "$orphaned"
118+
119+
if [[ "${DRY_RUN}" == "true" ]]; then
120+
echo "Dry-run mode: skipping attestation deletion"
121+
exit 0
122+
fi
97123
98-
# Delete attestations for digests that no longer have a package version
99-
while read -r digest; do
100-
[[ -z "$digest" ]] && continue
101-
if ! echo "$current_digests" | grep -qx "$digest"; then
102-
echo "Deleting attestations for removed digest: ${digest}"
103-
encoded_digest="${digest//:/%3A}"
104-
gh api --method DELETE "/orgs/${ORG}/attestations/digest/${encoded_digest}" \
105-
2>/dev/null && echo "Deleted" || echo "No attestations found (already cleaned up)"
106-
fi
107-
done < digests.txt
124+
echo "Deleting attestations for ${count} orphaned digests"
125+
echo "$orphaned" | jq -R . | jq -sc '{subject_digests: .}' | \
126+
gh api --method POST "/orgs/${ORG}/attestations/delete-request" --input -
108127
env:
128+
DRY_RUN: ${{ inputs.dry-run == true }}
109129
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110130
GH_REPO: ${{ github.repository }}
111131
GH_PACKAGE: ${{ matrix.package }}

0 commit comments

Comments
 (0)