diff --git a/scripts/build_release_images.sh b/scripts/build_release_images.sh index d87d61f50..079333f59 100755 --- a/scripts/build_release_images.sh +++ b/scripts/build_release_images.sh @@ -30,7 +30,8 @@ fi # ---- Registry 配置 ---- REGISTRY="${REGISTRY:-git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas}" CACHE_REGISTRY="${CACHE_REGISTRY:-git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas}" -CACHE_TAG="${CACHE_TAG:-release}" +# 主缓存 tag:develop 分支构建时写入,所有分支读取 +CACHE_TAG_PRIMARY="${CACHE_TAG:-develop}" API_IMAGE="xiaoxia-saas-api:$VERSION" WORKER_IMAGE="xiaoxia-saas-worker:$VERSION" @@ -45,6 +46,7 @@ REGISTRY_WEB="${REGISTRY}/xiaoxia-saas-web:$VERSION" USE_CACHE=0 USE_PUSH=0 +CACHE_WRITE=0 # 检查 buildx 和 Registry 认证 if docker buildx version >/dev/null 2>&1; then @@ -54,7 +56,10 @@ if docker buildx version >/dev/null 2>&1; then docker buildx use default 2>/dev/null || true fi -echo "=== Building API image ===" +# ---- 缓存读写策略(按分支隔离)---- +# 默认只读不写,防止 feature 分支污染主缓存 +# 只有 develop/main 分支才写回缓存 +BRANCH_NAME="${GITHUB_REF_NAME:-${CI_COMMIT_BRANCH:-unknown}}" if [ "$USE_CACHE" -eq 1 ]; then docker buildx build \ --build-arg APP_VERSION="$VERSION" \ @@ -68,6 +73,52 @@ else docker build --pull=false --build-arg APP_VERSION="$VERSION" -f infra/docker/api.Dockerfile -t "$API_IMAGE" -t "$API_LATEST" . fi +build_with_cache() { + # usage: build_with_cache + IMG_NAME="$1" + DOCKERFILE="$2" + shift 2 + EXTRA_ARGS="$*" + + CACHE_FROM="type=registry,ref=${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY},ignore-error=true" + + if [ "$CACHE_WRITE" -eq 1 ]; then + CACHE_TO="type=registry,ref=${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY},mode=max" + echo " cache: read+write from ${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY}" + else + CACHE_TO="" + echo " cache: read-only from ${CACHE_REGISTRY}/${IMG_NAME}-cache:${CACHE_TAG_PRIMARY}" + fi + + if [ "$USE_CACHE" -eq 1 ]; then + if [ -n "$CACHE_TO" ]; then + docker buildx build \ + $EXTRA_ARGS \ + --cache-from "$CACHE_FROM" \ + --cache-to "$CACHE_TO" \ + -f "$DOCKERFILE" \ + -t "$IMG_NAME:$VERSION" \ + --load \ + . + else + docker buildx build \ + $EXTRA_ARGS \ + --cache-from "$CACHE_FROM" \ + -f "$DOCKERFILE" \ + -t "$IMG_NAME:$VERSION" \ + --load \ + . + fi + else + docker build --pull=false $EXTRA_ARGS -f "$DOCKERFILE" -t "$IMG_NAME:$VERSION" . + fi +} + +echo "=== Building API image ===" +build_with_cache "api" "infra/docker/api.Dockerfile" \ + "--build-arg APP_VERSION=$VERSION" +docker tag "$API_IMAGE" "$API_LATEST" + echo "=== Building Worker image ===" if [ "$USE_CACHE" -eq 1 ]; then docker buildx build \ @@ -83,9 +134,16 @@ else fi echo "=== Building Web image (with buildx cache) ===" -# 先构建前端产物 +# 先构建前端产物(使用持久化 npm 缓存卷) +NPM_CACHE_VOLUME="xiaoxia-npm-cache" +if ! docker volume inspect "$NPM_CACHE_VOLUME" >/dev/null 2>&1; then + docker volume create "$NPM_CACHE_VOLUME" >/dev/null + echo " Created npm cache volume: $NPM_CACHE_VOLUME" +fi + docker run --rm \ -v "$PWD:/workspace" \ + -v "$NPM_CACHE_VOLUME:/workspace/apps/web/node_modules" \ -w /workspace/apps/web \ docker.m.daocloud.io/library/node:20 \ sh -lc "npm ci && npm run build"