Ajout d'une configuration DevContainer complète avec MCP Servers (LSP multi-langages, GitHub/Gitea), scripts de setup automatisés (crazycoder-setup.sh, setup-devcontainer.sh), et optimisation de l’image Docker (rustup/cargo-binstall, nettoyage des artefacts). Mise à jour du README avec documentation MCP et gestion dynamique des variables d’environnement (.env généré automatiquement selon la forge détectée). Simplification des entrypoints et postStartCommand pour une initialisation plus fiable.
170 lines
6.2 KiB
Bash
Executable File
170 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# setup-devcontainer.sh
|
|
#
|
|
# Adds the PMOCrazyCoder devcontainer environment to any project.
|
|
# Usage: bash setup-devcontainer.sh [project-dir]
|
|
#
|
|
# Example (run from the project root):
|
|
# bash setup-devcontainer.sh
|
|
#
|
|
# Or download and run directly:
|
|
# curl -fsSL https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder/raw/branch/main/setup-devcontainer.sh | bash
|
|
|
|
set -euo pipefail
|
|
|
|
PROJECT_DIR="${1:-$(pwd)}"
|
|
DEVCONTAINER_DIR="$PROJECT_DIR/.devcontainer"
|
|
LOCAL_LLM_API="${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}"
|
|
|
|
GIT_RAW="https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder/raw/branch/main"
|
|
|
|
# --- Colors ---
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RESET='\033[0m'
|
|
info() { echo -e "${GREEN}[setup]${RESET} $*"; }
|
|
warning() { echo -e "${YELLOW}[setup]${RESET} $*"; }
|
|
error() { echo -e "${RED}[setup]${RESET} $*" >&2; exit 1; }
|
|
|
|
fetch() {
|
|
local src="$1" dst="$2"
|
|
curl -fsSL "$GIT_RAW/$src" -o "$dst" \
|
|
|| error "Failed to fetch $src from $GIT_RAW"
|
|
}
|
|
|
|
# --- Checks ---
|
|
[[ -d "$PROJECT_DIR" ]] || error "Directory not found: $PROJECT_DIR"
|
|
command -v curl >/dev/null || error "curl is required"
|
|
|
|
# --- .devcontainer/ ---
|
|
info "Creating .devcontainer structure in $PROJECT_DIR"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/claude"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/opencode"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/aichat"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/ai_index"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/cargo-registry"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/cargo-git"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/cargo-bin"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/go-cache"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/go-bin"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/python-local"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/zed"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/npm-cache"
|
|
mkdir -p "$DEVCONTAINER_DIR/config/r-libs"
|
|
|
|
# --- devcontainer.json ---
|
|
DEVCONTAINER_JSON="$DEVCONTAINER_DIR/devcontainer.json"
|
|
if [[ -f "$DEVCONTAINER_JSON" ]]; then
|
|
warning "devcontainer.json already exists, skipping"
|
|
else
|
|
fetch ".devcontainer/devcontainer.json" "$DEVCONTAINER_JSON"
|
|
PROJECT_NAME="$(basename "$PROJECT_DIR")"
|
|
SERVICE_NAME="crazycoder-${PROJECT_NAME}"
|
|
# Patch display name and service reference
|
|
sed -i.bak \
|
|
-e "s/\"name\": \"PMOCrazyCoder\"/\"name\": \"${PROJECT_NAME}\"/" \
|
|
-e "s/\"service\": \"pmocrazycoder\"/\"service\": \"${SERVICE_NAME}\"/" \
|
|
"$DEVCONTAINER_JSON"
|
|
rm -f "$DEVCONTAINER_JSON.bak"
|
|
info "Created devcontainer.json"
|
|
fi
|
|
|
|
# --- docker-compose.yml ---
|
|
COMPOSE_FILE="$DEVCONTAINER_DIR/docker-compose.yml"
|
|
if [[ -f "$COMPOSE_FILE" ]]; then
|
|
warning "docker-compose.yml already exists, skipping"
|
|
else
|
|
fetch ".devcontainer/docker-compose.yml" "$COMPOSE_FILE"
|
|
PROJECT_NAME="$(basename "$PROJECT_DIR")"
|
|
SERVICE_NAME="crazycoder-${PROJECT_NAME}"
|
|
# Rename the service to avoid collision with project's own Docker services
|
|
sed -i.bak "s/^ pmocrazycoder:/ ${SERVICE_NAME}:/" "$COMPOSE_FILE"
|
|
# Patch LOCAL_LLM_API if overridden
|
|
if [[ "$LOCAL_LLM_API" != "http://host.docker.internal:1248/v1" ]]; then
|
|
sed -i.bak "s|http://host.docker.internal:1248/v1|${LOCAL_LLM_API}|g" "$COMPOSE_FILE"
|
|
fi
|
|
rm -f "$COMPOSE_FILE.bak"
|
|
info "Created docker-compose.yml"
|
|
fi
|
|
|
|
# --- .env ---
|
|
ENV_FILE="$DEVCONTAINER_DIR/.env"
|
|
if [[ -f "$ENV_FILE" ]]; then
|
|
warning ".env already exists, skipping"
|
|
else
|
|
# Détecter la forge depuis l'origin git du projet
|
|
DETECTED_GITEA_URL=""
|
|
IS_GITHUB=false
|
|
|
|
if command -v git >/dev/null && git -C "$PROJECT_DIR" rev-parse --git-dir &>/dev/null; then
|
|
ORIGIN_URL=$(git -C "$PROJECT_DIR" remote get-url origin 2>/dev/null || true)
|
|
if [[ -n "$ORIGIN_URL" ]]; then
|
|
# Extraire scheme + host (supporte https://host/... et git@host:...)
|
|
if [[ "$ORIGIN_URL" =~ ^(https?://[^/]+) ]]; then
|
|
ORIGIN_HOST="${BASH_REMATCH[1]}"
|
|
elif [[ "$ORIGIN_URL" =~ ^git@([^:]+): ]]; then
|
|
ORIGIN_HOST="https://${BASH_REMATCH[1]}"
|
|
fi
|
|
|
|
if [[ "${ORIGIN_HOST:-}" == *"github.com"* ]]; then
|
|
IS_GITHUB=true
|
|
info "Forge détectée : GitHub"
|
|
elif [[ -n "${ORIGIN_HOST:-}" ]]; then
|
|
# Tester si c'est un Gitea/Forgejo via son API
|
|
if curl -fsSL --max-time 5 "${ORIGIN_HOST}/api/v1/version" 2>/dev/null | grep -q '"version"'; then
|
|
DETECTED_GITEA_URL="$ORIGIN_HOST"
|
|
info "Forge détectée : Gitea/Forgejo ($DETECTED_GITEA_URL)"
|
|
else
|
|
warning "Forge non reconnue pour $ORIGIN_HOST (ni GitHub ni Gitea/Forgejo)"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
{
|
|
echo "# Secrets du devcontainer — ne pas committer"
|
|
echo ""
|
|
if $IS_GITHUB; then
|
|
echo "# GitHub"
|
|
echo "GITHUB_TOKEN="
|
|
else
|
|
echo "# GitHub (non détecté pour ce projet)"
|
|
echo "# GITHUB_TOKEN="
|
|
fi
|
|
echo ""
|
|
if [[ -n "$DETECTED_GITEA_URL" ]]; then
|
|
echo "# Gitea"
|
|
echo "GITEA_URL=${DETECTED_GITEA_URL}"
|
|
echo "GITEA_TOKEN="
|
|
else
|
|
echo "# Gitea (non détecté pour ce projet)"
|
|
echo "# GITEA_URL="
|
|
echo "# GITEA_TOKEN="
|
|
fi
|
|
} > "$ENV_FILE"
|
|
|
|
info "Created .env"
|
|
fi
|
|
|
|
# --- .gitignore ---
|
|
GITIGNORE="$PROJECT_DIR/.gitignore"
|
|
if [[ -f "$GITIGNORE" ]]; then
|
|
if grep -q "\.devcontainer/config/" "$GITIGNORE"; then
|
|
warning ".gitignore already contains .devcontainer/config/, skipping"
|
|
else
|
|
printf '\n# PMOCrazyCoder devcontainer runtime config\n.devcontainer/config/\n.devcontainer/.env\n' >> "$GITIGNORE"
|
|
info "Updated .gitignore"
|
|
fi
|
|
else
|
|
printf '# PMOCrazyCoder devcontainer runtime config\n.devcontainer/config/\n.devcontainer/.env\n' > "$GITIGNORE"
|
|
info "Created .gitignore"
|
|
fi
|
|
|
|
echo
|
|
info "Done. Next steps:"
|
|
echo " 1. Renseigner les tokens dans .devcontainer/.env"
|
|
echo " 2. Open the project in VS Code / Zed / Cursor"
|
|
echo " 3. Reopen in container (the image will be pulled from the registry)"
|
|
echo " 4. Run /login in the Claude Agent panel to authenticate"
|
|
echo
|
|
info "To use a different local LLM API endpoint:"
|
|
echo " LOCAL_LLM_API=http://myserver:1248/v1 bash setup-devcontainer.sh"
|