Skip to content

feat(bots): onboard reviewer-bot to pinned databricks-bot-engine #45

feat(bots): onboard reviewer-bot to pinned databricks-bot-engine

feat(bots): onboard reviewer-bot to pinned databricks-bot-engine #45

# Engineer Bot — follow-up.
#
# When someone replies to a review thread on a PR carrying the `engineer-bot`
# label (or the label is applied), the bot re-evaluates the open threads in
# catch-up mode, applies a fixup (or replies / marks blocked), and pushes to the
# PR branch. Driven by this repo's .bot/ prompts.
#
# Like the author, this builds/runs the product (setup-poetry). Shared setup
# (tokens + Node + engine install, PAT-free via an engine-scoped App token) is in
# the local ./.github/actions/bot-prelude composite; this file owns checkout,
# setup-poetry, and the followup run. Engine installed in REF mode pinned to a SHA.
#
# The gate below is the canonical label-gated form copied verbatim from the
# engine dogfood (the single source of truth). It ANDs with the engine-side
# floor; do not weaken it.
name: Engineer Bot — Follow-up
on:
pull_request_review_comment:
types: [created]
# `engineer-bot` label applied → catch-up over pre-existing review threads.
pull_request:
types: [labeled]
permissions:
contents: write # push fixup commits to the PR branch
pull-requests: write # post inline replies
id-token: write # JFrog OIDC exchange for the engine/SDK/CLI install
jobs:
followup:
# SECURITY + scope (CANONICAL label-gated model — verbatim from the engine):
# - skip fork PRs — keep the model + App token out of untrusted code's reach;
# - operate only on non-fork OPEN PRs carrying the `engineer-bot` label
# (maintainer-applied opt-in; label requires triage+);
# - comment path: trusted commenters only (OWNER/MEMBER/COLLABORATOR, or a
# bot — reviewer-bot/Copilot), never the engineer-bot's own comments, and
# never a reviewer-bot reconcile loopback;
# - labeled path: the `engineer-bot` label was just applied by a human.
if: >-
github.event.pull_request.head.repo.fork == false
&& github.event.pull_request.state == 'open'
&& (
(
github.event_name == 'pull_request_review_comment'
&& contains(github.event.pull_request.labels.*.name, 'engineer-bot')
&& !startsWith(github.event.comment.user.login, 'peco-engineer-bot')
&& !contains(github.event.comment.body, '<!-- pr-review-bot:v1 reconcile -->')
&& (
contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
|| (
github.event.comment.user.type == 'Bot'
&& (
startsWith(github.event.comment.user.login, 'peco-review-bot')
|| startsWith(github.event.comment.user.login, 'Copilot')
|| startsWith(github.event.comment.user.login, 'copilot')
)
)
)
)
|| (
github.event_name == 'pull_request'
&& github.event.action == 'labeled'
&& github.event.label.name == 'engineer-bot'
&& github.event.sender.type != 'Bot'
&& !startsWith(github.event.sender.login, 'peco-engineer-bot')
)
)
environment: azure-prod # DATABRICKS_HOST / DATABRICKS_TOKEN live here
runs-on:
group: databricks-protected-runner-group
labels: [linux-ubuntu-latest]
timeout-minutes: 30
concurrency:
group: engineer-bot-followup-pr-${{ github.event.pull_request.number }}
cancel-in-progress: false
steps:
# Checkout FIRST (remote action) so the local `./` composites resolve.
# Check out the PR head BRANCH (not the merge ref) so fixups push back to
# it; bot-run re-establishes the authenticated push remote.
- name: Checkout PR head branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
persist-credentials: false
# Python + connector deps via the repo's OWN setup-poetry action (JFrog
# mirror + poetry lock + install) — egress-safe, tolerates a stale lock.
# The agent runs `poetry run python -m pytest tests/unit` to verify fixups.
- name: Setup Poetry + connector deps (for pytest self-verify)
uses: ./.github/actions/setup-poetry
with:
python-version: '3.11'
# Shared prelude: mint the engineer-bot token (pushes fixup commits, posts
# replies) + the engine-scoped token, set up Node, install the engine.
- name: Bot prelude (tokens + Node + engine install)
id: prelude
uses: ./.github/actions/bot-prelude
with:
app-id: ${{ secrets.ENGINEER_BOT_APP_ID }}
private-key: ${{ secrets.ENGINEER_BOT_APP_PRIVATE_KEY }}
# Pinned engine SHA. DUPLICATED in all four bot workflows
# (engineer-bot{,-followup}.yml, reviewer-bot{,-followup}.yml) — bump
# them in LOCKSTEP or the bots silently run different engine versions.
engine-ref: d24ca2171d191a652a67f4f43995f0959c9a5791
# Run the follow-up. Inlines the engine's bot-run env contract for
# engineer:followup, plus the authenticated push remote bot-run would set
# up (followup pushes fixup commits via a plain `git push`, which doesn't
# consult GH_TOKEN; the checkout is persist-credentials:false).
- name: Run engineer follow-up (catch-up over all unaddressed threads)
env:
GH_TOKEN: ${{ steps.prelude.outputs.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
HEAD_BRANCH: ${{ github.event.pull_request.head.ref }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
TRIGGER_COMMENT_ID: ${{ github.event.comment.id }}
MODEL_ENDPOINT: https://${{ secrets.DATABRICKS_HOST }}/serving-endpoints/databricks-claude-opus-4-8/invocations
DATABRICKS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }}
RUNNER_TEMP: ${{ runner.temp }}
run: |
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
python -m databricks_bot_engine.engineer_bot.run --phase followup \
--system-prompt "$GITHUB_WORKSPACE/.bot/prompts/engineer-followup/system.md"