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[@]}"