setup.shā¢16.4 kB
#!/bin/bash
set -e
# Check for --auto-close flag and temp file
AUTO_CLOSE=false
TEMP_FILE=""
if [ "$1" = "--auto-close" ]; then
AUTO_CLOSE=true
TEMP_FILE="$2"
fi
# Function to signal completion on exit
cleanup() {
if [ "$AUTO_CLOSE" = true ] && [ -n "$TEMP_FILE" ]; then
echo "setup_complete" > "$TEMP_FILE"
fi
}
# Set trap to call cleanup on exit
if [ "$AUTO_CLOSE" = true ]; then
trap cleanup EXIT
fi
echo "š Databricks App Template Setup"
echo "================================="
# Function to prompt for input with default value
prompt_with_default() {
local prompt="$1"
local default="$2"
local var_name="$3"
local note="${4:-}" # Optional note parameter
if [ -n "$note" ]; then
echo " $note"
fi
read -p "$prompt [$default]: " input
if [ -z "$input" ]; then
input="$default"
fi
# Set the variable dynamically
eval "$var_name='$input'"
}
# Function to update or add a value in .env.local
update_env_value() {
local key="$1"
local value="$2"
local comment="$3"
if grep -q "^${key}=" .env.local 2>/dev/null; then
# Update existing value
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS sed
sed -i '' "s|^${key}=.*|${key}=${value}|" .env.local
else
# Linux sed
sed -i "s|^${key}=.*|${key}=${value}|" .env.local
fi
else
# Add new value with comment if provided
if [ -n "$comment" ]; then
echo "" >> .env.local
echo "# $comment" >> .env.local
fi
echo "${key}=${value}" >> .env.local
fi
}
# Function to test databricks connection
test_databricks_connection() {
local profile="$1"
echo "š Testing Databricks connection..."
# Ensure environment variables are exported for databricks CLI
if [ -n "$DATABRICKS_HOST" ] && [ -n "$DATABRICKS_TOKEN" ]; then
export DATABRICKS_HOST
export DATABRICKS_TOKEN
fi
if [ -n "$profile" ]; then
if databricks current-user me --profile "$profile" >/dev/null 2>&1; then
echo "ā
Successfully connected to Databricks with profile '$profile'"
return 0
else
echo "ā Failed to connect to Databricks with profile '$profile'"
return 1
fi
else
if databricks current-user me >/dev/null 2>&1; then
echo "ā
Successfully connected to Databricks"
return 0
else
echo "ā Failed to connect to Databricks"
return 1
fi
fi
}
# Check if .env.local already exists
if [ -f ".env.local" ]; then
echo "š Found existing .env.local file."
read -p "Do you want to update it? (y/N): " update_env
if [[ ! "$update_env" =~ ^[Yy]$ ]]; then
echo "Skipping environment configuration."
skip_env=true
fi
fi
if [ "$skip_env" != "true" ]; then
echo "āļø Setting up environment variables..."
# Load existing values if they exist
if [ -f ".env.local" ]; then
source .env.local 2>/dev/null || true
fi
# Initialize .env.local file if it doesn't exist
if [ ! -f ".env.local" ]; then
echo "# Databricks App Configuration" > .env.local
echo "# Generated by setup script on $(date)" >> .env.local
echo "" >> .env.local
fi
# Databricks Authentication Configuration
echo ""
echo "š Databricks Authentication"
echo "-----------------------------"
echo "Choose authentication method:"
echo "1. Personal Access Token (PAT)"
echo "2. Configuration Profile"
echo ""
# Pre-select based on existing configuration
if [ "$DATABRICKS_AUTH_TYPE" = "pat" ]; then
default_choice="1"
elif [ "$DATABRICKS_AUTH_TYPE" = "profile" ]; then
default_choice="2"
else
default_choice=""
fi
if [ -n "$default_choice" ]; then
prompt_with_default "Select option" "$default_choice" "auth_choice"
else
read -p "Select option (1 or 2): " auth_choice
fi
if [ "$auth_choice" = "1" ]; then
# PAT Authentication
echo ""
echo "š Personal Access Token Setup"
echo "-------------------------------"
# Update auth type in .env.local
update_env_value "DATABRICKS_AUTH_TYPE" "pat" "Databricks Authentication Type"
# Try to auto-detect workspace from current authentication
DETECTED_HOST=""
if databricks current-user me --output json >/dev/null 2>&1; then
DETECTED_HOST=$(databricks current-user me --output json 2>/dev/null | grep -o '"workspaceUrl":"https://[^"]*"' | cut -d'"' -f4)
if [ -z "$DETECTED_HOST" ]; then
# Try alternative method using workspace command
DETECTED_HOST=$(databricks workspace current --output json 2>/dev/null | grep -o '"host":"https://[^"]*"' | cut -d'"' -f4)
fi
fi
# Use detected host as default, or fall back to existing/placeholder
if [ -n "$DETECTED_HOST" ]; then
DEFAULT_HOST="$DETECTED_HOST"
echo "ā
Auto-detected workspace: $DETECTED_HOST"
# Warn if detected workspace differs from stored
if [ -n "$DATABRICKS_HOST" ] && [ "$DATABRICKS_HOST" != "$DETECTED_HOST" ]; then
echo ""
echo "ā ļø Warning: Detected workspace differs from stored configuration"
echo " Stored: $DATABRICKS_HOST"
echo " Detected: $DETECTED_HOST"
echo ""
fi
elif [ -n "$DATABRICKS_HOST" ]; then
DEFAULT_HOST="$DATABRICKS_HOST"
else
DEFAULT_HOST="https://your-workspace.cloud.databricks.com"
fi
prompt_with_default "Databricks Host" "$DEFAULT_HOST" "DATABRICKS_HOST"
# Update host in .env.local
update_env_value "DATABRICKS_HOST" "$DATABRICKS_HOST" "Databricks Configuration (PAT mode)"
if [ -n "$DATABRICKS_TOKEN" ]; then
echo "Found existing token: ${DATABRICKS_TOKEN:0:10}... (truncated)"
read -p "Use existing token? (y/N): " use_existing
if [[ ! "$use_existing" =~ ^[Yy]$ ]]; then
DATABRICKS_TOKEN=""
fi
fi
if [ -z "$DATABRICKS_TOKEN" ]; then
echo ""
echo "You can create a Personal Access Token here:"
echo "š $DATABRICKS_HOST/settings/user/developer/access-tokens"
echo ""
read -s -p "Databricks Personal Access Token: " DATABRICKS_TOKEN
echo ""
fi
# Update token in .env.local
update_env_value "DATABRICKS_TOKEN" "$DATABRICKS_TOKEN"
# Set empty profile to indicate PAT mode
DATABRICKS_CONFIG_PROFILE=""
DATABRICKS_AUTH_TYPE="pat"
# Test PAT authentication
echo "š Testing PAT authentication..."
export DATABRICKS_HOST="$DATABRICKS_HOST"
export DATABRICKS_TOKEN="$DATABRICKS_TOKEN"
echo "Attempting to connect with:"
echo "Host: $DATABRICKS_HOST"
echo "Token: ${DATABRICKS_TOKEN:0:10}... (truncated)"
echo ""
# Test connection and show output for debugging
echo "Running: databricks current-user me"
# Export for databricks CLI
export DATABRICKS_HOST="$DATABRICKS_HOST"
export DATABRICKS_TOKEN="$DATABRICKS_TOKEN"
if databricks current-user me >/dev/null 2>&1; then
echo "ā
Successfully connected to Databricks with PAT"
else
echo ""
echo "ā PAT authentication failed."
echo "Please check your host URL and token are correct."
echo "You can test manually with:"
echo "DATABRICKS_HOST='$DATABRICKS_HOST' DATABRICKS_TOKEN='$DATABRICKS_TOKEN' databricks current-user me"
exit 1
fi
elif [ "$auth_choice" = "2" ]; then
# Profile Authentication
echo ""
echo "š Configuration Profile Setup"
echo "-------------------------------"
# Update auth type in .env.local
update_env_value "DATABRICKS_AUTH_TYPE" "profile" "Databricks Authentication Type"
# List existing profiles
echo "Available profiles:"
if [ -f "$HOME/.databrickscfg" ]; then
grep '^\[' "$HOME/.databrickscfg" | sed 's/\[//g' | sed 's/\]//g' | sed 's/^/ - /'
else
echo " No existing profiles found"
fi
echo ""
prompt_with_default "Databricks Config Profile" "${DATABRICKS_CONFIG_PROFILE:-DEFAULT}" "DATABRICKS_CONFIG_PROFILE"
# Update profile in .env.local
update_env_value "DATABRICKS_CONFIG_PROFILE" "$DATABRICKS_CONFIG_PROFILE" "Databricks Configuration (Profile mode)"
# Clear PAT credentials when using profile
update_env_value "DATABRICKS_HOST" ""
update_env_value "DATABRICKS_TOKEN" ""
DATABRICKS_HOST=""
DATABRICKS_TOKEN=""
DATABRICKS_AUTH_TYPE="profile"
# Test profile authentication
if ! test_databricks_connection "$DATABRICKS_CONFIG_PROFILE"; then
echo ""
echo "Profile '$DATABRICKS_CONFIG_PROFILE' not found or invalid."
echo "Would you like to configure it now? (y/N)"
read -p "> " configure_profile
if [[ "$configure_profile" =~ ^[Yy]$ ]]; then
echo "Running 'databricks configure --profile $DATABRICKS_CONFIG_PROFILE'..."
databricks configure --profile "$DATABRICKS_CONFIG_PROFILE"
# Test again after configuration
if ! test_databricks_connection "$DATABRICKS_CONFIG_PROFILE"; then
echo "ā Profile configuration failed. Please check your settings."
exit 1
fi
else
echo "ā Valid Databricks authentication is required for deployment."
exit 1
fi
fi
else
echo "ā Invalid option. Please run setup again."
exit 1
fi
# Get current user information (only if we don't have existing DBA_SOURCE_CODE_PATH)
if [ -z "$DBA_SOURCE_CODE_PATH" ]; then
echo ""
echo "š Getting user information..."
if [ "$DATABRICKS_AUTH_TYPE" = "profile" ]; then
DATABRICKS_USER=$(databricks current-user me --profile "$DATABRICKS_CONFIG_PROFILE" --output json 2>/dev/null | grep -o '"userName":"[^"]*"' | cut -d'"' -f4)
else
DATABRICKS_USER=$(databricks current-user me --output json 2>/dev/null | grep -o '"userName":"[^"]*"' | cut -d'"' -f4)
fi
if [ -n "$DATABRICKS_USER" ]; then
echo "ā
Detected user: $DATABRICKS_USER"
else
echo "ā ļø Could not detect user, will use default email"
fi
else
echo ""
echo "ā
Using existing configuration from .env.local"
fi
# App Configuration
echo ""
echo "š App Configuration"
echo "--------------------"
if [ "$DATABRICKS_AUTH_TYPE" = "profile" ]; then
WORKSPACE_HOST=$(databricks current-user me --profile "$DATABRICKS_CONFIG_PROFILE" --output json 2>/dev/null | grep -o '"workspaceUrl":"[^"]*"' | cut -d'"' -f4)
else
WORKSPACE_HOST="$DATABRICKS_HOST"
fi
if [ -n "$WORKSPACE_HOST" ]; then
echo "š $WORKSPACE_HOST/apps/create"
else
echo "š https://your-workspace.cloud.databricks.com/apps/create"
fi
echo ""
echo "š App Naming Requirements:"
echo " - Must start with 'mcp-'"
echo " - Use lowercase letters, numbers, and hyphens only"
echo " - Examples: mcp-api-registry, mcp-prod-registry, mcp-dev-1"
echo ""
# Loop until valid app name is provided
while true; do
prompt_with_default "App Name for Deployment" "${DATABRICKS_APP_NAME:-mcp-api-registry}" "DATABRICKS_APP_NAME"
# Validate app name starts with 'mcp-'
if [[ "$DATABRICKS_APP_NAME" =~ ^mcp- ]]; then
echo "ā
App name validated: $DATABRICKS_APP_NAME"
break
else
echo "ā Error: App name must start with 'mcp-'"
echo " You entered: $DATABRICKS_APP_NAME"
echo " Please try again with a valid name (e.g., mcp-${DATABRICKS_APP_NAME})"
echo ""
# Clear the invalid value
DATABRICKS_APP_NAME=""
fi
done
# Update the default source path to use the chosen app name
if [ -z "$DBA_SOURCE_CODE_PATH" ]; then
if [ -n "$DATABRICKS_USER" ]; then
DEFAULT_SOURCE_PATH="/Workspace/Users/$DATABRICKS_USER/$DATABRICKS_APP_NAME"
else
DEFAULT_SOURCE_PATH="/Workspace/Users/<your-email@company.com>/$DATABRICKS_APP_NAME"
fi
else
DEFAULT_SOURCE_PATH="$DBA_SOURCE_CODE_PATH"
fi
prompt_with_default "Source Code Path for Deployment" "$DEFAULT_SOURCE_PATH" "DBA_SOURCE_CODE_PATH"
# Update app configuration in .env.local
update_env_value "DATABRICKS_APP_NAME" "$DATABRICKS_APP_NAME" "Databricks App Configuration"
update_env_value "DBA_SOURCE_CODE_PATH" "$DBA_SOURCE_CODE_PATH"
# MCP Server Configuration
echo ""
echo "š§ MCP Server Configuration"
echo "---------------------------"
# Default server name to app name (makes sense to keep them aligned)
DEFAULT_SERVERNAME="$DATABRICKS_APP_NAME"
# Load current servername from config.yaml if it exists
CURRENT_SERVERNAME=""
if [ -f "config.yaml" ]; then
CURRENT_SERVERNAME=$(grep "servername:" config.yaml 2>/dev/null | cut -d':' -f2 | sed 's/^ *//' | sed 's/ *$//')
fi
# Use current servername if exists, otherwise use app name as default
if [ -z "$CURRENT_SERVERNAME" ]; then
CURRENT_SERVERNAME="$DEFAULT_SERVERNAME"
fi
prompt_with_default "MCP Server Name" "$CURRENT_SERVERNAME" "SERVERNAME" "š” Press Enter to use default (same as app name)"
# Create or update config.yaml
echo "# MCP Server Configuration" > config.yaml
echo "servername: $SERVERNAME" >> config.yaml
echo "ā
MCP server configuration saved to config.yaml"
echo ""
echo "ā
Environment configuration saved to .env.local"
fi
# Check for required tools
echo ""
echo "š§ Checking dependencies..."
# Check for databricks CLI
if ! command -v databricks &> /dev/null; then
echo "ā Databricks CLI not found. Please install it first:"
echo " Visit: https://docs.databricks.com/dev-tools/cli/install.html"
echo " Or run: pip install databricks-cli"
exit 1
fi
# Check for uv
if ! command -v uv &> /dev/null; then
echo "ā uv not found. Installing uv..."
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env
fi
# Check for bun
if ! command -v bun &> /dev/null; then
echo "ā bun not found. Installing bun..."
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
fi
echo "ā
All required tools are available"
# Install Python dependencies
echo "š¦ Installing Python dependencies..."
uv sync --dev
# Install frontend dependencies
echo "š¦ Installing frontend dependencies..."
cd client
bun install
cd ..
echo ""
echo "š Setup complete!"
echo ""
echo "Next steps:"
echo "1. Run './watch.sh' to start the development servers"
echo "2. Open http://localhost:3000 to view the app"
echo "3. Open http://localhost:8000/docs to view the API documentation"
echo ""
echo "Optional:"
echo "- Run './fix.sh' to format your code"
echo "- Edit .env.local to update configuration"
# Auto-close terminal if flag is set
if [ "$AUTO_CLOSE" = true ]; then
echo ""
echo "Press Enter to close this terminal..."
read
# Close appropriate terminal app
if [ -d "/Applications/iTerm.app" ]; then
# For iTerm, close the current window
osascript -e 'tell application "iTerm" to close current window'
else
# For Terminal, close windows containing setup.sh
osascript -e 'tell application "Terminal" to close (every window whose name contains "setup.sh")'
fi
fi