name: Delete old merged git branches
on:
schedule:
- cron: "0 6 * * 1-5"
workflow_dispatch:
inputs:
max-age-days:
description: "Branches older than 'age' (days) will be deleted. Default: 30"
required: true
default: 30
type: number
main-branch:
description: "The main branch that shouldn't be deleted. Default: 'master'"
required: true
default: master
type: string
env:
MAX_AGE_DAYS: ${{ github.event.inputs.max-age-days }}
MAIN_BRANCH: ${{ github.event.inputs.main-branch }}
jobs:
build:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- name: "Print info"
run: echo "The script will remove all git branches older than ${{ env.MAX_AGE_DAYS }} days and merged into the ${{ env.MAIN_BRANCH }} branch."
- uses: actions/checkout@v3
with:
# Fetch all the branches to be able to list them later
fetch-depth: 0
- name: "Delete old merged branches"
# The best way to understand this is to actually run it piece-by-piece, perhaps skipping the last command (actual delete)
# ----
# 1. The "git branch" command shows all the merged branches with the date (unix epoch seconds) of the latest commit, e.g.
# 1636550813 +0100 origin/1095-improve-trello-provider
# 2. The "awk" command filter out those that are older then the threshold, printing only the branch names ($3)
# 3. Finally, we delete the branches one by one via `xargs git push --delete ...`
# ----
# NOTE: the 'origin/' prefix for the branch name is needed later, otherwise it fails on GH actions with this error: "fatal: --delete doesn't make sense without any refs"
run: git branch -r --merged origin/${{ env.MAIN_BRANCH }} --no-contains origin/${{ env.MAIN_BRANCH }} --format='%(committerdate:raw)%09%(refname:short)' | awk -v max_age=$(( ${{ env.MAX_AGE_DAYS }} * 86400 )) -v now=$(date +%s) '{ diff = now - $1; if (diff > max_age) print $3 }' | sed 's/origin\///' | xargs git push --delete origin