From f34b076dcd876c06fc03485f167ad35ab6df42d9 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Mon, 31 Aug 2026 21:09:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(ci):=20Web=20=E9=95=9C=E5=83=8F=20buildx=20?= =?UTF-8?q?=E5=B9=BD=E7=81=B5=E7=BC=93=E5=AD=98=E9=98=B2=E6=8A=A4=E2=80=94?= =?UTF-8?q?=E2=80=94Git=20Tree=20Hash=20Cache=20Bust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:ci-builder-persist 持久化 builder 的 buildkit 层缓存偶尔出现'幽灵命中': COPY apps/web/ ./ 步骤认为自己没变(实际文件已改),导致 vite build 不执行, 打出来的 Web 镜像前端文件是旧的。 修复原理: 把 apps/web/ 目录的 git tree hash 作为 build arg 传入 Dockerfile。 buildx 把 build arg 值作为缓存键的一部分,hash 变了 → RUN 步骤缓存失效 → vite build 必须重新执行。依赖层(npm ci)不受影响,仍然正常缓存。 改动: 1. web.Dockerfile:新增 ARG SOURCE_HASH,在构建步骤写入 .cache_bust 文件 2. docker_build_push.sh:Web 镜像构建时计算 git tree hash 并传入 3. docker_build_only.sh:同上 验证: - 合并后触发 push 到 develop - 查看 Build Staging Web Image 日志,确认输出 Web cache bust: SOURCE_HASH=xxxxx - 修改 apps/web/ 下文件再次 push,确认 SOURCE_HASH 值变化且 vite build 执行 --- infra/docker/web.Dockerfile | 3 +++ scripts/ci/docker_build_only.sh | 12 ++++++++++++ scripts/ci/docker_build_push.sh | 12 ++++++++++++ 3 files changed, 27 insertions(+) diff --git a/infra/docker/web.Dockerfile b/infra/docker/web.Dockerfile index 6465e56fe..10cd2f15d 100755 --- a/infra/docker/web.Dockerfile +++ b/infra/docker/web.Dockerfile @@ -1,5 +1,6 @@ # Build stage FROM git.xiaoxiajianji.com/xiaoxia/base/node:20 AS builder +ARG SOURCE_HASH="" WORKDIR /app ARG VITE_API_URL=https://saas-api.xiaoxiajianji.com ENV VITE_API_URL=$VITE_API_URL @@ -18,8 +19,10 @@ COPY apps/web/ ./ # 构建:TS增量编译 + Vite构建,tsbuildinfo用cache mount持久化 # node_modules直接使用镜像中已安装的(layer缓存保证完整性) +# SOURCE_HASH 变化时强制重新执行(防止 buildkit 幽灵缓存命中) RUN --mount=type=cache,target=/app/apps/web/.tscache,sharing=locked \ mkdir -p .tscache \ + && echo "SOURCE_HASH=${SOURCE_HASH}" > .cache_bust \ && ./node_modules/.bin/tsc --incremental --tsBuildInfoFile .tscache/tsconfig.tsbuildinfo \ && ./node_modules/.bin/vite build diff --git a/scripts/ci/docker_build_only.sh b/scripts/ci/docker_build_only.sh index aed388ba9..20070b717 100755 --- a/scripts/ci/docker_build_only.sh +++ b/scripts/ci/docker_build_only.sh @@ -19,6 +19,18 @@ for arg in "$@"; do BUILD_ARGS="$BUILD_ARGS --build-arg $arg" done +# Web 镜像 cache bust:计算 apps/web/ 的 git tree hash +# 当源码变化时 hash 变化,buildx 的 ARG 缓存键失效 → vite build 必定重新执行 +if [ "${DOCKERFILE##*/}" = "web.Dockerfile" ]; then + SOURCE_HASH=$(git rev-parse HEAD:apps/web 2>/dev/null || echo "") + if [ -n "$SOURCE_HASH" ]; then + echo "Web cache bust: SOURCE_HASH=${SOURCE_HASH}" + BUILD_ARGS="$BUILD_ARGS --build-arg SOURCE_HASH=${SOURCE_HASH}" + else + echo "⚠️ 无法计算 apps/web tree hash,跳过 cache bust" + fi +fi + BUILDER_NAME="ci-builder-persist" if ! docker buildx inspect "$BUILDER_NAME" > /dev/null 2>&1; then echo "持久 builder 不存在,创建中..." diff --git a/scripts/ci/docker_build_push.sh b/scripts/ci/docker_build_push.sh index 26fbc8bb5..0f0fc018e 100755 --- a/scripts/ci/docker_build_push.sh +++ b/scripts/ci/docker_build_push.sh @@ -31,6 +31,18 @@ for arg in "$@"; do BUILD_ARGS="$BUILD_ARGS --build-arg $arg" done +# Web 镜像 cache bust:计算 apps/web/ 的 git tree hash +# 当源码变化时 hash 变化,buildx 的 ARG 缓存键失效 → vite build 必定重新执行 +if [ "${DOCKERFILE##*/}" = "web.Dockerfile" ]; then + SOURCE_HASH=$(git rev-parse HEAD:apps/web 2>/dev/null || echo "") + if [ -n "$SOURCE_HASH" ]; then + echo "Web cache bust: SOURCE_HASH=${SOURCE_HASH}" + BUILD_ARGS="$BUILD_ARGS --build-arg SOURCE_HASH=${SOURCE_HASH}" + else + echo "⚠️ 无法计算 apps/web tree hash,跳过 cache bust" + fi +fi + # 确保持久 builder 存在并使用(幂等) if ! docker buildx inspect "$BUILDER_NAME" > /dev/null 2>&1; then echo "持久 builder 不存在,创建中..."