fix(ci): #2081 follow-up——CI 部署脚本修复(compose.yml 由 CI scp + --env-file) #2082

Merged
xiaoxia merged 2 commits from fix/ci-worker-compose-followup into develop 2026-09-28 02:41:32 +08:00
2 changed files with 31 additions and 29 deletions
+9 -1
View File
@@ -1302,8 +1302,16 @@ jobs:
"${staging_user}@${staging_host}:/var/lib/xiaoxia-saas-staging/configs/douyin_cookies.txt"
echo "✅ Douyin cookies uploaded"
# 上传 infra/docker 配置到服务器(compose 单一事实来源)
echo "Uploading infra/docker configs to staging server..."
ssh -p "$staging_port" -i "$key_path" -o StrictHostKeyChecking=no "${staging_user}@${staging_host}" \
"mkdir -p /var/lib/xiaoxia-saas-staging/infra/docker"
scp -P "$staging_port" -i "$key_path" -o StrictHostKeyChecking=no infra/docker/compose.yml \
"${staging_user}@${staging_host}:/var/lib/xiaoxia-saas-staging/infra/docker/compose.yml"
echo "✅ infra/docker/compose.yml uploaded"
# 通过环境变量传递凭证,避免命令行引号转义问题
cat scripts/ci_staging_deploy.sh | ssh -p "$staging_port" -i "$key_path" -o StrictHostKeyChecking=no "${staging_user}@${staging_host}" "IMAGE_TAG=${GITHUB_SHA} ACR_USERNAME=${ACR_USERNAME} ACR_PASSWORD=${ACR_PASSWORD} sh"
cat scripts/ci_staging_deploy.sh | ssh -p "$staging_port" -i "$key_path" -o StrictHostKeyChecking=no "${staging_user}@${staging_host}" "IMAGE_TAG=${GITHUB_SHA} ACR_USERNAME=${ACR_USERNAME} ACR_PASSWORD=${ACR_PASSWORD} COMPOSE_SYNC=0 sh"
# 清理 CI runner 上的渲染文件
rm -f .env.rendered
+22 -28
View File
@@ -52,6 +52,8 @@ COOKIES_FILE="${COOKIES_FILE:-/var/lib/xiaoxia-saas-staging/configs/douyin_cooki
INFRA_DOCKER_DIR="${INFRA_DOCKER_DIR:-/var/lib/xiaoxia-saas-staging/infra/docker}"
COMPOSE_PROJECT="${COMPOSE_PROJECT:-xiaoxia-staging}"
COMPOSE_ENV_VALUE="${COMPOSE_ENV_VALUE:-staging}"
# COMPOSE_SYNC: CI workflow 已通过 scp 把 infra/docker/compose.yml 上传到服务器时设为 0 跳过同步
COMPOSE_SYNC="${COMPOSE_SYNC:-1}"
SKIP_MIGRATION="${SKIP_MIGRATION:-false}"
SKIP_ROLLBACK="${SKIP_ROLLBACK:-false}"
@@ -123,26 +125,24 @@ server {
NGINX_EOF
echo "✅ Nginx config written: $NGINX_CONF_FILE"
# ── 同步 infra/docker/compose.yml(单一事实来源)──
COMPOSE_FILE_URL="${COMPOSE_FILE_URL:-https://git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas/raw/branch/${IMAGE_TAG}/infra/docker/compose.yml}"
echo "Syncing infra/docker/compose.yml from repo (tag=$IMAGE_TAG)..."
COMPOSE_SYNC_OK=0
if command -v curl >/dev/null 2>&1; then
if retry_cmd 3 5 curl -sf --max-time 15 -o "$INFRA_DOCKER_DIR/compose.yml" "$COMPOSE_FILE_URL"; then
echo "✅ compose.yml written: $INFRA_DOCKER_DIR/compose.yml ($(wc -l < "$INFRA_DOCKER_DIR/compose.yml") lines)"
COMPOSE_SYNC_OK=1
else
echo "WARN: failed to fetch compose.yml from repo, will use existing server copy"
fi
else
echo "WARN: curl not available, skipping compose.yml sync"
fi
if [ "$COMPOSE_SYNC_OK" -ne 1 ] && [ ! -f "$INFRA_DOCKER_DIR/compose.yml" ]; then
echo "ERROR: no compose.yml available (sync failed and no existing copy)"
# ── 确认 infra/docker/compose.yml 存在 ──
# CI workflow 在执行本脚本前已通过 scp 把 infra/docker/compose.yml 上传到 $INFRA_DOCKER_DIR
# (workflow 里做:scp infra/docker/compose.yml <host>:$INFRA_DOCKER_DIR/compose.yml)。
# 这里只做存在性检查 + nginx 软链;不再 curl 私有仓库(SSH 环境无 Gitea token)。
COMPOSE_FILE_PATH="$INFRA_DOCKER_DIR/compose.yml"
if [ ! -f "$COMPOSE_FILE_PATH" ]; then
echo "ERROR: $COMPOSE_FILE_PATH 不存在。CI workflow 应先 scp infra/docker/compose.yml 到服务器"
exit 1
fi
echo "✅ compose.yml ready: $COMPOSE_FILE_PATH ($(wc -l < "$COMPOSE_FILE_PATH") lines)"
ln -sf "$NGINX_CONF_FILE" "$INFRA_DOCKER_DIR/nginx-${COMPOSE_ENV_VALUE}.conf" 2>/dev/null || true
# 封装 docker compose 调用:统一 --env-file(compose 默认只读取 project 目录下的 .env,
# 我们的 .env 在 $INFRA_DOCKER_DIR/../../.env,必须显式传入才能读到 GENERATED_FILES_HOST_DIR 等变量)
compose() {
(cd "$INFRA_DOCKER_DIR" && docker compose --env-file "$ENV_FILE" -p "$COMPOSE_PROJECT" "$@")
}
echo "==========================================="
echo " Staging 部署 - $IMAGE_TAG"
echo "==========================================="
@@ -182,11 +182,8 @@ rollback() {
docker rm -f xiaoxia-api-staging xiaoxia-web-staging 2>/dev/null || true
if [ -n "$PREV_WORKER_IMAGE" ]; then
echo "Rolling back Worker to: $PREV_WORKER_IMAGE (via compose)"
(cd "$INFRA_DOCKER_DIR" && \
ENV="$COMPOSE_ENV_VALUE" \
WORKER_IMAGE="$PREV_WORKER_IMAGE" \
docker compose -p "$COMPOSE_PROJECT" up -d worker) 2>&1 || \
echo "WARN: compose rollback for worker failed, fallback to docker run"
compose up -d --no-deps worker 2>&1 || echo "WARN: compose rollback failed, fallback to docker run"
# 镜像通过 env 注入:compose 默认读 WORKER_IMAGE(未设则用 :dev),这里用临时 env 覆盖
if ! docker inspect xiaoxia-worker-staging >/dev/null 2>&1; then
echo "Fallback: docker run previous worker image"
docker run -d \
@@ -518,14 +515,11 @@ docker run -d \
PID_API_START=$!
# ── Worker: 通过 compose 启动(单一事实来源)──
# compose.yml 定义:三进程(beat+generation+transcode)、独立并发、BEAT_ENABLED、
# healthcheck 匹配 'celery.*worker'(不把 beat 算活)、资源限制 4C/8G。
# WORKER_IMAGE 通过环境变量覆盖镜像 tag(compose.yml 默认 :dev)。
echo "Starting worker via docker compose (from $INFRA_DOCKER_DIR)..."
(
cd "$INFRA_DOCKER_DIR" && \
ENV="$COMPOSE_ENV_VALUE" \
WORKER_IMAGE="$REGISTRY_WORKER" \
APP_VERSION="$IMAGE_TAG" \
docker compose -p "$COMPOSE_PROJECT" up -d worker
) &
WORKER_IMAGE="$REGISTRY_WORKER" APP_VERSION="$IMAGE_TAG" compose up -d --no-deps worker &
PID_WORKER_START=$!
# ── Web: 暂保留 docker run(TODO: 后续收敛到 compose)──