Skip to content

Commit e900527

Browse files
docs: design for onboarding to pinned databricks-bot-engine
Co-authored-by: Isaac
1 parent 5b25eaa commit e900527

1 file changed

Lines changed: 186 additions & 0 deletions

File tree

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Onboard databricks-sql-python to the pinned databricks-bot-engine
2+
3+
**Date:** 2026-07-14
4+
**Status:** Approved (pending spec review)
5+
**Repo:** `databricks/databricks-sql-python`
6+
7+
## Problem
8+
9+
The repo currently runs the PR **reviewer bot** from *vendored* code under
10+
`scripts/reviewer_bot/` + `scripts/shared/`, invoked as
11+
`python -m scripts.reviewer_bot.*`. The upstream `databricks/databricks-bot-engine`
12+
is the documented source of truth: consumers `pip install` it pinned to an
13+
immutable `engine-ref` and call its **reusable workflows**, rather than copying
14+
its code. The vendored copy has already drifted from the engine and will not pick
15+
up engine fixes without hand-resync.
16+
17+
This work converts the repo to the documented consumer model, matching the
18+
existing `databricks/databricks-driver-test` consumer.
19+
20+
## Goal
21+
22+
- Reviewer bot (initial review + follow-up) runs from the pinned engine via its
23+
reusable workflows, installed in REF mode.
24+
- All vendored bot code removed; engine is the single source of truth.
25+
- Trigger policy unchanged: every non-fork PR (no label gate).
26+
- Repo-specific review guidance preserved as engine *additive* prompt.
27+
28+
Non-goals: adopting the **engineer bot** (bug-fix / coverage). Only the reviewer
29+
is in scope, matching what the repo runs today.
30+
31+
## Engine pin
32+
33+
- **Engine SHA:** `d780b2da60bb1ac68bb5cd1acb7cabf495b3ff2d` (current
34+
`databricks-bot-engine` `main` HEAD).
35+
- The SHA is used in BOTH the `uses:` ref AND the `engine-ref:` input of each
36+
caller, so the workflow definition and the installed engine match. Never
37+
`@main` (force-pushable; the job carries secrets).
38+
39+
## Design
40+
41+
### 1. Workflows — thin callers of the engine reusables
42+
43+
**`.github/workflows/reviewer-bot.yml`** (replaces the current hand-rolled job):
44+
```yaml
45+
name: Reviewer Bot
46+
on:
47+
pull_request:
48+
types: [opened, synchronize, reopened, ready_for_review]
49+
workflow_dispatch:
50+
inputs:
51+
pr_number: { description: 'PR number to review', required: true, type: string }
52+
dry_run: { description: 'Print instead of posting', required: false, default: 'true', type: string }
53+
permissions:
54+
contents: read
55+
pull-requests: write
56+
id-token: write
57+
jobs:
58+
review:
59+
uses: databricks/databricks-bot-engine/.github/workflows/reviewer-bot.reusable.yml@d780b2da60bb1ac68bb5cd1acb7cabf495b3ff2d
60+
with:
61+
engine-ref: d780b2da60bb1ac68bb5cd1acb7cabf495b3ff2d
62+
pr-number: ${{ inputs.pr_number }}
63+
dry-run: ${{ inputs.dry_run }}
64+
secrets:
65+
review-bot-app-id: ${{ secrets.REVIEW_BOT_APP_ID }}
66+
review-bot-app-private-key: ${{ secrets.REVIEW_BOT_APP_PRIVATE_KEY }}
67+
databricks-token: ${{ secrets.DATABRICKS_TOKEN }}
68+
databricks-host: ${{ secrets.DATABRICKS_HOST }}
69+
engine-pat: ${{ secrets.BOT_ENGINE_PAT }}
70+
```
71+
72+
**`.github/workflows/reviewer-bot-followup.yml`** (replaces the current job):
73+
```yaml
74+
name: Reviewer Bot — Follow-up
75+
on:
76+
pull_request_review_comment: { types: [created] }
77+
pull_request: { types: [synchronize] }
78+
permissions:
79+
contents: read
80+
pull-requests: write
81+
id-token: write
82+
jobs:
83+
followup:
84+
# No enablement `if:` — keep today's "every non-fork PR" policy. The engine
85+
# reusable's job `if:` still enforces the security floor (fork==false, PR
86+
# open) and loop-prevention lives in the engine's followup.py.
87+
uses: databricks/databricks-bot-engine/.github/workflows/reviewer-bot-followup.reusable.yml@d780b2da60bb1ac68bb5cd1acb7cabf495b3ff2d
88+
with:
89+
engine-ref: d780b2da60bb1ac68bb5cd1acb7cabf495b3ff2d
90+
secrets:
91+
review-bot-app-id: ${{ secrets.REVIEW_BOT_APP_ID }}
92+
review-bot-app-private-key: ${{ secrets.REVIEW_BOT_APP_PRIVATE_KEY }}
93+
databricks-token: ${{ secrets.DATABRICKS_TOKEN }}
94+
databricks-host: ${{ secrets.DATABRICKS_HOST }}
95+
engine-pat: ${{ secrets.BOT_ENGINE_PAT }}
96+
```
97+
98+
The engine reusables own: the fork/open-PR security gate (job `if:`), App-token
99+
mint, Python setup, JFrog-OIDC engine install, `MODEL_ENDPOINT` construction
100+
(`https://$DATABRICKS_HOST/serving-endpoints/databricks-claude-opus-4-8/invocations`),
101+
`workflow_dispatch` input validation, and (for `reviewer-bot`) the PR-head
102+
content-root dispatch security. So the ~250 lines of hand-rolled gate / checkout /
103+
pre-filter logic in the current workflows are removed.
104+
105+
### 2. `.bot/prompts/review/system.md` — repo-specific additive prompt
106+
107+
Verified against the engine source at the pinned SHA
108+
(`reviewer_bot/run_review.py::_review_system_prompt`): the reviewer's **base**
109+
system prompt is **engine-owned** (`SYSTEM_PROMPT` — it owns the output contract,
110+
severity scale, anchoring, and dedup rules). The consumer file is read from the
111+
default path `.bot/prompts/review/system.md` and **appended** as *additive* repo
112+
guidance via `append_repo_guidance`. It is **optional** at the default path
113+
(missing ⇒ engine base alone — no abort). It is read from the TRUSTED checkout
114+
(REPO_ROOT), never the PR-head tree (fork prompt-injection guard).
115+
116+
> Note: the engine README describes this file as "the reviewer's *entire* system
117+
> prompt (absent ⇒ runtime abort)." The **code** at this SHA disagrees — it is
118+
> additive and optional. We follow the code.
119+
120+
We port only the *repo-specific* parts of the current vendored `SYSTEM_PROMPT`
121+
and drop the engine-owned parts (severity scheme, anchor rules, output structure,
122+
dedup, `finalize_review` contract), which the base already owns. Kept:
123+
- "senior code reviewer for databricks-sql-python (the Databricks SQL connector
124+
for Python)" framing + the review axes tuned for this repo.
125+
- Landmarks: `CONTRIBUTING.md` (PEP 8, 100-char limit, DCO sign-off), `README.md`,
126+
connector package under `src/databricks/`, tests under `tests/unit` (fast,
127+
mocked) + `tests/e2e` (warehouse integration).
128+
129+
No `config.yaml`, engineer prompts, or `context-repos.yaml` — none are read by the
130+
reviewer path.
131+
132+
### 3. Deletions (vendored removal)
133+
134+
Delete:
135+
- `scripts/reviewer_bot/` (runtime + tests)
136+
- `scripts/shared/` (runtime + tests)
137+
- `scripts/__init__.py` (only present to package the vendored bot; `dependency_manager.py` runs as a path script)
138+
- `scripts/requirements-sdk.txt`
139+
- `.github/actions/setup-claude-sdk/`
140+
- `.github/workflows/sdk-smoke.yml` (the reviewer-bot *foundation* smoke test; the only consumer of `setup-claude-sdk`)
141+
- `.github/workflows/reviewer-bot-unit-tests.yml` (its tests import the deleted `scripts.reviewer_bot` / `scripts.shared`)
142+
143+
**Keep** (used by unrelated CI — verified via grep):
144+
- `.github/actions/setup-jfrog/` — used by `kernel-e2e.yml` and `setup-poetry`.
145+
- `scripts/dependency_manager.py` — used by `code-quality-checks.yml`.
146+
147+
### 4. Secrets (provisioned by the maintainer, documented in the PR)
148+
149+
| Secret | Status | Purpose |
150+
|---|---|---|
151+
| `REVIEW_BOT_APP_ID` | exists | mint bot App token |
152+
| `REVIEW_BOT_APP_PRIVATE_KEY` | exists | " |
153+
| `DATABRICKS_TOKEN` | exists | model auth |
154+
| `DATABRICKS_HOST` | **NEW** — replaces `MODEL_ENDPOINT` | engine builds `MODEL_ENDPOINT` from it |
155+
| `BOT_ENGINE_PAT` | **NEW** | read access to the private engine repo (REF-mode install) |
156+
157+
The old `MODEL_ENDPOINT` secret is no longer consumed after this change.
158+
159+
## Testing / verification
160+
161+
- Static: `actionlint` on the new workflow YAML if available, else a YAML parse
162+
check; confirm no dangling references to deleted paths remain (grep).
163+
- Runtime: the reusable `uses:` against the **private** engine repo cannot fully
164+
resolve in CI until `BOT_ENGINE_PAT` + `DATABRICKS_HOST` are added as secrets.
165+
End-to-end verification (a real PR review) happens after secrets are
166+
provisioned. This limitation is stated plainly in the PR description — the PR
167+
is not claimed "verified working end-to-end."
168+
169+
## Rollout
170+
171+
1. New branch off `main`; commit workflows + `.bot/` + deletions.
172+
2. Open PR to `databricks/databricks-sql-python` with the secrets checklist.
173+
3. Maintainer adds `DATABRICKS_HOST` + `BOT_ENGINE_PAT`.
174+
4. Merge; first non-fork PR exercises the reviewer end-to-end.
175+
5. Future engine updates: bump the SHA in both `uses:` and `engine-ref:` in
176+
lockstep across both workflows.
177+
178+
## Risks
179+
180+
- **Private-engine install:** REF mode fails without `BOT_ENGINE_PAT`; the engine
181+
action fails fast with a clear error. Documented.
182+
- **README vs. code drift** on the review prompt semantics: resolved by following
183+
the code (additive/optional), recorded above.
184+
- **Reusable `uses: ./…` cross-repo resolution:** the engine's reusables use local
185+
`./.github/actions/...` refs that resolve against the engine repo at the called
186+
ref (verified in the engine's own dogfood). No consumer action needed.

0 commit comments

Comments
 (0)