Add workflow_dispatch job to delete stale Actions artifacts
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
parent
2f8d7175f6
commit
478a92f1a5
78
.github/workflows/cleanup-actions-artifacts.yml
vendored
Normal file
78
.github/workflows/cleanup-actions-artifacts.yml
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
name: cleanup-actions-artifacts
|
||||||
|
|
||||||
|
# Manual reclaim of Actions artifact storage for this repository.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
dry_run:
|
||||||
|
description: List artifacts only; do not delete
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cleanup:
|
||||||
|
name: Delete stale Actions artifacts
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
steps:
|
||||||
|
- name: Remove old artifacts
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
DRY_RUN: ${{ inputs.dry_run }}
|
||||||
|
REPOSITORY: ${{ github.repository }}
|
||||||
|
run: |
|
||||||
|
python3 <<'PY'
|
||||||
|
import json, os, subprocess, sys
|
||||||
|
|
||||||
|
repo = os.environ["REPOSITORY"]
|
||||||
|
dry_run = os.environ.get("DRY_RUN", "false").lower() == "true"
|
||||||
|
|
||||||
|
def gh(*args):
|
||||||
|
return subprocess.check_output(["gh", "api", *args], text=True)
|
||||||
|
|
||||||
|
def should_delete(name: str) -> bool:
|
||||||
|
if name.startswith("playwright-artifacts-"):
|
||||||
|
return True
|
||||||
|
if name.startswith("digest-"):
|
||||||
|
return True
|
||||||
|
if name == "desktop-e2e-screenshots":
|
||||||
|
return True
|
||||||
|
if name.endswith(".dockerbuild"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
artifacts = []
|
||||||
|
page = 1
|
||||||
|
while True:
|
||||||
|
data = json.loads(
|
||||||
|
gh(f"repos/{repo}/actions/artifacts?per_page=100&page={page}")
|
||||||
|
)
|
||||||
|
artifacts.extend(data.get("artifacts", []))
|
||||||
|
if len(data.get("artifacts", [])) < 100:
|
||||||
|
break
|
||||||
|
page += 1
|
||||||
|
|
||||||
|
deleted = 0
|
||||||
|
freed = 0
|
||||||
|
for art in artifacts:
|
||||||
|
name = art["name"]
|
||||||
|
if not should_delete(name):
|
||||||
|
print(f"skip id={art['id']} name={name} size={art['size_in_bytes']}")
|
||||||
|
continue
|
||||||
|
if dry_run:
|
||||||
|
print(f"would delete id={art['id']} name={name} size={art['size_in_bytes']}")
|
||||||
|
continue
|
||||||
|
subprocess.check_call(
|
||||||
|
["gh", "api", "--method", "DELETE", f"repos/{repo}/actions/artifacts/{art['id']}"]
|
||||||
|
)
|
||||||
|
print(f"deleted id={art['id']} name={name} size={art['size_in_bytes']}")
|
||||||
|
deleted += 1
|
||||||
|
freed += art["size_in_bytes"]
|
||||||
|
|
||||||
|
print(f"deleted_count={deleted}")
|
||||||
|
print(f"freed_bytes={freed}")
|
||||||
|
PY
|
||||||
Loading…
x
Reference in New Issue
Block a user