From 7716371c8d1aaccd2a9f240d7a72fc96d2eacbd3 Mon Sep 17 00:00:00 2001 From: Xiaoxia AI Date: Mon, 22 Jun 2026 15:00:23 +0800 Subject: [PATCH] fix(release): prevent runtime builds on production host --- docs/DEPLOYMENT.md | 1 + scripts/build_release_images.sh | 8 ++++++++ tests/unit/test_release_scripts.py | 2 ++ 3 files changed, 11 insertions(+) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 822f5f308..2a6d69e16 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -126,3 +126,4 @@ Staging 当前可以保持 no-op;Production 开启前必须先验证 SMTP/Redi - 生产环境必须设置 `DEBUG=false`。 - staging / production 不允许开启 `AUTO_CREATE_SCHEMA` 绕过 Alembic。 - 生产机禁止构建 API/Worker runtime 镜像;如发现需要构建,先补构建机/CI 产物流程,不得临时开启生产构建。 +- `scripts/build_release_images.sh` 会检测生产容器;如果当前机器运行生产服务,默认拒绝构建 runtime 镜像。 diff --git a/scripts/build_release_images.sh b/scripts/build_release_images.sh index 4bc7e3189..83b379d28 100755 --- a/scripts/build_release_images.sh +++ b/scripts/build_release_images.sh @@ -20,6 +20,14 @@ TAR_PATH="$OUTPUT_DIR/xiaoxia-runtime-images-$VERSION.tar" cd "$ROOT_DIR" +if docker ps --format '{{.Names}}' | grep -Eq '^(xiaoxia-(api|web|worker|postgres|redis)-production|gitea)$'; then + if [ "${ALLOW_SHARED_PRODUCTION_BUILD_HOST:-false}" != "true" ]; then + echo "Refusing to build runtime images on a host that is running production services." + echo "Use a dedicated build host/CI runner, or set ALLOW_SHARED_PRODUCTION_BUILD_HOST=true only for an explicitly approved emergency." + exit 1 + fi +fi + docker build --pull=false -f infra/docker/api.Dockerfile -t "$API_IMAGE" -t "$API_LATEST" . docker build --pull=false -f infra/docker/worker.Dockerfile -t "$WORKER_IMAGE" -t "$WORKER_LATEST" . docker save "$API_IMAGE" "$API_LATEST" "$WORKER_IMAGE" "$WORKER_LATEST" -o "$TAR_PATH" diff --git a/tests/unit/test_release_scripts.py b/tests/unit/test_release_scripts.py index 539c17f86..e1bae9d36 100644 --- a/tests/unit/test_release_scripts.py +++ b/tests/unit/test_release_scripts.py @@ -170,6 +170,8 @@ def test_runtime_image_release_scripts_keep_builds_off_production(): assert "docker build --pull=false -f infra/docker/api.Dockerfile" in build_script assert "docker build --pull=false -f infra/docker/worker.Dockerfile" in build_script assert "docker save" in build_script + assert "Refusing to build runtime images on a host that is running production services." in build_script + assert "ALLOW_SHARED_PRODUCTION_BUILD_HOST=true" in build_script assert "docker load -i" in deploy_script assert "API_IMAGE=\"xiaoxia-saas-api:$VERSION\"" in deploy_script assert "WORKER_IMAGE=\"xiaoxia-saas-worker:$VERSION\"" in deploy_script