From 0379065ce862932f461b70acacf9341c46f0ee5a Mon Sep 17 00:00:00 2001 From: richarddushime Date: Mon, 22 Dec 2025 16:26:23 +0100 Subject: [PATCH] Workflow to Cleanup Branches --- .github/workflows/cleanup-branches.yml | 149 +++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 .github/workflows/cleanup-branches.yml diff --git a/.github/workflows/cleanup-branches.yml b/.github/workflows/cleanup-branches.yml new file mode 100644 index 0000000000..536a13f384 --- /dev/null +++ b/.github/workflows/cleanup-branches.yml @@ -0,0 +1,149 @@ +name: Cleanup Branches + +on: + schedule: + - cron: '0 0 * * 0' # Run every Sunday at midnight + workflow_dispatch: + inputs: + dry_run: + description: 'Dry run (do not delete)' + required: false + type: boolean + default: false + +permissions: + contents: write + +jobs: + cleanup-staging: + name: Cleanup Staging Aggregate Branches + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Delete old staging branches + env: + DRY_RUN: ${{ inputs.dry_run }} + run: | + echo "Fetching all branches..." + git fetch --all --prune + + echo "Listing staging-aggregate branches..." + # Get branches matching pattern, sort by committer date (descending), skip first 10 + BRANCHES_TO_DELETE=$(git branch -r --list 'origin/staging-aggregate-*' --sort=-committerdate | tail -n +11 | sed 's/origin\///') + + if [ -z "$BRANCHES_TO_DELETE" ]; then + echo "No old staging branches to delete." + exit 0 + fi + + echo "Found branches to delete:" + echo "$BRANCHES_TO_DELETE" + + for branch in $BRANCHES_TO_DELETE; do + branch=$(echo "$branch" | xargs) # trim whitespace + if [ "$DRY_RUN" = "true" ]; then + echo "[DRY RUN] Would delete: $branch" + else + echo "Deleting: $branch" + git push origin --delete "$branch" || echo "Failed to delete $branch" + fi + done + + cleanup-merged: + name: Cleanup Merged Branches + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Delete merged branches + env: + DRY_RUN: ${{ inputs.dry_run }} + run: | + echo "Fetching all branches..." + git fetch --all --prune --tags + + # Define protected branches + PROTECTED_BRANCHES="master|main|staging|production|gh-pages" + + echo "Finding merged branches..." + # List remote branches merged into origin/master, exclude protected ones + MERGED_BRANCHES=$(git branch -r --merged origin/master | grep -vE "HEAD|$PROTECTED_BRANCHES" | sed 's/origin\///') + + if [ -z "$MERGED_BRANCHES" ]; then + echo "No merged branches to delete." + exit 0 + fi + + echo "Found merged branches to delete:" + echo "$MERGED_BRANCHES" + + for branch in $MERGED_BRANCHES; do + branch=$(echo "$branch" | xargs) + if [ "$DRY_RUN" = "true" ]; then + echo "[DRY RUN] Would delete: $branch" + else + echo "Deleting: $branch" + git push origin --delete "$branch" || echo "Failed to delete $branch" + fi + done + + cleanup-stale: + name: Cleanup Stale Branches + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Delete stale branches + env: + DRY_RUN: ${{ inputs.dry_run }} + MONTHS_THRESHOLD: 6 + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "Fetching all branches..." + git fetch --all --prune + + PROTECTED_BRANCHES="master|main|staging|production|gh-pages" + + # Calculate threshold date (6 months ago) + THRESHOLD_DATE=$(date -d "-$MONTHS_THRESHOLD months" +%s) + echo "Threshold date: $(date -d "@$THRESHOLD_DATE")" + + echo "Checking for stale branches..." + + # Iterate over all remote branches + git branch -r | grep -vE "HEAD|$PROTECTED_BRANCHES" | while read -r branch; do + branch=$(echo "$branch" | xargs) # trim whitespace + clean_branch_name=${branch#origin/} + + # Get last commit date for the branch + last_commit_date=$(git log -1 --format=%ct "$branch") + + # check if branch has open PR + open_pr_count=$(gh pr list -H "$clean_branch_name" --state open --json number | jq '. | length') + + if [ "$open_pr_count" -gt 0 ]; then + echo "Skipping $clean_branch_name (Has open PR)" + continue + fi + + if [ "$last_commit_date" -lt "$THRESHOLD_DATE" ]; then + echo "Branch '$clean_branch_name' is stale (Last commit: $(date -d "@$last_commit_date"))" + + if [ "$DRY_RUN" = "true" ]; then + echo "[DRY RUN] Would delete: $clean_branch_name" + else + echo "Deleting: $clean_branch_name" + git push origin --delete "$clean_branch_name" || echo "Failed to delete $clean_branch_name" + fi + fi + done