Skip to content

OBS Stale PR Cleanup #1

OBS Stale PR Cleanup

OBS Stale PR Cleanup #1

name: OBS Stale PR Cleanup
# Runs daily. For each open PR, looks at the last commit's date and:
# - skips PRs carrying the `keep-pr-build` label (never delete);
# - posts a one-day deletion warning when the last commit is >= WARN_DAYS old
# (idempotent: a marker in the comment body avoids reposting);
# - deletes the PR's OBS project when the last commit is >= DELETE_DAYS old.
# Staleness is measured from the last commit (not updatedAt) so that posting
# the warning comment does not reset the deletion countdown.
# Can also be triggered manually via workflow_dispatch.
on:
schedule:
- cron: '0 2 * * *' # 02:00 UTC daily
workflow_dispatch: {}
jobs:
cleanup:
name: Clean up OBS projects for stale PRs
runs-on: ubuntu-latest
container: ghcr.io/${{ github.repository_owner }}/obs-tools:latest
permissions:
packages: read
env:
OBS_APIURL: ${{ vars.OBS_APIURL }}
OBS_PR_ROOTPRJ: ${{ vars.OBS_PR_ROOTPRJ }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/obs-setup
with:
obs-apiurl: ${{ vars.OBS_APIURL }}
obs-user: ${{ vars.OBS_USER }}
obs-password: ${{ secrets.OBS_PASSWORD }}
- name: Warn or delete OBS projects for stale PRs
shell: bash
env:
GH_TOKEN: ${{ github.token }}
WARN_DAYS: "6"
DELETE_DAYS: "7"
WARN_MARKER: "<!-- percona-obs-stale-warning -->"
run: |
now_ts=$(date -u +%s)
gh pr list \
--state open \
--limit 200 \
--json number,labels \
| jq -c '.[]' \
| while read -r pr; do
number=$(jq -r '.number' <<<"$pr")
has_keep=$(jq -r 'any(.labels[]; .name == "keep-pr-build")' <<<"$pr")
if [ "$has_keep" = "true" ]; then
echo "PR #${number}: keep-pr-build label present, skipping"
continue
fi
last_commit=$(gh pr view "$number" --json commits \
--jq '.commits | sort_by(.committedDate) | last.committedDate // empty')
if [ -z "$last_commit" ]; then
echo "PR #${number}: no commits found, skipping"
continue
fi
last_ts=$(date -u -d "$last_commit" +%s)
age_days=$(( (now_ts - last_ts) / 86400 ))
PR_ROOTPRJ="${OBS_PR_ROOTPRJ}:pr-${number}"
if [ "$age_days" -ge "$DELETE_DAYS" ]; then
echo "PR #${number}: ${age_days}d stale, deleting ${PR_ROOTPRJ}"
venv/bin/python -m percona_obs --verbose \
-A "$OBS_APIURL" \
-R "$PR_ROOTPRJ" \
sync delete \
--yes \
--recursive \
--from-obs
elif [ "$age_days" -ge "$WARN_DAYS" ]; then
if gh pr view "$number" --json comments --jq '.comments[].body' \
| grep -qF "$WARN_MARKER"; then
echo "PR #${number}: ${age_days}d stale, warning already posted"
continue
fi
echo "PR #${number}: ${age_days}d stale, posting warning"
warn_body=$(printf '%s\n\n:warning: This PR has had no new commits for %d days. Its OBS PR build project (`%s`) will be deleted in 1 day unless:\n\n- new commits are pushed, **or**\n- the `keep-pr-build` label is added.\n' \
"$WARN_MARKER" "$age_days" "$PR_ROOTPRJ")
gh pr comment "$number" --body "$warn_body"
else
echo "PR #${number}: ${age_days}d stale, no action"
fi
done