Close Low-Quality PRs #28
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: Close Low-Quality PRs | |
| # Auto-close any open PR (including drafts, regardless of age) authored by an | |
| # external OSS contributor that Greptile reviewed with a confidence score | |
| # below 4/5. Closures are explained in a comment that tells the contributor | |
| # to push fixes and open a fresh PR (since OSS authors cannot reopen a PR | |
| # closed by a bot/maintainer) or comment `@agent-shin reconsider` to have | |
| # Agent Shin re-evaluate. | |
| # | |
| # Manual one-off run: | |
| # gh workflow run "Close Low-Quality PRs" -f close=true | |
| # | |
| # Dry-run preview (no PRs are touched): | |
| # gh workflow run "Close Low-Quality PRs" -f close=false | |
| on: | |
| schedule: | |
| # Daily at 09:00 UTC. Pairs well with the stale-issue workflow at midnight. | |
| - cron: "0 9 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| close: | |
| description: "Actually close matching PRs (false = dry run)." | |
| required: false | |
| default: "false" | |
| type: choice | |
| options: | |
| - "true" | |
| - "false" | |
| min_age_days: | |
| description: "Minimum PR age in days (default 0 = no age filter)." | |
| required: false | |
| default: "0" | |
| min_score: | |
| description: "Greptile score below which a PR is closed (1-5)." | |
| required: false | |
| default: "4" | |
| limit: | |
| description: "Maximum number of PRs to close in a single run." | |
| required: false | |
| default: "25" | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| close-low-quality-prs: | |
| if: github.repository == 'BerriAI/litellm' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout triage script | |
| uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 | |
| with: | |
| sparse-checkout: .github/scripts | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: "3.12" | |
| - name: Run low-quality PR closer | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Scheduled runs are ALWAYS dry-run, even when AGENT_SHIN_ENABLED is | |
| # "true", so the team can QA the closer's verdicts in step summaries | |
| # before any contributor sees a PR closed. Real closures only happen | |
| # on manual workflow_dispatch with close=true (and the variable set). | |
| CLOSE_FLAG: ${{ github.event.inputs.close || 'false' }} | |
| AGENT_SHIN_ENABLED: ${{ vars.AGENT_SHIN_ENABLED }} | |
| MIN_AGE_DAYS: ${{ github.event.inputs.min_age_days || '0' }} | |
| MIN_SCORE: ${{ github.event.inputs.min_score || '4' }} | |
| LIMIT: ${{ github.event.inputs.limit || '25' }} | |
| run: | | |
| set -euo pipefail | |
| ARGS=( | |
| --repo "${{ github.repository }}" | |
| --min-age-days "${MIN_AGE_DAYS}" | |
| --min-score "${MIN_SCORE}" | |
| --limit "${LIMIT}" | |
| ) | |
| if [ "${AGENT_SHIN_ENABLED:-false}" != "true" ]; then | |
| echo "::notice::AGENT_SHIN_ENABLED is not 'true' -> forcing dry-run regardless of close input." | |
| elif [ "${GITHUB_EVENT_NAME:-}" = "workflow_dispatch" ] && [ "${CLOSE_FLAG}" = "true" ]; then | |
| ARGS+=(--close) | |
| echo "::notice::Running in close-on-fail mode." | |
| else | |
| echo "::notice::AGENT_SHIN_ENABLED is true but this trigger is dry-run (scheduled event or close=false)." | |
| fi | |
| python3 .github/scripts/close_low_quality_prs.py "${ARGS[@]}" |