This commit is contained in:
@@ -45,6 +45,11 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
release_retention_count:
|
||||
description: Number of immutable sha-* release images to retain after a successful promotion
|
||||
required: false
|
||||
default: 2
|
||||
type: number
|
||||
secrets:
|
||||
REGISTRY_USERNAME:
|
||||
required: true
|
||||
@@ -149,3 +154,90 @@ jobs:
|
||||
set -eu
|
||||
ssh -i ~/.ssh/id_ed25519 cicd-deploy@"${{ inputs.deploy_host }}" \
|
||||
"promote ${{ inputs.deploy_service }} ${{ inputs.image_name }}:sha-${{ gitea.sha }}"
|
||||
- name: Retain current and previous release images
|
||||
if: ${{ startsWith(gitea.ref, 'refs/tags/v') && inputs.deploy_service != '' && inputs.deploy_host != '' }}
|
||||
env:
|
||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
image_name='${{ inputs.image_name }}'
|
||||
keep_count='${{ inputs.release_retention_count }}'
|
||||
current_version='sha-${{ gitea.sha }}'
|
||||
|
||||
case "$keep_count" in
|
||||
''|*[!0-9]*|0)
|
||||
echo "release_retention_count must be a positive integer"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
registry="${image_name%%/*}"
|
||||
image_path="${image_name#*/}"
|
||||
owner="${image_path%%/*}"
|
||||
package_name="${image_path#*/}"
|
||||
|
||||
if [ "$registry" = "$image_name" ] || [ "$owner" = "$image_path" ]; then
|
||||
echo "image_name must include registry, owner, and package name"
|
||||
exit 1
|
||||
fi
|
||||
case "$owner/$package_name" in
|
||||
*[!A-Za-z0-9._/-]*|*/*/*)
|
||||
echo "image owner or package name contains unsupported characters"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
api_base="https://${registry}/api/v1/packages"
|
||||
versions_file="$(mktemp)"
|
||||
keep_file="$(mktemp)"
|
||||
trap 'rm -f "$versions_file" "$keep_file"' EXIT
|
||||
|
||||
page=1
|
||||
while [ "$page" -le 100 ]; do
|
||||
response="$(curl --fail --silent --show-error --retry 3 --retry-all-errors \
|
||||
--user "$REGISTRY_USERNAME:$REGISTRY_PASSWORD" \
|
||||
"${api_base}/${owner}?type=container&q=${package_name}&limit=50&page=${page}")"
|
||||
item_count="$(printf '%s' "$response" | jq 'length')"
|
||||
[ "$item_count" -gt 0 ] || break
|
||||
printf '%s' "$response" | jq -r --arg package_name "$package_name" '
|
||||
.[]
|
||||
| select((.name | ascii_downcase) == ($package_name | ascii_downcase))
|
||||
| select(.version | test("^sha-[0-9a-f]{40}$"))
|
||||
| [.created_at, .version]
|
||||
| @tsv
|
||||
' >> "$versions_file"
|
||||
page=$((page + 1))
|
||||
done
|
||||
|
||||
if ! awk -F '\t' -v current="$current_version" '$2 == current { found = 1 } END { exit(found ? 0 : 1) }' "$versions_file"; then
|
||||
echo "Current release version was not returned by the Gitea Packages API: $current_version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$current_version" > "$keep_file"
|
||||
previous_count=$((keep_count - 1))
|
||||
if [ "$previous_count" -gt 0 ]; then
|
||||
sort -r "$versions_file" | awk -F '\t' \
|
||||
-v current="$current_version" \
|
||||
-v limit="$previous_count" \
|
||||
'$2 != current && kept < limit { print $2; kept++ }' >> "$keep_file"
|
||||
fi
|
||||
|
||||
deleted=0
|
||||
while IFS=$'\t' read -r _created_at version; do
|
||||
[ -n "$version" ] || continue
|
||||
if grep -Fqx "$version" "$keep_file"; then
|
||||
echo "Keeping release image: $package_name:$version"
|
||||
continue
|
||||
fi
|
||||
curl --fail --silent --show-error --retry 3 --retry-all-errors \
|
||||
--user "$REGISTRY_USERNAME:$REGISTRY_PASSWORD" \
|
||||
--request DELETE \
|
||||
"${api_base}/${owner}/container/${package_name}/${version}"
|
||||
echo "Deleted superseded release image: $package_name:$version"
|
||||
deleted=$((deleted + 1))
|
||||
done < <(sort -r "$versions_file")
|
||||
|
||||
echo "Release retention complete: package=$package_name retained=$keep_count deleted=$deleted"
|
||||
|
||||
Reference in New Issue
Block a user