Skip to content

Commit

Permalink
feat: support pruning merged preview branches (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
Oreoxmt authored Jul 11, 2024
1 parent ad36c1d commit 20de1b3
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/prune_branches.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Prune merged preview branches

on:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:

prune_branches:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout current repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Delete remote branches
run: |
BRANCHES=($(git branch -r | sed 's/^[[:space:]]*origin\///'))
if [ ${#BRANCHES[@]} -gt 0 ]; then
./prune_preview_branches.sh "${BRANCHES[@]}"
else
echo "No branches to prune."
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DELETE_BRANCHES: "remote"
70 changes: 70 additions & 0 deletions prune_preview_branches.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash

set -e

check_prerequisites() {
# Verify if jq is installed and GITHUB_TOKEN is set.
which jq &>/dev/null || (echo "Error: jq is required but not installed. You can download and install jq from <https://stedolan.github.io/jq/download/>." && exit 1)

test -n "$GITHUB_TOKEN" || (echo "Error: GITHUB_TOKEN (repo scope) is required but not set." && exit 1)
}

is_pr_merged() {
# Verify if a PR is merged.
local repo_owner="$1" repo_name="$2" pr_number="$3"
local api_url="https://api.github.com/repos/${repo_owner}/${repo_name}/pulls/${pr_number}"
local is_merged
is_merged=$(curl -fsSL -H "Authorization: token $GITHUB_TOKEN" "$api_url" | jq -r '.merged_at')
[[ -n "$is_merged" && "$is_merged" != "null" ]]
}

process_branch() {
# If the branch starts with 'preview', it checks if the associated pull request is merged.
# If it is merged, the branch is added to a list of branches to be pruned. Otherwise, the branch is skipped.
local branch="$1"
if [[ $branch == preview* ]]; then
IFS='/' read -r _ repo_owner repo_name pr_number <<< "$branch"
if is_pr_merged "$repo_owner" "$repo_name" "$pr_number"; then
echo "$branch: This preview PR is merged, will be pruned."
PRUNE_BRANCHES+=("$branch")
else
echo "$branch: This preview PR is not merged, skipping."
fi
fi
}

delete_branch() {
# Delete a branch based on the specified mode (local or remote).
local branch="$1" mode="$2"
echo "Deleting branch: $branch"
case "$mode" in
local) git branch -D "$branch" ;;
remote) git push origin --delete "$branch" ;;
*) echo "No action specified for branch deletion." ;;
esac
}

# Get the directory of this script.
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
cd "$SCRIPT_DIR"

check_prerequisites

# Check if arguments are passed.
if [ "$#" -eq 0 ]; then
set +o posix
mapfile -t BRANCHES < <(git branch --list | sed 's/^[*[:space:]]*//')
else
BRANCHES=("$@")
fi

PRUNE_BRANCHES=()

for branch in "${BRANCHES[@]}"; do
process_branch "$branch"
done

# Delete branches in the prune list.
for branch in "${PRUNE_BRANCHES[@]}"; do
delete_branch "$branch" "${DELETE_BRANCHES:-}"
done

0 comments on commit 20de1b3

Please sign in to comment.