fix(deploy): require prebuilt web artifact for production
This commit is contained in:
@@ -49,7 +49,7 @@ services:
|
||||
image: ${WEB_IMAGE:-xiaoxia-saas-web:dev}
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: infra/docker/web.Dockerfile
|
||||
dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile}
|
||||
container_name: xiaoxia-web-${ENV:-staging}
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
||||
@@ -30,6 +30,11 @@ 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
|
||||
@@ -38,6 +43,7 @@ cd "$COMPOSE_DIR"
|
||||
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
|
||||
|
||||
docker compose --env-file "$ENV_FILE" build --pull=false api
|
||||
docker compose --env-file "$ENV_FILE" build --pull=false worker
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
FROM docker.m.daocloud.io/library/nginx:alpine AS runner
|
||||
WORKDIR /usr/share/nginx/html
|
||||
COPY apps/web/dist ./
|
||||
COPY infra/docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
ROOT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
||||
OUTPUT_PATH="${1:-$ROOT_DIR/release-artifact.tar}"
|
||||
|
||||
cd "$ROOT_DIR/apps/web"
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
tar --exclude=.git --exclude=apps/web/node_modules -cf "$OUTPUT_PATH" .
|
||||
|
||||
echo "Release artifact written to $OUTPUT_PATH"
|
||||
@@ -23,6 +23,9 @@ def test_deploy_production_uses_production_infra_and_project():
|
||||
script = Path("infra/docker/deploy-production.sh").read_text(encoding="utf-8")
|
||||
|
||||
assert 'HOST_PREFIX="${HOST_PREFIX-/host}"' in script
|
||||
assert "apps/web/dist/index.html" in script
|
||||
assert "Production deploy must not build frontend assets on the server" in script
|
||||
assert "WEB_DOCKERFILE=infra/docker/web-artifact.Dockerfile" in script
|
||||
assert "xiaoxia-postgres-production" in script
|
||||
assert "xiaoxia-redis-production" in script
|
||||
assert "xiaoxia-postgres\n" not in script
|
||||
@@ -71,9 +74,27 @@ def test_staging_deploy_supports_host_prefix_and_web_build():
|
||||
def test_deploy_scripts_build_web_image_explicitly():
|
||||
staging_script = Path("infra/docker/deploy-staging.sh").read_text(encoding="utf-8")
|
||||
production_script = Path("infra/docker/deploy-production.sh").read_text(encoding="utf-8")
|
||||
compose = Path("infra/docker/compose.yml").read_text(encoding="utf-8")
|
||||
|
||||
assert "docker compose build --pull=false web" in staging_script
|
||||
assert "docker compose --env-file \"$ENV_FILE\" build --pull=false web" in production_script
|
||||
assert "dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile}" in compose
|
||||
|
||||
|
||||
def test_web_artifact_dockerfile_does_not_build_frontend_on_server():
|
||||
dockerfile = Path("infra/docker/web-artifact.Dockerfile").read_text(encoding="utf-8")
|
||||
|
||||
assert "COPY apps/web/dist ./" in dockerfile
|
||||
assert "npm" not in dockerfile
|
||||
assert "node" not in dockerfile.lower()
|
||||
|
||||
|
||||
def test_release_artifact_script_builds_web_before_packaging():
|
||||
script = Path("scripts/package_release_artifact.sh").read_text(encoding="utf-8")
|
||||
|
||||
assert "npm ci" in script
|
||||
assert "npm run build" in script
|
||||
assert "--exclude=apps/web/node_modules" in script
|
||||
|
||||
|
||||
def test_web_dockerfile_uses_reachable_base_image_mirror():
|
||||
|
||||
Reference in New Issue
Block a user