Files
xiaoxia-saas/scripts/ci/docker_build_push.sh
T
xiaoxia 5672757e23
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m49s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 3m11s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2m37s
CI/CD Pipeline / Check push changed paths (push) Successful in 4m11s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 3m58s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 4m54s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 9m8s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m40s
AI Code Review / AI Code Review (pull_request) Failing after 7m3s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m41s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m28s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m40s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m0s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m7s
CI/CD Pipeline / Integration Tests (push) Successful in 4m19s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m32s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m32s
CI/CD Pipeline / Unit Tests (push) Successful in 15m46s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 12m52s
CI/CD Pipeline / CI Gate (pull_request) Successful in 32s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 432h20m34s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 432h20m36s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 432h20m36s
CI/CD Pipeline / Production Browser E2E (push) Failing after 432h20m45s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 432h24m11s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 432h24m13s
CI/CD Pipeline / Canary Release to Production (push) Failing after 432h24m40s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 432h24m15s
CI/CD Pipeline / Deploy Production (push) Failing after 432h24m42s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 432h30m18s
CI/CD Pipeline / Build Production API Image (push) Failing after 432h30m19s
CI/CD Pipeline / CI Gate (push) Failing after 432h30m26s
CI/CD Pipeline / ACR Image Cleanup (push) Failing after 432h35m59s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Failing after 432h36m1s
CI/CD Pipeline / Staging API Integration Tests (push) Failing after 432h35m59s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Failing after 432h36m1s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 432h35m59s
CI/CD Pipeline / Retag skipped Staging API Image (push) Failing after 432h36m2s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 432h37m3s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 432h37m5s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 432h37m7s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 432h37m8s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 432h37m9s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 432h37m10s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 432h39m32s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 432h39m55s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 432h39m57s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 432h42m23s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 432h42m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 432h44m51s
CI/CD Pipeline / PR Build Web Image (push) Failing after 432h45m50s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 432h45m48s
CI/CD Pipeline / PR Build API Image (push) Failing after 432h45m52s
CI/CD Pipeline / Frontend Lint (push) Failing after 432h46m48s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 432h46m50s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 432h49m36s
CI/CD Pipeline / Build Production Web Image (push) Failing after 433h4m21s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Failing after 433h10m3s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 433h11m6s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 433h13m55s
perf(ci): 流水线提速 - 路径过滤/持久builder缓存/依赖缓存卷/部署job迁移ci-l2 (#1536)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-08-29 14:36:04 +08:00

135 lines
4.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 通用Docker镜像构建+推送脚本
# 缓存策略(2026-08 起):
# - buildx 使用宿主机持久 builder (ci-builder-persist),层缓存保存在
# buildkit 容器/命名卷中,跨 job 共享、job 结束不清理
# - registry cache 仅作为冷启动兜底读取
# - 额外 tag(如分支 tag :develop)通过 EXTRA_TAGS 环境变量传入,随构建一并推送
# 用法: docker_build_push.sh [--no-cache] <Dockerfile> <image_tag> <cache_ref> [build_arg...]
# 环境变量:
# EXTRA_TAGS 空格分隔的额外 tag(完整 image:tag 引用),可选
set -eu
# 单次 build 超时时间(秒),防止 docker buildx build 无限挂起
BUILD_TIMEOUT=1500
# 持久 builder 名(宿主机级,所有 CI job 共享;由 ensure_persistent_builder.sh 维护)
BUILDER_NAME="ci-builder-persist"
NO_CACHE_FLAG=""
if [ "$1" = "--no-cache" ]; then
NO_CACHE_FLAG="--no-cache"
shift
echo "模式: --no-cache (不使用缓存,全新构建)"
fi
DOCKERFILE="$1"
IMAGE_TAG="$2"
CACHE_REF="$3"
shift 3
BUILD_ARGS=""
for arg in "$@"; do
BUILD_ARGS="$BUILD_ARGS --build-arg $arg"
done
# 确保持久 builder 存在并使用(幂等)
if ! docker buildx inspect "$BUILDER_NAME" > /dev/null 2>&1; then
echo "持久 builder 不存在,创建中..."
docker buildx create --name "$BUILDER_NAME" --driver docker-container \
--driver-opt network=host \
--buildkitd-flags "--allow-insecure-entitlement network.host" \
--platform linux/amd64
fi
docker buildx use "$BUILDER_NAME"
docker buildx inspect "$BUILDER_NAME" --bootstrap
# 组装额外 tag 参数
EXTRA_TAG_FLAGS=""
EXTRA_TAG_LIST=""
if [ -n "${EXTRA_TAGS:-}" ]; then
for t in $EXTRA_TAGS; do
EXTRA_TAG_FLAGS="$EXTRA_TAG_FLAGS -t $t"
EXTRA_TAG_LIST="$EXTRA_TAG_LIST $t"
done
fi
build_with_cache_retry() {
local attempt=1
local max_attempts=2
while [ $attempt -le $max_attempts ]; do
local build_output
local exit_code
set +e
build_output=$(timeout ${BUILD_TIMEOUT} docker buildx build \
$NO_CACHE_FLAG \
$BUILD_ARGS \
--cache-from "type=registry,ref=${CACHE_REF}" \
-f "${DOCKERFILE}" \
-t "${IMAGE_TAG}" \
$EXTRA_TAG_FLAGS \
--push \
. 2>&1)
exit_code=$?
set -e
if [ $exit_code -eq 0 ]; then
echo "$build_output"
return 0
fi
# 超时退出(exit code 124)
if [ $exit_code -eq 124 ]; then
echo "❌ Docker build TIMEOUT after ${BUILD_TIMEOUT}s - build hung and was killed"
echo "$build_output" | tail -20
return $exit_code
fi
# 检测到缓存/快照损坏类错误,重建 builder 后重试
if echo "$build_output" | grep -qE "parent snapshot.*not found|snapshot.*does not exist|cache.*corrupt|failed to compute cache key|no such file or directory.*cache"; then
echo "$build_output"
echo ""
echo "⚠️ builder 缓存异常,重建持久 builder 后重试 (attempt $attempt/$max_attempts)..."
# 共享 builder 的重建必须串行:ci-builder-persist 被所有 build job 共用,
# 若 job A 正在构建、job B 检测到损坏直接 rm,会把 A 正在用的 buildkit 杀掉。
# 用 flock 串行化重建;拿到锁后再次检查 builder 健康度,已被别的 job 重建则直接复用。
LOCK_FILE="/tmp/ci-builder-persist-rebuild.lock"
exec 9>"$LOCK_FILE"
echo "🔒 等待重建锁(最多 120s)..."
if flock -w 120 9; then
if docker buildx inspect "$BUILDER_NAME" --bootstrap >/dev/null 2>&1; then
echo "✅ builder 已被其他并发 job 重建/恢复,直接复用"
else
echo "🔨 锁内重建持久 builder..."
docker buildx rm "$BUILDER_NAME" >/dev/null 2>&1 || true
docker buildx create --name "$BUILDER_NAME" --driver docker-container \
--driver-opt network=host \
--buildkitd-flags "--allow-insecure-entitlement network.host" \
--platform linux/amd64
docker buildx use "$BUILDER_NAME"
docker buildx inspect "$BUILDER_NAME" --bootstrap
fi
else
echo "⚠️ 等待重建锁超时,直接重试 build(失败将重试/--no-cache)"
docker buildx use "$BUILDER_NAME" 2>/dev/null || true
fi
attempt=$((attempt + 1))
else
echo "$build_output"
return $exit_code
fi
done
return 1
}
echo "=== Build & push image (persistent builder cache) ==="
echo "Builder: ${BUILDER_NAME} (persistent)"
echo "Registry cache(from): ${CACHE_REF}"
echo "Image tag: ${IMAGE_TAG}"
[ -n "$EXTRA_TAG_LIST" ] && echo "Extra tags: ${EXTRA_TAG_LIST}"
echo "Timeout: ${BUILD_TIMEOUT}s"
echo ""
build_with_cache_retry
echo ""
echo "Image pushed: ${IMAGE_TAG}"
[ -n "$EXTRA_TAG_LIST" ] && echo "Also pushed: ${EXTRA_TAG_LIST}"
echo ""
echo "Build completed: ${IMAGE_TAG}"