name: Stale Release Branch Cleanup on: schedule: - cron: '0 9 * * 1' # Weekly every Monday at 09:00 UTC workflow_dispatch: inputs: dry_run: description: 'Dry run (no changes made)' required: false default: false type: boolean jobs: cleanup-stale-branches: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: sparse-checkout: | .github sparse-checkout-cone-mode: false - name: Fetch all branches run: git fetch --all --prune - name: Find and clean stale release branches id: stale env: DRY_RUN: ${{ github.event.inputs.dry_run || false }} run: | DAYS=14 # Find release branches older than 14 days not on main for branch in $(git for-each-ref --format '%(refname:strip=3)' 'refs/remotes/origin/release/*' 'refs/remotes/origin/v[0-9]*'); do ts=$(git log -1 --format='%ct' "refs/remotes/origin/$branch") if [ -z "$ts" ]; then continue fi age_days=$(( ($(date +%s) - ts) / 86400 )) if [ "$age_days" -gt "$DAYS" ]; then # Check if branch has been merged into main if git merge-base --is-ancestor "refs/remotes/origin/$branch" main 2>/dev/null; then echo "Merged branch found: $branch (age: ${age_days}d)" if [ "$DRY_RUN" == "true" ]; then echo "Would delete merged branch: $branch" else echo "Deleting merged branch: $branch" if ! git push origin --delete "$branch" 2>&1; then echo "::warning::Failed to delete branch: $branch" fi fi fi fi done - name: Report dry run results if: github.event.inputs.dry_run == 'true' run: | echo "Dry run complete. No branches were deleted." echo "" echo "Release branches found:" git for-each-ref --format '%(refname:strip=3) - %(committerdate:relative)' \ 'refs/remotes/origin/release/*' 'refs/remotes/origin/v[0-9]*' 2>/dev/null || echo "None found"