ci: PR构建验证 + Agent提交格式化 + buildx清理 (#690)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 42s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 2m22s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m25s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m36s
CI/CD Pipeline / Unit Tests (push) Successful in 2m40s
CI/CD Pipeline / Integration Tests (push) Successful in 1m10s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 22m16s
CI/CD Pipeline / Build Staging API Image (push) Failing after 22m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 42s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 2m22s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m25s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m36s
CI/CD Pipeline / Unit Tests (push) Successful in 2m40s
CI/CD Pipeline / Integration Tests (push) Successful in 1m10s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 22m16s
CI/CD Pipeline / Build Staging API Image (push) Failing after 22m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
This commit was merged in pull request #690.
This commit is contained in:
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# Agent代码提交前自动格式化+质量检查脚本
|
||||
# 用法: scripts/agent-commit.sh <commit_message> [files...]
|
||||
# 效果: 自动跑black+isort+ruff check,通过后才commit+push
|
||||
set -e
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "用法: $0 <commit_message> [file1 file2 ...]"
|
||||
echo "示例: $0 \"feat: add new api\" apps/api/src/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMIT_MSG="$1"
|
||||
shift
|
||||
|
||||
TARGETS="${@:-.}"
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
REPO_ROOT=$(pwd)
|
||||
echo "仓库根目录: $REPO_ROOT"
|
||||
echo "提交信息: $COMMIT_MSG"
|
||||
echo "目标路径: $TARGETS"
|
||||
echo ""
|
||||
|
||||
# 后端代码格式化(Python文件)
|
||||
PYTHON_FILES=$(find $TARGETS -name "*.py" -type f 2>/dev/null | head -100 || true)
|
||||
if [ -n "$PYTHON_FILES" ]; then
|
||||
echo "=== Step 1/4: 后端代码格式化 (black) ==="
|
||||
if command -v black &> /dev/null; then
|
||||
black $TARGETS 2>&1 | tail -3
|
||||
echo "✅ black 完成"
|
||||
else
|
||||
echo "⚠️ 未安装black,跳过"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "=== Step 2/4: import排序 (isort) ==="
|
||||
if command -v isort &> /dev/null; then
|
||||
isort $TARGETS 2>&1 | tail -3
|
||||
echo "✅ isort 完成"
|
||||
else
|
||||
echo "⚠️ 未安装isort,跳过"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "=== Step 3/4: 代码质量检查 (ruff check) ==="
|
||||
if command -v ruff &> /dev/null; then
|
||||
RUFF_OUTPUT=$(ruff check $TARGETS 2>&1) || true
|
||||
RUFF_ERRORS=$(echo "$RUFF_OUTPUT" | grep -c "^" || echo 0)
|
||||
if [ "$RUFF_ERRORS" -le 2 ] || echo "$RUFF_OUTPUT" | grep -q "All checks passed"; then
|
||||
echo "✅ ruff 检查通过(错误数: $RUFF_ERRORS)"
|
||||
else
|
||||
echo "❌ ruff 发现以下问题:"
|
||||
echo "$RUFF_OUTPUT" | head -30
|
||||
echo ""
|
||||
echo "请修复后重新提交,或手动忽略特定问题"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 未安装ruff,跳过"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
echo "ℹ️ 未检测到Python文件,跳过后端格式化"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 前端代码格式化(TS/TSX文件)
|
||||
TS_FILES=$(find $TARGETS -name "*.ts" -o -name "*.tsx" -type f 2>/dev/null | head -100 || true)
|
||||
if [ -n "$TS_FILES" ] && [ -f "apps/web/package.json" ]; then
|
||||
echo "=== Step 4/4: 前端代码格式化 (prettier) ==="
|
||||
if command -v npx &> /dev/null; then
|
||||
cd apps/web && npx prettier --write "src/**/*.{ts,tsx}" 2>&1 | tail -3 || true
|
||||
cd "$REPO_ROOT"
|
||||
echo "✅ prettier 完成"
|
||||
else
|
||||
echo "⚠️ 未安装npx,跳过前端格式化"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Git操作
|
||||
echo "=== 提交代码 ==="
|
||||
git add -A
|
||||
git diff --cached --stat
|
||||
echo ""
|
||||
git commit -m "$COMMIT_MSG"
|
||||
echo ""
|
||||
echo "✅ 本地提交完成"
|
||||
|
||||
# 可选:自动推送
|
||||
if [ "$AGENT_AUTO_PUSH" = "true" ]; then
|
||||
echo "正在推送到远程..."
|
||||
git push
|
||||
echo "✅ 推送完成"
|
||||
else
|
||||
echo "ℹ️ 本地已提交,如需推送执行: git push"
|
||||
echo " 设置 AGENT_AUTO_PUSH=true 可自动推送"
|
||||
fi
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# PR构建专用:只构建不推送,只读缓存不写,用于PR阶段验证Dockerfile
|
||||
set -eu
|
||||
|
||||
NO_CACHE_FLAG=""
|
||||
if [ "$1" = "--no-cache" ]; then
|
||||
NO_CACHE_FLAG="--no-cache"
|
||||
shift
|
||||
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_NAME="ci-pr-builder-${GITHUB_RUN_ID:-local}"
|
||||
if ! docker buildx inspect "$BUILDER_NAME" > /dev/null 2>&1; then
|
||||
docker buildx create --use --name "$BUILDER_NAME" --driver docker-container
|
||||
else
|
||||
docker buildx use "$BUILDER_NAME"
|
||||
fi
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
CACHE_NAME=$(echo "$CACHE_REF" | tr "/" "_" | tr ":" "-")
|
||||
LOCAL_CACHE_DIR="/tmp/buildx-cache/${CACHE_NAME}"
|
||||
mkdir -p "$LOCAL_CACHE_DIR"
|
||||
|
||||
echo "=== PR Build: build only, no push, read-only cache ==="
|
||||
echo "Dockerfile: ${DOCKERFILE}"
|
||||
echo "Image tag: ${IMAGE_TAG}"
|
||||
echo ""
|
||||
|
||||
build_with_retry() {
|
||||
local attempt=1
|
||||
local max_attempts=2
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
local build_output
|
||||
local exit_code
|
||||
set +e
|
||||
build_output=$(docker buildx build \
|
||||
$NO_CACHE_FLAG \
|
||||
$BUILD_ARGS \
|
||||
--cache-from "type=local,src=${LOCAL_CACHE_DIR}" \
|
||||
--cache-from "type=registry,ref=${CACHE_REF}" \
|
||||
-f "${DOCKERFILE}" \
|
||||
-t "${IMAGE_TAG}" \
|
||||
--load \
|
||||
. 2>&1)
|
||||
exit_code=$?
|
||||
set -e
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "$build_output"
|
||||
return 0
|
||||
fi
|
||||
if echo "$build_output" | grep -qE "parent snapshot.*not found|snapshot.*does not exist|cache.*corrupt|failed to compute cache key"; then
|
||||
echo "$build_output"
|
||||
echo "Local cache corrupted, cleaning and retrying ($attempt/$max_attempts)..."
|
||||
rm -rf "${LOCAL_CACHE_DIR}"
|
||||
mkdir -p "${LOCAL_CACHE_DIR}"
|
||||
docker buildx prune -f -a >/dev/null 2>&1 || true
|
||||
attempt=$((attempt + 1))
|
||||
else
|
||||
echo "$build_output"
|
||||
return $exit_code
|
||||
fi
|
||||
done
|
||||
echo "Local cache failed, building with registry cache only..."
|
||||
docker buildx build \
|
||||
$NO_CACHE_FLAG \
|
||||
$BUILD_ARGS \
|
||||
--cache-from "type=registry,ref=${CACHE_REF}" \
|
||||
-f "${DOCKERFILE}" \
|
||||
-t "${IMAGE_TAG}" \
|
||||
--load \
|
||||
.
|
||||
}
|
||||
|
||||
build_with_retry
|
||||
echo ""
|
||||
echo "PR build OK (not pushed): ${IMAGE_TAG}"
|
||||
Reference in New Issue
Block a user