diff --git a/.github/scripts/github/gh-purge-deleted-branch-workflows.sh b/.github/scripts/github/gh-purge-deleted-branch-workflows.sh new file mode 100755 index 0000000000..3b3b5eb7c9 --- /dev/null +++ b/.github/scripts/github/gh-purge-deleted-branch-workflows.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + echo "Usage: $0 [--dry-run] [--workflow ] " + echo + echo "Arguments:" + echo " --dry-run Only show which runs would be deleted (no deletion)" + echo " --workflow Only purge runs from this workflow name (optional)" + echo " owner/repo GitHub repository in 'owner/repo' format" + exit 1 +} + +log_info() { echo "[INFO] $*"; } +log_warn() { echo "[WARN] $*" >&2; } +log_error() { echo "[ERROR] $*" >&2; exit 1; } + +DRYRUN=false +WORKFLOW_FILTER="" + +# Parse options +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRYRUN=true + shift + ;; + --workflow) + if [[ $# -lt 2 ]]; then + usage + fi + WORKFLOW_FILTER=$2 + shift 2 + ;; + *) + if [[ -z "${REPO:-}" ]]; then + REPO=$1 + shift + else + usage + fi + ;; + esac +done + +if [[ -z "${REPO:-}" ]]; then + usage +fi + +if ! command -v gh >/dev/null 2>&1; then + log_error "GitHub CLI (gh) is required but not installed." +fi +if ! command -v jq >/dev/null 2>&1; then + log_error "jq is required but not installed." +fi + +# Ensure user is logged in +if ! gh auth status >/dev/null 2>&1; then + log_error "You are not logged in to GitHub CLI. Run: gh auth login" +fi + +# Get all existing branches +log_info "Fetching existing branches..." +existing_branches=$(gh api -H "Accept: application/vnd.github+json" \ + "/repos/${REPO}/branches?per_page=100" --paginate \ + | jq -r '.[].name' | sort -u) + +if [[ -z "$existing_branches" ]]; then + log_warn "No branches found in repo. Aborting." + exit 0 +fi +log_info "Found $(echo "$existing_branches" | wc -l) branches." + +# Fetch workflow runs +log_info "Fetching workflow runs..." +gh api -H "Accept: application/vnd.github+json" \ + "/repos/${REPO}/actions/runs?per_page=100" --paginate \ + | jq -c '.workflow_runs[] | {id: .id, branch: .head_branch, workflow: .name}' \ + | while read -r run; do + run_id=$(echo "$run" | jq -r '.id') + run_branch=$(echo "$run" | jq -r '.branch') + workflow_name=$(echo "$run" | jq -r '.workflow') + + if [[ -z "$run_branch" ]]; then + log_warn "Run $run_id has no branch (skipping)." + continue + fi + + # Skip if branch exists + if echo "$existing_branches" | grep -qx "$run_branch"; then + continue + fi + + # Skip if workflow filter is set and does not match + if [[ -n "$WORKFLOW_FILTER" && "$workflow_name" != "$WORKFLOW_FILTER" ]]; then + continue + fi + + if [[ "$DRYRUN" == true ]]; then + log_info "[DRY-RUN] Would delete run $run_id (branch: $run_branch, workflow: $workflow_name)" + else + log_info "Deleting run $run_id (branch: $run_branch, workflow: $workflow_name)" + gh api -X DELETE \ + "/repos/${REPO}/actions/runs/${run_id}" >/dev/null || true + fi + done + +if [[ "$DRYRUN" == true ]]; then + log_info "Dry-run finished. No runs were deleted." +else + log_info "Finished purging workflow runs for deleted branches." +fi diff --git a/.github/workflows/tidy-up-auto.yml b/.github/workflows/tidy-up-auto.yml index e752ae7a23..4cb16db61a 100644 --- a/.github/workflows/tidy-up-auto.yml +++ b/.github/workflows/tidy-up-auto.yml @@ -2,6 +2,9 @@ name: delete old workflow runs on: schedule: - cron: '0 0 * * *' # nightly + push: + branches: + - master jobs: delete_old_workflow_runs: @@ -17,3 +20,16 @@ jobs: repository: ${{ github.repository }} retain_days: 14 keep_minimum_runs: 2 + + purge_deleted_branch_workflows: + runs-on: ubuntu-latest + permissions: + actions: write + contents: read + steps: + - name: Check out repository code + uses: actions/checkout@v4 + - name: purge workflows on deleted branches + run: .github/scripts/github/gh-purge-deleted-branch-workflows.sh X11Libre/xserver + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}