Files
cleanup-release-action/action.yml
2025-12-01 10:06:30 +08:00

247 lines
10 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: 'Cleanup Old Releases'
description: '自動清理舊版本的 releases保留指定數量的最新版本'
inputs:
gitea-server:
description: 'Gitea 伺服器 URL'
required: true
repository:
description: '儲存庫名稱 (格式: owner/repo)'
required: true
package-name:
description: 'Container 套件名稱 (選填,若提供則會清理 Container Registry)'
required: false
default: ''
token:
description: 'Gitea API Token'
required: true
keep-count:
description: '保留的最新版本數量'
required: false
default: '2'
dry-run:
description: '是否為模擬執行 (只顯示會刪除的版本,不實際刪除)'
required: false
default: 'false'
outputs:
deleted-count:
description: '已刪除的版本數量'
value: ${{ steps.cleanup.outputs.deleted-count }}
deleted-releases:
description: '已刪除的版本列表 (JSON 格式)'
value: ${{ steps.cleanup.outputs.deleted-releases }}
deleted-images-count:
description: '已刪除的映像數量'
value: ${{ steps.cleanup-images.outputs.deleted-count }}
deleted-images:
description: '已刪除的映像列表 (JSON 格式)'
value: ${{ steps.cleanup-images.outputs.deleted-images }}
runs:
using: 'composite'
steps:
- name: 清理舊版本
id: cleanup
shell: bash
run: |
echo "開始清理舊版本,保留最新 ${{ inputs.keep-count }} 個版本"
# 獲取所有 releases 並按創建時間排序
RELEASES_JSON=$(curl -s "${{ inputs.gitea-server }}/api/v1/repos/${{ inputs.repository }}/releases" \
-H "Authorization: token ${{ inputs.token }}" \
-H "Accept: application/json")
# 檢查是否成功獲取 releases
if [ $? -ne 0 ] || [ -z "$RELEASES_JSON" ]; then
echo "錯誤:無法獲取 releases 列表"
exit 1
fi
# 計算總數量
TOTAL_COUNT=$(echo "$RELEASES_JSON" | jq 'length')
echo "目前總共有 $TOTAL_COUNT 個 releases"
# 如果總數量小於等於保留數量,則無需清理
if [ $TOTAL_COUNT -le ${{ inputs.keep-count }} ]; then
echo "releases 數量 ($TOTAL_COUNT) 未超過保留數量 (${{ inputs.keep-count }}),無需清理"
echo "deleted-count=0" >> $GITHUB_OUTPUT
echo "deleted-releases=[]" >> $GITHUB_OUTPUT
exit 0
fi
# 計算需要刪除的數量
DELETE_COUNT=$((TOTAL_COUNT - ${{ inputs.keep-count }}))
echo "需要刪除 $DELETE_COUNT 個舊版本"
# 獲取要刪除的 releases (跳過前 keep-count 個)
TO_DELETE=$(echo "$RELEASES_JSON" | jq -r ".[${{ inputs.keep-count }}:] | .[] | {id: .id, tag: .tag_name, name: .name}")
# 初始化刪除計數器和列表
DELETED_COUNT=0
DELETED_LIST="[]"
# 處理每個要刪除的 release
echo "$TO_DELETE" | jq -c '.' | while read -r release; do
if [ -z "$release" ] || [ "$release" = "null" ]; then
continue
fi
RELEASE_ID=$(echo "$release" | jq -r '.id')
RELEASE_TAG=$(echo "$release" | jq -r '.tag')
RELEASE_NAME=$(echo "$release" | jq -r '.name')
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
continue
fi
echo "準備刪除: ID=$RELEASE_ID, Tag=$RELEASE_TAG, Name=$RELEASE_NAME"
if [ "${{ inputs.dry-run }}" = "true" ]; then
echo "🔍 [模擬執行] 會刪除 release: $RELEASE_TAG ($RELEASE_NAME)"
DELETED_COUNT=$((DELETED_COUNT + 1))
else
# 實際刪除
DELETE_RESPONSE=$(curl -s -w "HTTP_STATUS:%{http_code}" \
-X DELETE "${{ inputs.gitea-server }}/api/v1/repos/${{ inputs.repository }}/releases/$RELEASE_ID" \
-H "Authorization: token ${{ inputs.token }}")
HTTP_STATUS=$(echo "$DELETE_RESPONSE" | grep -o "HTTP_STATUS:[0-9]*" | cut -d: -f2)
if [ "$HTTP_STATUS" = "204" ] || [ "$HTTP_STATUS" = "200" ]; then
echo "✅ 成功刪除 release: $RELEASE_TAG ($RELEASE_NAME)"
DELETED_COUNT=$((DELETED_COUNT + 1))
# 更新已刪除列表
DELETED_LIST=$(echo "$DELETED_LIST" | jq ". + [{\"id\": \"$RELEASE_ID\", \"tag\": \"$RELEASE_TAG\", \"name\": \"$RELEASE_NAME\"}]")
else
echo "❌ 刪除失敗 release: $RELEASE_TAG ($RELEASE_NAME), HTTP狀態: $HTTP_STATUS"
fi
fi
done
# 由於 while 迴圈在子 shell 中執行,需要重新計算
if [ "${{ inputs.dry-run }}" = "true" ]; then
FINAL_DELETE_COUNT=$(echo "$TO_DELETE" | jq -s 'length')
echo "deleted-count=$FINAL_DELETE_COUNT" >> $GITHUB_OUTPUT
echo "deleted-releases=[]" >> $GITHUB_OUTPUT
echo "🔍 [模擬執行] 總共會刪除 $FINAL_DELETE_COUNT 個版本"
else
# 重新獲取並計算實際刪除的數量
echo "deleted-count=$ACTUAL_DELETED" >> $GITHUB_OUTPUT
echo "deleted-releases=$DELETED_LIST" >> $GITHUB_OUTPUT
echo "✅ 清理完成,實際刪除了 $ACTUAL_DELETED 個版本"
fi
- name: 清理舊映像
id: cleanup-images
if: ${{ inputs.package-name != '' }}
shell: bash
run: |
echo "開始清理舊映像,保留最新 ${{ inputs.keep-count }} 個版本"
# 提取 owner 名稱
OWNER=$(echo "${{ inputs.repository }}" | cut -d'/' -f1)
PACKAGE_NAME="${{ inputs.package-name }}"
echo "Owner: $OWNER"
echo "Package: $PACKAGE_NAME"
# 獲取所有 container 版本並按創建時間排序
VERSIONS_JSON=$(curl -s "${{ inputs.gitea-server }}/api/v1/packages/$OWNER/container/$PACKAGE_NAME" \
-H "Authorization: token ${{ inputs.token }}" \
-H "Accept: application/json")
# 檢查是否成功獲取版本列表
if [ $? -ne 0 ] || [ -z "$VERSIONS_JSON" ]; then
echo "錯誤:無法獲取 container 版本列表"
exit 1
fi
# 獲取並排序所有版本 (按創建時間降序)
SORTED_VERSIONS=$(echo "$VERSIONS_JSON" | jq -r '.versions | sort_by(.created_at) | reverse')
# 計算總數量
TOTAL_COUNT=$(echo "$SORTED_VERSIONS" | jq 'length')
echo "目前總共有 $TOTAL_COUNT 個映像版本"
# 如果總數量小於等於保留數量,則無需清理
if [ $TOTAL_COUNT -le ${{ inputs.keep-count }} ]; then
echo "映像數量 ($TOTAL_COUNT) 未超過保留數量 (${{ inputs.keep-count }}),無需清理"
echo "deleted-count=0" >> $GITHUB_OUTPUT
echo "deleted-images=[]" >> $GITHUB_OUTPUT
exit 0
fi
# 計算需要刪除的數量
DELETE_COUNT=$((TOTAL_COUNT - ${{ inputs.keep-count }}))
echo "需要刪除 $DELETE_COUNT 個舊映像"
# 獲取要刪除的版本 (跳過前 keep-count 個)
TO_DELETE=$(echo "$SORTED_VERSIONS" | jq -r ".[${{ inputs.keep-count }}:]")
# 初始化刪除計數器和列表
DELETED_COUNT=0
DELETED_LIST="[]"
# 處理每個要刪除的版本
echo "$TO_DELETE" | jq -c '.[]' | while read -r version; do
if [ -z "$version" ] || [ "$version" = "null" ]; then
continue
fi
VERSION_ID=$(echo "$version" | jq -r '.id')
VERSION_NAME=$(echo "$version" | jq -r '.name')
CREATED_AT=$(echo "$version" | jq -r '.created_at')
if [ -z "$VERSION_ID" ] || [ "$VERSION_ID" = "null" ]; then
continue
fi
echo "準備刪除: ID=$VERSION_ID, Version=$VERSION_NAME, Created=$CREATED_AT"
if [ "${{ inputs.dry-run }}" = "true" ]; then
echo "🔍 [模擬執行] 會刪除映像版本: $VERSION_NAME (ID: $VERSION_ID)"
DELETED_COUNT=$((DELETED_COUNT + 1))
else
# 實際刪除
DELETE_RESPONSE=$(curl -s -w "HTTP_STATUS:%{http_code}" \
-X DELETE "${{ inputs.gitea-server }}/api/v1/packages/$OWNER/container/$PACKAGE_NAME/$VERSION_ID" \
-H "Authorization: token ${{ inputs.token }}")
HTTP_STATUS=$(echo "$DELETE_RESPONSE" | grep -o "HTTP_STATUS:[0-9]*" | cut -d: -f2)
if [ "$HTTP_STATUS" = "204" ] || [ "$HTTP_STATUS" = "200" ]; then
echo "✅ 成功刪除映像版本: $VERSION_NAME (ID: $VERSION_ID)"
DELETED_COUNT=$((DELETED_COUNT + 1))
# 更新已刪除列表
DELETED_LIST=$(echo "$DELETED_LIST" | jq ". + [{\"id\": \"$VERSION_ID\", \"version\": \"$VERSION_NAME\", \"created_at\": \"$CREATED_AT\"}]")
else
echo "❌ 刪除失敗映像版本: $VERSION_NAME (ID: $VERSION_ID), HTTP狀態: $HTTP_STATUS"
fi
fi
done
# 由於 while 迴圈在子 shell 中執行,需要重新計算
if [ "${{ inputs.dry-run }}" = "true" ]; then
FINAL_DELETE_COUNT=$(echo "$TO_DELETE" | jq 'length')
echo "deleted-count=$FINAL_DELETE_COUNT" >> $GITHUB_OUTPUT
echo "deleted-images=[]" >> $GITHUB_OUTPUT
echo "🔍 [模擬執行] 總共會刪除 $FINAL_DELETE_COUNT 個映像版本"
else
# 重新獲取並計算實際刪除的數量
NEW_VERSIONS_JSON=$(curl -s "${{ inputs.gitea-server }}/api/v1/packages/$OWNER/container/$PACKAGE_NAME" \
-H "Authorization: token ${{ inputs.token }}" \
-H "Accept: application/json")
NEW_TOTAL_COUNT=$(echo "$NEW_VERSIONS_JSON" | jq '.versions | length')
ACTUAL_DELETED=$((TOTAL_COUNT - NEW_TOTAL_COUNT))
echo "deleted-count=$ACTUAL_DELETED" >> $GITHUB_OUTPUT
echo "deleted-images=$DELETED_LIST" >> $GITHUB_OUTPUT
echo "✅ 清理完成,實際刪除了 $ACTUAL_DELETED 個映像版本"
fiNEW_TOTAL_COUNT=$(echo "$NEW_RELEASES_JSON" | jq 'length')
ACTUAL_DELETED=$((TOTAL_COUNT - NEW_TOTAL_COUNT))
echo "deleted-count=$ACTUAL_DELETED" >> $GITHUB_OUTPUT
echo "deleted-releases=$DELETED_LIST" >> $GITHUB_OUTPUT
echo "✅ 清理完成,實際刪除了 $ACTUAL_DELETED 個版本"
fi