From 3b2f2ae71ab8ffe7262f0603c75b86e4ec12e680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Fern=C3=A1ndez?= Date: Thu, 4 Nov 2021 22:57:31 +0100 Subject: [PATCH] ci: add maintenance workflow (#643) [skip ci] --- .github/workflows/maintenance.yml | 46 ++++++++++++++++ .../delete_ghcr_dangling_images.sh | 33 ++++++++++++ .../workflows/maintenance/delete_workflows.sh | 54 +++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 .github/workflows/maintenance.yml create mode 100755 .github/workflows/maintenance/delete_ghcr_dangling_images.sh create mode 100755 .github/workflows/maintenance/delete_workflows.sh diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml new file mode 100644 index 00000000..613cb084 --- /dev/null +++ b/.github/workflows/maintenance.yml @@ -0,0 +1,46 @@ +name: Maintenance ๐Ÿงฐ + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + workflow_removal: + runs-on: ubuntu-latest + name: Workflow cleanup ๐Ÿงน๐Ÿ‘ทโ€โ™‚๏ธ + # Errors will probably be caused by excesses in API quota, so we can safely continue. + # Remaining workflows will be removed in the next scheduled run. + continue-on-error: true + steps: + - name: Clone repository + uses: actions/checkout@v2.3.4 + + - name: Run deletion script ๐Ÿ—‘ + run: ./delete_workflows.sh lowlighter/metrics + working-directory: ./.github/workflows/maintenance + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + dangling_images_removal: + runs-on: ubuntu-latest + name: Cleanup dangling images from GHCR ๐Ÿงน๐Ÿ“ฆ + # Errors will probably be caused by excesses in API quota, so we can safely continue. + # Remaining workflows will be removed in the next scheduled run. + continue-on-error: true + # Pay attention that the org name is not necessary here, as gh will automatically take the one from the logged in user. + strategy: + fail-fast: false + matrix: + container: + - 'metrics' + + steps: + - name: Clone repository + uses: actions/checkout@v2.3.4 + + - name: Run deletion script ๐Ÿ—‘ + run: ./delete_ghcr_dangling_images.sh ${{ matrix.container }} + working-directory: ./.github/workflows/maintenance + env: + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} diff --git a/.github/workflows/maintenance/delete_ghcr_dangling_images.sh b/.github/workflows/maintenance/delete_ghcr_dangling_images.sh new file mode 100755 index 00000000..f33c6aa2 --- /dev/null +++ b/.github/workflows/maintenance/delete_ghcr_dangling_images.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +# Simple script to remove dangling images from GHCR +# You need to be logged to 'gh' first. + +# package_name syntax. i.e: jellyfin-vue +container="$1" +temp_file="ghcr_prune.ids" +rm -rf $temp_file + +echo "Fetching dangling images from GHCR..." +gh api /user/packages/container/${container}/versions --paginate > $temp_file + +ids_to_delete=$(cat "$temp_file" | jq -r '.[] | select(.metadata.container.tags==[]) | .id') + +if [ "${ids_to_delete}" = "" ] +then + echo "There are no dangling images to remove for this package" + exit 0 +fi + +echo -e "\nDeleting dangling images..." +while read -r line; do + id="$line" + ## Workaround for https://github.com/cli/cli/issues/4286 and https://github.com/cli/cli/issues/3937 + echo -n | gh api --method DELETE /user/packages/container/${container}/versions/${id} --input - + echo Dangling image with ID $id deleted successfully +done <<< $ids_to_delete + +rm -rf $temp_file +echo -e "\nAll the dangling images have been removed successfully" +exit 0 diff --git a/.github/workflows/maintenance/delete_workflows.sh b/.github/workflows/maintenance/delete_workflows.sh new file mode 100755 index 00000000..4fd45636 --- /dev/null +++ b/.github/workflows/maintenance/delete_workflows.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -e + +# Simple script to remove workflows that are not successful or failed (with completion status like skipped, cancelled, etc.) +# It also removes successful or failed workflows that doesn't have artifacts or logs. +# You need to be logged to 'gh' first + +# owner/repo syntax +repo="$1" + +temp_file="workflow_runs.payload" +rm -rf $temp_file + +echo "Fetching workflows..." +echo $(gh api /repos/${repo}/actions/runs --paginate | jq '{count: .total_count, runs: [.workflow_runs[] | select(.status=="completed") | {id, conclusion}]}') | jq '.' > $temp_file + +ids_to_delete=$(cat "$temp_file" | jq -r '.runs | .[] | select((.conclusion!="success") and (.conclusion!="failure")) | .id') + +if [ "${ids_to_delete}" = "" ] +then + echo "All workflows are exited successfully or failed. Nothing to remove" +else + echo "Removing all the workflows that are not successful or failed..." + while read -r line; do + id="$line" + ## Workaround for https://github.com/cli/cli/issues/4286 and https://github.com/cli/cli/issues/3937 + echo -n | gh api --method DELETE /repos/${repo}/actions/runs/${id} --input - + + echo "Stale workflow run with ID $id deleted successfully!" + done <<< $ids_to_delete +fi + +ids_to_delete=$(cat "$temp_file" | jq -r '.runs | .[] | select((.conclusion=="success") or (.conclusion=="failure")) | .id') + +if [ "${ids_to_delete}" = "" ] +then + echo "No workflows to check for logs or artifacts. Exiting..." +else + echo -e "\nDeleting workflows without logs and artifacts..." + while read -r line; do + id="$line" + artifact_count=$(gh api /repos/${repo}/actions/runs/${id}/artifacts | jq -r '.total_count') + if [ "${artifact_count}" = "0" ] + then + gh api --silent /repos/${repo}/actions/runs/${id}/logs || \ + echo -n | gh api --method DELETE /repos/${repo}/actions/runs/${id} --input - && \ + echo "Workflow run without logs and artifacts with ID $id deleted successfully!" + fi + done <<< $ids_to_delete +fi + +rm -rf $temp_file +echo -e "\n\nFinished the workflow run cleaning process" +exit 0