--- /dev/null
+#!/bin/bash
+
+# clean-ci [--dry-run] [--since="relative date"]
+#
+# Cleanup the ceph-ci.git repository branch list by deleting any branch with a
+# HEAD commit date older than (by default) 3 months.
+
+set -e
+
+CEPH_CI=git@github.com:ceph/ceph-ci.git
+DRY_RUN=0
+SINCE="3 months ago"
+
+function eprintf {
+ formats="$1"
+ shift
+ printf "$formats"'\n' "$@" >&2
+}
+
+
+function delete_refs {
+ if [[ DRY_RUN -eq 0 ]]; then
+ eprintf 'Deleting refs: %s' "$*"
+ git push --quiet "$CEPH_CI" --delete "$@"
+ else
+ eprintf 'Would delete refs: %s' "$*"
+ fi
+}
+
+function iterate_ci {
+ cutoff_date=$(date -d "$SINCE" +%s)
+
+ REFS=$(git ls-remote --refs --heads "$CEPH_CI")
+
+ # Fetch the refs, shallow
+ printf '%s' "$REFS" | \
+ cut -f2 | \
+ git fetch --quiet --depth=1 --refetch --filter=blob:none --stdin "$CEPH_CI"
+
+ declare -a TO_DELETE
+
+ # Examine each ref/commit
+ while read commit_ref; do
+ commit=$(cut -f1 <<<"$commit_ref")
+ ref=$(cut -f2 <<<"$commit_ref")
+
+ eprintf 'Examining %s (commit %s)' "$ref" "$commit"
+
+ commit_date=$(git log -1 --format="%ct" "$commit")
+
+ eprintf '\thas commit date: %s' $(date --iso-8601=sec --date="@$commit_date")
+
+ if (( commit_date < cutoff_date )); then
+ TO_DELETE+=("$ref")
+ if [[ DRY_RUN -eq 0 ]]; then
+ eprintf '\twill delete remote ref: %s' "$ref"
+ else
+ eprintf '\twould delete remote ref: %s' "$ref"
+ fi
+ if [[ ${#TO_DELETE[@]} -ge 100 ]]; then
+ delete_refs "${TO_DELETE[@]}"
+ TO_DELETE=()
+ fi
+ else
+ eprintf '\tNOT deleting: %s' "$ref"
+ fi
+ done <<<"$REFS"
+
+ delete_refs "${TO_DELETE[@]}"
+}
+
+function main {
+ eval set -- $(getopt --name "$0" --options 'h' --longoptions 'help,dry-run,since:' -- "$@")
+
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -h|--help)
+ printf '%s: [--dry-run] [--since=<relative time>]\n' "$0"
+ exit 0
+ ;;
+ --dry-run)
+ DRY_RUN=1
+ shift
+ ;;
+ --since)
+ SINCE="$2"
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ done
+
+ iterate_ci
+}
+
+main "$@"