Files
xiaoxia-saas/infra/docker/deploy-production.sh
T
Xiaoxia AI 91ec8559b6
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
fix(deploy): require runtime image artifact for production
2026-06-22 14:53:48 +08:00

82 lines
3.2 KiB
Bash
Executable File

#!/bin/sh
set -eu
HOST_PREFIX="${HOST_PREFIX-/host}"
ROOT_DIR="$HOST_PREFIX/var/lib/xiaoxia-saas-production/repo"
COMPOSE_DIR="$ROOT_DIR/infra/docker"
ENV_FILE="$HOST_PREFIX/var/lib/xiaoxia-saas-production/.env"
RELEASE_VERSION="${RELEASE_VERSION:-}"
RUNTIME_IMAGE_TAR="${RUNTIME_IMAGE_TAR:-}"
if [ -n "$RELEASE_VERSION" ] && [ -z "$RUNTIME_IMAGE_TAR" ]; then
RUNTIME_IMAGE_TAR="$HOST_PREFIX/var/lib/xiaoxia-saas-production/runtime-images-$RELEASE_VERSION.tar"
fi
ensure_container_running() {
name="$1"
if ! docker inspect "$name" >/dev/null 2>&1; then
echo "Required infrastructure container not found: $name"
echo "Run infra/docker/infra-production.yml first before deploying production applications."
exit 1
fi
state="$(docker inspect -f '{{.State.Status}}' "$name")"
if [ "$state" != "running" ]; then
echo "Required infrastructure container is not running: $name ($state)"
exit 1
fi
}
if [ ! -d "$ROOT_DIR" ] && [ -n "${PRODUCTION_REPO_FALLBACK:-}" ] && [ -d "$PRODUCTION_REPO_FALLBACK" ]; then
ROOT_DIR="$PRODUCTION_REPO_FALLBACK"
COMPOSE_DIR="$ROOT_DIR/infra/docker"
fi
cd "$ROOT_DIR"
cp "$ENV_FILE" "$ROOT_DIR/.env"
mkdir -p "$ROOT_DIR/apps/web/public" "$HOST_PREFIX/var/lib/xiaoxia-saas-production/generated"
[ -f "$ROOT_DIR/apps/web/public/.keep" ] || printf 'placeholder' > "$ROOT_DIR/apps/web/public/.keep"
if [ ! -f "$ROOT_DIR/apps/web/dist/index.html" ]; then
echo "Missing prebuilt web artifact: $ROOT_DIR/apps/web/dist/index.html"
echo "Production deploy must not build frontend assets on the server. Run npm run build before packaging the release artifact."
exit 1
fi
ensure_container_running xiaoxia-postgres-production
ensure_container_running xiaoxia-redis-production
cd "$COMPOSE_DIR"
if [ -n "$RELEASE_VERSION" ]; then
if [ ! -f "$RUNTIME_IMAGE_TAR" ]; then
echo "Missing production runtime image artifact: $RUNTIME_IMAGE_TAR"
echo "Build it on a dedicated build host with scripts/build_release_images.sh $RELEASE_VERSION, then upload it before production deploy."
exit 1
fi
docker load -i "$RUNTIME_IMAGE_TAR"
export API_IMAGE="xiaoxia-saas-api:$RELEASE_VERSION"
export WORKER_IMAGE="xiaoxia-saas-worker:$RELEASE_VERSION"
fi
export DOCKER_BUILDKIT=0
export COMPOSE_DOCKER_CLI_BUILD=0
export COMPOSE_PROJECT_NAME=xiaoxia-production-app
export WEB_DOCKERFILE=infra/docker/web-artifact.Dockerfile
export WEB_NGINX_CONF=infra/docker/nginx-production.conf
if [ "${ALLOW_PRODUCTION_BUILDS:-false}" = "true" ]; then
docker compose --env-file "$ENV_FILE" build --pull=false api
docker compose --env-file "$ENV_FILE" build --pull=false worker
else
echo "Skipping production API/worker image builds. Set ALLOW_PRODUCTION_BUILDS=true only on a dedicated build host."
docker image inspect "${API_IMAGE:-xiaoxia-saas-api:dev}" >/dev/null
docker image inspect "${WORKER_IMAGE:-xiaoxia-saas-worker:dev}" >/dev/null
fi
docker compose --env-file "$ENV_FILE" build --pull=false web
docker compose --env-file "$ENV_FILE" run --rm --no-deps api sh -c '
cd /app &&
python /app/scripts/validate_release_env.py --from-environ --strict-external &&
alembic upgrade head
'
docker compose --env-file "$ENV_FILE" up -d api worker web
docker compose --env-file "$ENV_FILE" ps