OBS Stale PR Cleanup #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |