Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/actions/setup-claude-sdk/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright (c) 2025 ADBC Drivers Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

# Install the Claude Agent SDK (pip) + the Claude Code CLI (npm) that the bots
# now spawn, via Databricks' internal JFrog mirror. The protected runner group
# is egress-blocked from pypi.org and registry.npmjs.org, so this configures
# both package managers through JFrog (same mechanism as setup-jfrog / the
# sdk-smoke workflow, which is verified working end-to-end against the gateway).
#
# Requires `id-token: write` on the calling job (for the JFrog OIDC exchange).
# Idempotent w.r.t. a prior setup-jfrog step (re-exchanging the token + re-
# setting PIP_INDEX_URL is harmless).
name: Setup Claude Agent SDK
description: Install claude-agent-sdk (pip) + Claude Code CLI (npm) via the internal JFrog mirror.

inputs:
requirements-file:
description: >-
Path to the SDK requirements file, relative to the job working directory
($GITHUB_WORKSPACE — composite `run:` steps always execute there, not at
the caller's working-directory). Defaults to scripts/requirements-sdk.txt,
correct when the repo is checked out at the workspace root (e.g. the
reviewer bots). Workflows that check the repo into a subdir (the engineer
bots use `path: internal-repo`) MUST pass the prefixed path, e.g.
internal-repo/scripts/requirements-sdk.txt.
required: false
default: scripts/requirements-sdk.txt

runs:
using: composite
steps:
- name: Setup Node (for the Claude Code CLI the SDK spawns)
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '20'

- name: Configure JFrog (pip + npm internal mirror)
uses: ./.github/actions/setup-jfrog
with:
configure-pip: 'true'
configure-npm: 'true'

- name: Install claude-agent-sdk + Claude Code CLI
shell: bash
run: |
python -m pip install --upgrade pip
# Install the SDK from the documented requirements file (not a bare
# `pip install claude-agent-sdk`) so CI and local docs share one
# dependency source and future pins land in a single place. (Review)
pip install -r "${{ inputs.requirements-file }}"
npm i -g @anthropic-ai/claude-code
echo "claude CLI: $(command -v claude || echo 'NOT FOUND')"
78 changes: 78 additions & 0 deletions .github/actions/setup-jfrog/setup-jfrog/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Setup JFrog OIDC
description: Obtain a JFrog access token via GitHub OIDC and configure package managers

inputs:
configure-pip:
description: Configure pip to use JFrog PyPI proxy
default: "true"
configure-cargo:
description: Configure Cargo to use JFrog crates proxy
default: "false"
configure-npm:
description: Configure npm to use JFrog npm proxy
default: "false"

runs:
using: composite
steps:
- name: Get JFrog OIDC token
shell: bash
run: |
set -euo pipefail
ID_TOKEN=$(curl -sLS \
-H "User-Agent: actions/oidc-client" \
-H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=jfrog-github" | jq .value | tr -d '"')
echo "::add-mask::${ID_TOKEN}"
ACCESS_TOKEN=$(curl -sLS -XPOST -H "Content-Type: application/json" \
"https://databricks.jfrog.io/access/api/v1/oidc/token" \
-d "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"${ID_TOKEN}\", \"provider_name\": \"github-actions\"}" | jq .access_token | tr -d '"')
echo "::add-mask::${ACCESS_TOKEN}"
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
echo "FAIL: Could not extract JFrog access token"
exit 1
fi
echo "JFROG_ACCESS_TOKEN=${ACCESS_TOKEN}" >> "$GITHUB_ENV"
echo "JFrog OIDC token obtained successfully"

- name: Configure pip
if: inputs.configure-pip == 'true'
shell: bash
run: |
set -euo pipefail
echo "PIP_INDEX_URL=https://gha-service-account:${JFROG_ACCESS_TOKEN}@databricks.jfrog.io/artifactory/api/pypi/db-pypi/simple" >> "$GITHUB_ENV"
echo "pip configured to use JFrog registry"

- name: Configure Cargo
if: inputs.configure-cargo == 'true'
shell: bash
run: |
set -euo pipefail
mkdir -p ~/.cargo
cat > ~/.cargo/config.toml << EOF
[source.crates-io]
replace-with = "jfrog"
[source.jfrog]
registry = "sparse+https://databricks.jfrog.io/artifactory/api/cargo/db-cargo-remote/index/"
[registries.jfrog]
index = "sparse+https://databricks.jfrog.io/artifactory/api/cargo/db-cargo-remote/index/"
credential-provider = ["cargo:token"]
EOF
cat > ~/.cargo/credentials.toml << EOF
[registries.jfrog]
token = "Bearer ${JFROG_ACCESS_TOKEN}"
EOF
echo "CARGO_REGISTRIES_JFROG_TOKEN=Bearer ${JFROG_ACCESS_TOKEN}" >> "$GITHUB_ENV"
echo "Cargo configured to use JFrog registry"

- name: Configure npm
if: inputs.configure-npm == 'true'
shell: bash
run: |
set -euo pipefail
cat > ~/.npmrc << EOF
registry=https://databricks.jfrog.io/artifactory/api/npm/db-npm/
//databricks.jfrog.io/artifactory/api/npm/db-npm/:_authToken=${JFROG_ACCESS_TOKEN}
always-auth=true
EOF
echo "npm configured to use JFrog registry"
34 changes: 34 additions & 0 deletions .github/workflows/reviewer-bot-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Unit tests for the migrated PR-review bot (scripts/reviewer_bot + scripts/shared).
#
# Pure-logic tests — no secrets, no model calls, no Claude Agent SDK install
# (the SDK import is guarded, so the tests run with just pytest, which the
# connector's poetry dev-deps already provide). Runs only when the bot code
# changes, so it doesn't add load to every connector PR.
name: Reviewer Bot Unit Tests

on:
pull_request:
paths:
- 'scripts/shared/**'
- 'scripts/reviewer_bot/**'
- '.github/workflows/reviewer-bot-unit-tests.yml'

permissions:
contents: read

jobs:
unit-tests:
name: Reviewer Bot Unit Tests
runs-on:
group: databricks-protected-runner-group
labels: linux-ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Poetry
uses: ./.github/actions/setup-poetry
with:
python-version: "3.11"
- name: Run reviewer-bot + shared unit tests
run: poetry run python -m pytest scripts/reviewer_bot/tests scripts/shared/tests
39 changes: 39 additions & 0 deletions .github/workflows/sdk-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Reviewer-bot foundation smoke test.
#
# Manual-only (workflow_dispatch). Verifies the one infra unknown for the
# reviewer-bot foundation on this repo: that the Claude Agent SDK (pip) + the
# Claude Code CLI (npm) install on the protected runner via Databricks' internal
# JFrog mirror (the runner group is egress-blocked from pypi.org/npmjs.org).
# No secrets required — only the JFrog OIDC token exchange (id-token: write).
name: SDK Smoke (reviewer-bot foundation)

on:
workflow_dispatch:

permissions:
contents: read
id-token: write # JFrog OIDC token exchange for the internal pip/npm mirror

jobs:
smoke:
runs-on:
group: databricks-protected-runner-group
labels: [linux-ubuntu-latest]
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.11'

- name: Setup Claude Agent SDK + CLI
uses: ./.github/actions/setup-claude-sdk

- name: Verify SDK + CLI are importable/spawnable
run: |
python -c "import claude_agent_sdk; print('claude_agent_sdk import OK')"
echo "claude CLI: $(command -v claude || echo 'NOT FOUND')"
claude --version || true
Empty file added scripts/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions scripts/requirements-sdk.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Claude Agent SDK migration dependencies (PoC).
#
# Replaces the hand-rolled LLM transport + tool-use loop
# (scripts/engineer_bot/agent_runner.py, scripts/shared/llm_client.py)
# with the Claude Agent SDK. See docs/migration/claude-agent-sdk-migration.md.
#
# IMPORTANT: the SDK spawns the Claude Code CLI under the hood. The CLI
# must be on PATH in any environment that calls sdk_agent.run_agent
# (CI runners + local dev). Install it once, globally, via npm:
#
# npm i -g @anthropic-ai/claude-code
#
# The CLI is NOT a pip package; it cannot be pinned here. CI workflows
# (engineer-bot.yml, reviewer-bot.yml, *-followup.yml) must add an install
# + npm-cache step before invoking any bot that uses the SDK.
#
# Endpoint config (set by sdk_agent.configure_databricks_env at runtime,
# derived from the existing MODEL_ENDPOINT / DATABRICKS_TOKEN workflow env):
# ANTHROPIC_BASE_URL = <workspace>/serving-endpoints/anthropic
# ANTHROPIC_AUTH_TOKEN = $DATABRICKS_TOKEN # NOT ANTHROPIC_API_KEY
# ANTHROPIC_MODEL = databricks-claude-opus-4-8

claude-agent-sdk
Empty file.
Loading
Loading