maestro/scripts/setup.sh
2026-06-03 04:30:10 +00:00

276 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# MAESTRO 初回セットアップスクリプト
#
# 新しい環境でゼロから動かすための対話式セットアップ。
# クローン済みのディレクトリで実行する:
#
# git clone https://gitea.example.com/your-org/maestro.git maestro
# cd maestro
# ./scripts/setup.sh
#
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_DIR"
echo "=========================================="
echo " MAESTRO セットアップ"
echo "=========================================="
echo ""
# -------------------------------------------------------
# Step 1: 依存関係チェック
# -------------------------------------------------------
echo "[1/5] 前提条件チェック..."
MISSING=()
command -v node >/dev/null 2>&1 || MISSING+=("node")
command -v npm >/dev/null 2>&1 || MISSING+=("npm")
command -v curl >/dev/null 2>&1 || MISSING+=("curl")
if [ ${#MISSING[@]} -gt 0 ]; then
echo " ERROR: 以下がインストールされていません: ${MISSING[*]}"
exit 1
fi
NODE_VER=$(node -v | sed 's/v//' | cut -d. -f1)
if [ "$NODE_VER" -lt 20 ]; then
echo " ERROR: Node.js 20+ が必要です(現在: $(node -v)"
exit 1
fi
echo " Node.js $(node -v) ... OK"
echo ""
# -------------------------------------------------------
# Step 2: npm install & build
# -------------------------------------------------------
echo "[2/5] 依存パッケージのインストール & ビルド..."
./scripts/build-all.sh | tail -5
echo " ビルド完了"
echo ""
# Playwright ブラウザのインストールWebSearch に必要)
echo " Playwright ブラウザをインストール中..."
if npx playwright install chromium 2>/dev/null; then
echo " Playwright chromium インストール完了"
else
echo " WARN: Playwright のインストールに失敗しました。WebSearch は SearXNG フォールバックで動作します。"
echo " 後から 'npx playwright install chromium' で手動インストールできます。"
fi
echo ""
# -------------------------------------------------------
# Step 3: config.yaml 生成
# -------------------------------------------------------
echo "[3/5] 設定ファイル (config.yaml) の作成..."
DEFAULT_OLLAMA_URL="http://localhost:11434/v1"
DEFAULT_MODEL_NAME="qwen3:8b"
DEFAULT_ALLOWED_USER="*"
DEFAULT_MODE="local"
if [ -f "config.yaml" ]; then
EXISTING_MODE=$(grep -E '^\s*integration_mode:' config.yaml | head -1 | sed 's/.*integration_mode:\s*//' | tr -d '"' | tr -d "'" || true)
EXISTING_OLLAMA_URL=$(grep -E '^\s*base_url:' config.yaml | head -1 | sed 's/.*base_url:\s*//' | tr -d '"' | tr -d "'" || true)
EXISTING_MODEL_NAME=$(grep -E '^\s*model:' config.yaml | head -1 | sed 's/.*model:\s*//' | tr -d '"' | tr -d "'" || true)
EXISTING_ALLOWED_USER=$(grep -E '^\s*allowed_users:' config.yaml | head -1 | sed 's/.*\["\?//' | sed 's/"\?\].*//' || true)
[ -n "${EXISTING_MODE}" ] && DEFAULT_MODE="${EXISTING_MODE}"
[ -n "${EXISTING_OLLAMA_URL}" ] && DEFAULT_OLLAMA_URL="${EXISTING_OLLAMA_URL}"
[ -n "${EXISTING_MODEL_NAME}" ] && DEFAULT_MODEL_NAME="${EXISTING_MODEL_NAME}"
[ -n "${EXISTING_ALLOWED_USER}" ] && DEFAULT_ALLOWED_USER="${EXISTING_ALLOWED_USER}"
fi
echo ""
read -rp " 起動モード (local / hybrid / gitea) [${DEFAULT_MODE}]: " INTEGRATION_MODE
read -rp " Ollama の URL (例: http://gpu-server:11434/v1) [${DEFAULT_OLLAMA_URL}]: " OLLAMA_URL
read -rp " 使用する LLM モデル名 (例: qwen3:8b) [${DEFAULT_MODEL_NAME}]: " MODEL_NAME
read -rp " Local/Gitea で受け付けるユーザー名 [${DEFAULT_ALLOWED_USER}]: " ALLOWED_USER
INTEGRATION_MODE="${INTEGRATION_MODE:-$DEFAULT_MODE}"
OLLAMA_URL="${OLLAMA_URL:-$DEFAULT_OLLAMA_URL}"
MODEL_NAME="${MODEL_NAME:-$DEFAULT_MODEL_NAME}"
ALLOWED_USER="${ALLOWED_USER:-$DEFAULT_ALLOWED_USER}"
GITEA_URL=""
if [ "$INTEGRATION_MODE" = "hybrid" ] || [ "$INTEGRATION_MODE" = "gitea" ]; then
EXISTING_GITEA_URL=$(grep -E '^\s*url:' config.yaml 2>/dev/null | head -1 | sed 's/.*url:\s*//' | tr -d '"' | tr -d "'" || true)
DEFAULT_GITEA_URL="${EXISTING_GITEA_URL:-https://your-gitea.example.com}"
read -rp " Gitea の URL (例: https://gitea.example.com) [${DEFAULT_GITEA_URL}]: " GITEA_URL
GITEA_URL="${GITEA_URL:-$DEFAULT_GITEA_URL}"
fi
if [ -f "config.yaml" ]; then
cp config.yaml config.yaml.bak
echo " 既存の config.yaml を config.yaml.bak にバックアップしました"
fi
if [ ! -f "config.yaml.example" ]; then
echo " ERROR: config.yaml.example が見つかりません"
exit 1
fi
cp config.yaml.example config.yaml
sed -i "s|^\(\s*integration_mode:\s*\).*|\1${INTEGRATION_MODE}|" config.yaml
sed -i "s|^\(\s*model:\s*\).*|\1${MODEL_NAME}|" config.yaml
sed -i "s|^\(\s*base_url:\s*\).*|\1${OLLAMA_URL}|" config.yaml
sed -i "s|^\(allowed_users:\s*\).*|\1[\"${ALLOWED_USER}\"]|" config.yaml
if [ -n "${GITEA_URL}" ]; then
python3 - <<PY
from pathlib import Path
path = Path("config.yaml")
text = path.read_text()
needle = "# gitea:\n# url: https://your-gitea.example.com\n# token_env: GITEA_API_TOKEN\n# webhook_secret_env: GITEA_WEBHOOK_SECRET\n"
replacement = "gitea:\n url: ${GITEA_URL}\n token_env: GITEA_API_TOKEN\n webhook_secret_env: GITEA_WEBHOOK_SECRET\n"
path.write_text(text.replace(needle, replacement))
PY
fi
echo " config.yaml を生成/更新しました"
echo ""
echo " DB / workspace ディレクトリを準備しています..."
DB_PATH=$(grep -E '^\s*db_path:' config.yaml | head -1 | sed 's/.*db_path:\s*//' | tr -d '"' | tr -d "'" || true)
WORKTREE_DIR=$(grep -E '^\s*worktree_dir:' config.yaml | head -1 | sed 's/.*worktree_dir:\s*//' | tr -d '"' | tr -d "'" || true)
if [ -n "${DB_PATH}" ]; then
DB_DIR=$(dirname "${DB_PATH}")
mkdir -p "${DB_DIR}"
echo " DB directory: ${DB_DIR}"
else
echo " db_path は未設定(既定の data/maestro.db が使われます)"
mkdir -p data
echo " fallback DB directory: $(pwd)/data"
fi
if [ -n "${WORKTREE_DIR}" ]; then
mkdir -p "${WORKTREE_DIR}"
echo " worktree_dir: ${WORKTREE_DIR}"
fi
echo ""
# -------------------------------------------------------
# Step 4: 環境変数の確認
# -------------------------------------------------------
echo "[4/5] 環境変数の確認..."
if [ "$INTEGRATION_MODE" = "hybrid" ] || [ "$INTEGRATION_MODE" = "gitea" ]; then
if [ -z "${GITEA_API_TOKEN:-}" ]; then
echo ""
echo " GITEA_API_TOKEN が未設定です。"
echo " Gitea の設定 → アプリケーション → トークン生成 で作成してください。"
read -rp " Gitea API トークンを入力: " GITEA_API_TOKEN
export GITEA_API_TOKEN
fi
if [ -z "${GITEA_WEBHOOK_SECRET:-}" ]; then
# ランダム生成
GITEA_WEBHOOK_SECRET=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 32)
export GITEA_WEBHOOK_SECRET
echo " Webhook シークレットを自動生成しました: ${GITEA_WEBHOOK_SECRET}"
fi
echo ""
echo " 以下を .env やシェルの起動スクリプトに保存してください:"
echo ""
echo " export GITEA_API_TOKEN=\"${GITEA_API_TOKEN}\""
echo " export GITEA_WEBHOOK_SECRET=\"${GITEA_WEBHOOK_SECRET}\""
echo ""
else
echo " local モードのため Gitea 用環境変数は不要です。"
echo ""
fi
# -------------------------------------------------------
# Step 5: Webhook 登録
# -------------------------------------------------------
echo "[5/5] Webhook の登録..."
echo ""
if [ "$INTEGRATION_MODE" = "local" ]; then
echo " local モードのため Webhook 登録はスキップします。"
TARGET_REPO=""
else
read -rp " 監視するリポジトリ (例: myorg/myrepo、スキップは空Enter): " TARGET_REPO
fi
if [ -n "$TARGET_REPO" ]; then
read -rp " Orchestrator の外部URL (例: http://10.0.0.10:9876): " ORCH_URL
ORCH_URL="${ORCH_URL:-http://localhost:9876}"
# UI の repo プルダウンに出すため ui_repos へ登録
if grep -q '^ui_repos:' config.yaml; then
if grep -q "- ${TARGET_REPO}" config.yaml; then
echo " ui_repos に ${TARGET_REPO} は既に登録済みです"
else
echo " NOTE: ui_repos セクションは既存のため自動追記はスキップしました。"
echo " config.yaml の ui_repos に '${TARGET_REPO}' を追加してください。"
fi
else
cat >> config.yaml <<YAML
ui_repos:
- ${TARGET_REPO}
YAML
echo " ui_repos に ${TARGET_REPO} を追加しました"
fi
GITEA_URL=$(grep -E '^\s*url:' config.yaml | head -1 | sed 's/.*url:\s*//' | tr -d '"' | tr -d "'")
WEBHOOK_URL="${ORCH_URL}/webhook"
echo ""
echo " Webhook を登録中..."
echo " Gitea: ${GITEA_URL}"
echo " Repository: ${TARGET_REPO}"
echo " Webhook URL: ${WEBHOOK_URL}"
RESPONSE=$(curl -sf -X POST \
-H "Authorization: token ${GITEA_API_TOKEN}" \
-H "Content-Type: application/json" \
"${GITEA_URL}/api/v1/repos/${TARGET_REPO}/hooks" \
-d "{
\"type\": \"gitea\",
\"active\": true,
\"events\": [\"issues\", \"issue_comment\"],
\"config\": {
\"url\": \"${WEBHOOK_URL}\",
\"content_type\": \"json\",
\"secret\": \"${GITEA_WEBHOOK_SECRET}\"
}
}" 2>&1) || true
if echo "$RESPONSE" | python3 -c "import sys,json; print(' Webhook ID:', json.load(sys.stdin)['id'])" 2>/dev/null; then
echo " 登録完了"
else
echo " WARN: Webhook の登録に失敗しました。手動で設定してください。"
echo " エラー: ${RESPONSE}"
fi
else
echo " スキップ。後から ./scripts/setup-repo.sh で追加できます。"
fi
echo ""
echo "=========================================="
echo " セットアップ完了!"
echo "=========================================="
echo ""
echo "起動コマンド:"
echo ""
if [ "$INTEGRATION_MODE" = "hybrid" ] || [ "$INTEGRATION_MODE" = "gitea" ]; then
echo " export GITEA_API_TOKEN=\"${GITEA_API_TOKEN}\""
echo " export GITEA_WEBHOOK_SECRET=\"${GITEA_WEBHOOK_SECRET}\""
fi
echo " npm start"
echo ""
echo "管理ダッシュボード: http://localhost:9876/ui/"
echo ""
if [ "$INTEGRATION_MODE" != "local" ]; then
echo "追加リポジトリの監視:"
echo " ./scripts/setup-repo.sh owner/repo http://this-machine:9876"
fi
echo ""