feat(bots): onboard reviewer-bot to pinned databricks-bot-engine #9
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
| # Reviewer Bot — initial PR review. | |
| # | |
| # Own-job composite caller of the databricks-bot-engine actions. We deliberately | |
| # do NOT use the engine's reusable WORKFLOW (jobs.<id>.uses: | |
| # .../reviewer-bot.reusable.yml@<sha>): a cross-repo reusable-workflow call to | |
| # the private engine fails to resolve ("workflow was not found"). Cross-repo | |
| # composite ACTIONS (steps: - uses: .../.github/actions/...@<sha>) DO resolve | |
| # in-org — this is the pattern databricks-driver-test's engineer bot uses in | |
| # production, and the one the engineer-bot workflows here use too. So this file | |
| # owns the job and replicates the reusable's steps (fork gate, token mint, | |
| # install, run) with cross-repo action refs. | |
| # | |
| # Engine pin: the SHA below pins BOTH the action refs AND engine-ref, so the | |
| # workflow and installed engine match. Bump in lockstep; never @main. | |
| # | |
| # Auth: PAT-free. We mint a short-lived, engine-scoped App installation token | |
| # from the review-bot App creds and pass it as engine-pat to install-bot-engine | |
| # (no stored BOT_ENGINE_PAT). | |
| name: Reviewer Bot | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to review' | |
| required: true | |
| type: string | |
| dry_run: | |
| description: 'Print what would be posted instead of posting' | |
| required: false | |
| default: 'true' | |
| type: string | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| id-token: write # JFrog OIDC exchange for the engine/SDK/CLI install | |
| jobs: | |
| review: | |
| # SECURITY FLOOR (was the reusable's job `if:`): manual dispatch, OR a | |
| # non-draft, non-fork PR. fork == false keeps the App + model tokens off | |
| # untrusted code. | |
| if: >- | |
| github.event_name == 'workflow_dispatch' | |
| || (github.event.pull_request.draft == false | |
| && github.event.pull_request.head.repo.fork == false) | |
| environment: azure-prod # DATABRICKS_HOST / DATABRICKS_TOKEN live here | |
| runs-on: | |
| group: databricks-protected-runner-group | |
| labels: [linux-ubuntu-latest] | |
| timeout-minutes: 30 | |
| steps: | |
| # Checkout FIRST. Default ref = the PR merge ref on pull_request, the | |
| # default branch on dispatch. persist-credentials:false — the reviewer | |
| # reads this tree via read_paths/grep, so no token may sit in .git/config. | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| # Mint the review-bot token (posts findings). | |
| - name: Mint review-bot App token | |
| id: setup | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ secrets.REVIEW_BOT_APP_ID }} | |
| private-key: ${{ secrets.REVIEW_BOT_APP_PRIVATE_KEY }} | |
| - name: Setup Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.11' | |
| - name: Setup Node (for the Claude Code CLI the SDK spawns) | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: '20' | |
| # PAT-free engine install: mint a per-run token scoped to ONLY the engine | |
| # repo (contents:read) from the review-bot App creds. Requires the | |
| # review-bot App installed on databricks-bot-engine with contents:read. | |
| - name: Mint engine-scoped install token | |
| id: engine-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ secrets.REVIEW_BOT_APP_ID }} | |
| private-key: ${{ secrets.REVIEW_BOT_APP_PRIVATE_KEY }} | |
| owner: databricks | |
| repositories: databricks-bot-engine | |
| permission-contents: read | |
| # LOCAL composite (not a cross-repo `uses:` of the engine — that fails to | |
| # resolve from this external repo). It pip-installs the pinned engine via | |
| # the engine-scoped token. | |
| - name: Install engine + Claude SDK/CLI | |
| uses: ./.github/actions/install-bot-engine | |
| with: | |
| engine-ref: b6205fb502566d617a456ccf3c37f3e4e3072ccd | |
| engine-token: ${{ steps.engine-token.outputs.token }} | |
| - name: Resolve trigger inputs | |
| id: inputs | |
| # SECURITY: dispatcher-supplied values pass via env, never interpolated | |
| # into the script body (an inline expression would inject at assignment, | |
| # before the digits-only check). Env values expand without re-parsing. | |
| env: | |
| GH_TOKEN: ${{ steps.setup.outputs.token }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| INPUT_PR: ${{ inputs.pr_number }} | |
| INPUT_DRY_RUN: ${{ inputs.dry_run }} | |
| EVENT_PR: ${{ github.event.pull_request.number }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| if [ "$EVENT_NAME" = "workflow_dispatch" ]; then | |
| RAW_PR="$INPUT_PR"; DRY_RUN="$INPUT_DRY_RUN" | |
| else | |
| RAW_PR="$EVENT_PR"; DRY_RUN="false" | |
| fi | |
| [[ "$RAW_PR" =~ ^[0-9]+$ ]] || { echo "::error::Invalid pr_number '$RAW_PR'"; exit 1; } | |
| case "$DRY_RUN" in true|false) ;; *) DRY_RUN="true" ;; esac # fail safe | |
| HEAD_SHA=$(gh pr view "$RAW_PR" --repo "$REPO" --json headRefOid -q .headRefOid) | |
| { echo "pr_number=$RAW_PR"; echo "head_sha=$HEAD_SHA"; echo "dry_run=$DRY_RUN"; } >> "$GITHUB_OUTPUT" | |
| - name: Run reviewer | |
| env: | |
| GH_TOKEN: ${{ steps.setup.outputs.token }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| PR_NUMBER: ${{ steps.inputs.outputs.pr_number }} | |
| HEAD_SHA: ${{ steps.inputs.outputs.head_sha }} | |
| DRY_RUN: ${{ steps.inputs.outputs.dry_run }} | |
| MODEL_ENDPOINT: https://${{ secrets.DATABRICKS_HOST }}/serving-endpoints/databricks-claude-opus-4-8/invocations | |
| DATABRICKS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }} | |
| RUNNER_TEMP: ${{ runner.temp }} | |
| # The reviewer's repo-specific ADDITIVE guidance, read from the TRUSTED | |
| # checkout (run_review enforces containment). Engine owns the base prompt. | |
| REVIEW_SYSTEM_PROMPT: .bot/prompts/review/system.md | |
| run: python -m databricks_bot_engine.reviewer_bot.run_review |