name: TheRock PR Bot on: workflow_dispatch: # SECURITY: pull_request_target runs in the BASE-repo context, so secrets and # a write token are available even for PRs opened from FORKS. # # This is SAFE here ONLY because this workflow: # • NEVER checks out or executes PR head code (see checkout step below), # • runs the TRUSTED policy_check.py / policy.yml from the base branch, and # • reads all PR data via the GitHub API. # Do NOT add build/test/install steps that run PR-provided code, and do NOT # change the checkout to the PR head — that would create a "pwn request". # Refs: # https://docs.github.com/en/actions/reference/security/securely-using-pull_request_target # https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/ pull_request_target: branches: [main, pr-bot-test] types: [opened, synchronize, reopened, ready_for_review, edited] # Least privilege. Writes are needed to post the results comment and manage the # "Not ready to Review" label; everything else stays read-only. permissions: contents: read pull-requests: write # post / update the policy results table comment issues: write # add / remove the "Not ready to Review" label checks: read # Avoid two runs racing on the same PR's comment/label (e.g. fast pushes). concurrency: group: therock-pr-bot-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: policy: name: therock-pr-bot runs-on: ubuntu-24.04 steps: # SECURITY: check out the TRUSTED base commit, NEVER the PR head. This # guarantees we run OUR policy_check.py / policy.yml — not the fork's. # `persist-credentials: false` follows the safer-checkout defaults # (https://github.blog/changelog/2026-06-18-safer-pull_request_target-defaults-for-github-actions-checkout/). - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.11" - name: Detect GitHub App secrets id: app-secrets shell: bash env: APP_ID: ${{ secrets.THEROCK_PR_BOT_APPID }} APP_KEY: ${{ secrets.THEROCK_PRBOT_KEY }} run: | if [[ -n "$APP_ID" && -n "$APP_KEY" ]]; then echo "available=true" >> "$GITHUB_OUTPUT" else echo "available=false" >> "$GITHUB_OUTPUT" fi - name: Create GitHub App token id: app-token if: steps.app-secrets.outputs.available == 'true' uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: app-id: ${{ secrets.THEROCK_PR_BOT_APPID }} private-key: ${{ secrets.THEROCK_PRBOT_KEY }} # SECURITY: only fixed, trusted dependencies — never installed from the PR. - name: Install deps run: python -m pip install --upgrade pip requests pyyaml - name: Enforce policy env: GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} HAS_GITHUB_APP_TOKEN: ${{ steps.app-secrets.outputs.available }} POST_COMMENTS: ${{ steps.app-secrets.outputs.available }} MUTATE_PR: ${{ steps.app-secrets.outputs.available }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} PR_NUMBER: ${{ github.event.pull_request.number }} SHA: ${{ github.event.pull_request.head.sha }} run: python skills/therock_pr_bot/policy_check.py --timeout-seconds 900 --poll-seconds 15