#!/usr/bin/env bash # [DEF:build:Module] # @PURPOSE: Utility script for build # @COMPLEXITY: 1 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" BACKEND_ENV_FILE="$SCRIPT_DIR/backend/.env" PROFILE="${1:-current}" case "$PROFILE" in master) PROFILE_ENV_FILE="$SCRIPT_DIR/.env.master" PROJECT_NAME="ss-tools-master" ;; current) PROFILE_ENV_FILE="$SCRIPT_DIR/.env.current" PROJECT_NAME="ss-tools-current" ;; *) echo "Error: unknown profile '$PROFILE'. Use one of: master, current." exit 1 ;; esac if ! command -v docker >/dev/null 2>&1; then echo "Error: docker is not installed or not in PATH." exit 1 fi if docker compose version >/dev/null 2>&1; then COMPOSE_CMD=(docker compose) elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD=(docker-compose) else echo "Error: docker compose is not available." exit 1 fi ensure_backend_encryption_key() { if command -v python3 >/dev/null 2>&1; then python3 - "$BACKEND_ENV_FILE" <<'PY' import base64 import os import sys from pathlib import Path from typing import List, Optional def is_valid_fernet_key(raw_value: str) -> bool: value = raw_value.strip() if not value: return False try: decoded = base64.urlsafe_b64decode(value.encode()) except Exception: return False return len(decoded) == 32 def generate_fernet_key() -> str: return base64.urlsafe_b64encode(os.urandom(32)).decode() env_path = Path(sys.argv[1]) env_path.parent.mkdir(parents=True, exist_ok=True) existing_lines: List[str] = [] existing_key: Optional[str] = None if env_path.exists(): existing_lines = env_path.read_text(encoding="utf-8").splitlines() for line in existing_lines: if line.startswith("ENCRYPTION_KEY="): candidate = line.partition("=")[2].strip() if is_valid_fernet_key(candidate): existing_key = candidate break if existing_key is None: generated_key = generate_fernet_key() filtered_lines = [line for line in existing_lines if not line.startswith("ENCRYPTION_KEY=")] filtered_lines.append(f"ENCRYPTION_KEY={generated_key}") env_path.write_text("\n".join(filtered_lines) + "\n", encoding="utf-8") print(f"[build] ENCRYPTION_KEY ensured in {env_path}") else: print(f"[build] Existing ENCRYPTION_KEY reused from {env_path}") PY return fi echo "Error: python3 is required to generate backend/.env with ENCRYPTION_KEY." exit 1 } ensure_backend_encryption_key COMPOSE_ARGS=(-p "$PROJECT_NAME") if [[ -f "$PROFILE_ENV_FILE" ]]; then COMPOSE_ARGS+=(--env-file "$PROFILE_ENV_FILE") else echo "[build] Warning: profile env file not found at $PROFILE_ENV_FILE, using compose defaults." fi echo "[build] Profile: $PROFILE (project: $PROJECT_NAME)" if [[ -f "$PROFILE_ENV_FILE" ]]; then echo "[build] Env file: $PROFILE_ENV_FILE" fi echo "[1/2] Building project images..." "${COMPOSE_CMD[@]}" "${COMPOSE_ARGS[@]}" build echo "[2/2] Starting Docker services..." "${COMPOSE_CMD[@]}" "${COMPOSE_ARGS[@]}" up -d echo "Done. Services are running." echo "Use '${COMPOSE_CMD[*]} ${COMPOSE_ARGS[*]} ps' to check status and '${COMPOSE_CMD[*]} ${COMPOSE_ARGS[*]} logs -f' to stream logs." # [/DEF:build:Module]