#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" ENV_FILE="${1:-$ROOT_DIR/.env.production}" COMPOSE_FILE="${2:-$ROOT_DIR/infra/docker-compose.prod.yml}" if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then cat <<'USAGE' Usage: scripts/ops/preflight-prod.sh [env-file] [compose-file] Examples: scripts/ops/preflight-prod.sh scripts/ops/preflight-prod.sh .env.production infra/docker-compose.prod.yml Checks: - required host tools exist and docker daemon is reachable - production environment values pass validation - production compose file renders successfully - expected core services are present in compose config USAGE exit 0 fi if [[ ! -f "$ENV_FILE" ]]; then echo "[error] env file not found: $ENV_FILE" >&2 exit 1 fi if [[ ! -f "$COMPOSE_FILE" ]]; then echo "[error] compose file not found: $COMPOSE_FILE" >&2 exit 1 fi require_cmd() { local cmd="$1" if ! command -v "$cmd" >/dev/null 2>&1; then echo "[error] required command not found: $cmd" >&2 exit 1 fi } for cmd in docker node bash; do require_cmd "$cmd" done if ! docker info >/dev/null 2>&1; then echo "[error] docker daemon is not reachable" >&2 exit 1 fi echo "[step] validating production environment values..." node "$ROOT_DIR/scripts/check-production-env.mjs" "$ENV_FILE" echo "[step] validating compose rendering..." if ! docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" config >/dev/null; then echo "[error] docker compose config validation failed" >&2 exit 1 fi mapfile -t configured_services < <(docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" config --services) required_services=(gateway frontend auth api postgres rustfs rustfs-init) for service in "${required_services[@]}"; do found=0 for configured in "${configured_services[@]}"; do if [[ "$configured" == "$service" ]]; then found=1 break fi done if [[ "$found" -ne 1 ]]; then echo "[error] required service missing from compose config: $service" >&2 exit 1 fi done echo "[ok] production preflight checks passed"