diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7859fa3fc..79a26d7de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,48 +8,57 @@ on: - '**/*.kt' env: - # 🚀 优化后的 Gradle 配置 - 提升构建性能 - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=8 -Dkotlin.incremental=true -Dorg.gradle.configuration-cache=true -Dorg.gradle.build-cache=true -Dorg.gradle.caching=true" - # 🎯 JVM 性能优化配置 - 针对 GitHub Actions 7GB 内存环境调优 - JVM_OPTS: "-Xmx5g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:G1HeapRegionSize=32m -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UseLargePages" - # 🐳 Docker 和 TestContainers 优化 + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=6 -Dkotlin.incremental=true -Dorg.gradle.configuration-cache=true -Dorg.gradle.build-cache=true -Dorg.gradle.caching=true" + JVM_OPTS: "-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:+UseStringDeduplication" TESTCONTAINERS_RYUK_DISABLED: false TESTCONTAINERS_REUSE_ENABLE: true DOCKER_BUILDKIT: 1 jobs: - # 🔍 快速检查 - 编译和基础验证 quick-check: - name: "🔍 Quick Check" + name: Quick Check runs-on: ubuntu-latest timeout-minutes: 8 outputs: cache-key: ${{ steps.cache-info.outputs.cache-key }} gradle-cache-key: ${{ steps.cache-info.outputs.gradle-cache-key }} + java-version: ${{ steps.version-info.outputs.java-version }} + gradle-version: ${{ steps.version-info.outputs.gradle-version }} steps: - name: Checkout code uses: actions/checkout@v5.0.0 with: - fetch-depth: 1 # 浅克隆提升速度 + fetch-depth: 1 - - name: Set up JDK 17 + - name: Extract versions from libs.versions.toml + id: version-info + run: | + JAVA_VERSION=$(sed -n 's/^java\s*=\s*"\(.*\)"/\1/p' gradle/libs.versions.toml | head -n1) + GRADLE_VERSION=$(sed -n 's/^org-gradle\s*=\s*"\(.*\)"/\1/p' gradle/libs.versions.toml | head -n1) + + echo "java-version=$JAVA_VERSION" >> $GITHUB_OUTPUT + echo "gradle-version=$GRADLE_VERSION" >> $GITHUB_OUTPUT + + echo "Extracted Java version: $JAVA_VERSION" + echo "Extracted Gradle version: $GRADLE_VERSION" + + - name: Set up JDK ${{ steps.version-info.outputs.java-version }} uses: actions/setup-java@v5.0.0 with: - java-version: '17' - distribution: 'graalvm' + java-version: ${{ steps.version-info.outputs.java-version }} + distribution: 'temurin' cache: gradle - - name: 📊 Cache info + - name: Cache info id: cache-info run: | - # 生成更精确的缓存键 GRADLE_CACHE_KEY="${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'build-logic/**/*') }}" DEPS_CACHE_KEY="${{ runner.os }}-deps-${{ hashFiles('gradle/libs.versions.toml', '**/build.gradle.kts') }}" echo "cache-key=$GRADLE_CACHE_KEY" >> $GITHUB_OUTPUT echo "gradle-cache-key=$DEPS_CACHE_KEY" >> $GITHUB_OUTPUT - - name: 🎯 Cache Gradle wrapper and distributions + - name: Cache Gradle wrapper and distributions uses: actions/cache@v4 with: path: | @@ -61,7 +70,7 @@ jobs: ${{ runner.os }}-deps- ${{ runner.os }}-gradle- - - name: 📦 Cache build outputs + - name: Cache build outputs uses: actions/cache@v4 with: path: | @@ -76,16 +85,15 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: - gradle-version: '9.0.0' + gradle-version: ${{ steps.version-info.outputs.gradle-version }} cache-read-only: false cache-write-only: false - name: Grant execute permission run: chmod +x gradlew - - name: 🚀 Quick compile with optimizations + - name: Quick compile run: | - # 预热 Gradle daemon 并编译 ./gradlew help --quiet ./gradlew compileKotlin compileTestKotlin \ --no-daemon \ @@ -94,78 +102,92 @@ jobs: --configuration-cache \ --quiet - # 🧪 优化后的并行测试矩阵 - 重新分组以提升并行效率 test-matrix: - name: "🧪 Test" + name: Test needs: quick-check runs-on: ubuntu-latest timeout-minutes: 25 strategy: fail-fast: false - max-parallel: 6 # 增加并行度 + max-parallel: 6 matrix: group: - - "core-fast" # 快速核心模块 - - "core-build" # 构建相关模块 - - "rds-light" # 轻量数据库模块 - - "rds-heavy" # 重量数据库模块 - - "business-ai" # AI 和支付模块 - - "business-oss" # 对象存储模块 - - "business-misc" # 其他业务模块 - - "security" # 安全模块 - - "data-depend" # 数据和依赖模块 + - "core-foundation" + - "core-build-tools" + - "rds-light" + - "rds-heavy" + - "business-ai-pay" + - "business-oss" + - "business-communication" + - "security" + - "data-processing" + - "platform-integrations" + - "testing-tools" + - "integration-tests" include: - - group: "core-fast" - modules: "shared testtoolkit" - containers: "none" + - group: "core-foundation" + modules: "shared cacheable docsite" + testcontainers: false timeout: 8 - - group: "core-build" + - group: "core-build-tools" modules: "gradle-plugin version-catalog bom" - containers: "none" + testcontainers: false timeout: 10 - group: "rds-light" modules: "rds:rds-shared rds:rds-flyway-migration-shared" - containers: "none" + testcontainers: false timeout: 8 - group: "rds-heavy" modules: "rds:rds-crud rds:rds-jimmer-ext-postgres rds:rds-flyway-migration-postgresql rds:rds-flyway-migration-mysql8" - containers: "database" - timeout: 20 - - group: "business-ai" + testcontainers: true + timeout: 25 + - group: "business-ai-pay" modules: "ai:ai-shared ai:ai-langchain4j pay:pay-shared pay:pay-wechat" - containers: "cache" - timeout: 15 + testcontainers: true + timeout: 18 - group: "business-oss" modules: "oss:oss-shared oss:oss-minio oss:oss-aliyun-oss oss:oss-huawei-obs oss:oss-volcengine-tos" - containers: "cache" - timeout: 18 - - group: "business-misc" - modules: "sms:sms-shared sms:sms-tencent surveillance:surveillance-shared surveillance:surveillance-hikvision cacheable" - containers: "cache" - timeout: 12 + testcontainers: true + timeout: 20 + - group: "business-communication" + modules: "sms:sms-shared sms:sms-tencent surveillance:surveillance-shared surveillance:surveillance-hikvision" + testcontainers: true + timeout: 15 - group: "security" modules: "security:security-crypto security:security-oauth2 security:security-spring" - containers: "none" - timeout: 10 - - group: "data-depend" - modules: "data:data-crawler data:data-extract depend:depend-http-exchange depend:depend-jackson depend:depend-paho depend:depend-servlet depend:depend-springdoc-openapi depend:depend-xxl-job ksp:ksp-meta ksp:ksp-plugin ksp:ksp-shared psdk:psdk-wxpa" - containers: "none" + testcontainers: false + timeout: 12 + - group: "data-processing" + modules: "data:data-crawler data:data-extract" + testcontainers: true + timeout: 15 + - group: "platform-integrations" + modules: "depend:depend-http-exchange depend:depend-jackson depend:depend-paho depend:depend-servlet depend:depend-springdoc-openapi depend:depend-xxl-job ksp:ksp-meta ksp:ksp-plugin ksp:ksp-shared psdk:psdk-wxpa ide:ide-idea-mcp" + testcontainers: false + timeout: 18 + - group: "testing-tools" + modules: "testtoolkit:testtoolkit-shared testtoolkit:testtoolkit-testcontainers testtoolkit:testtoolkit-springmvc" + testcontainers: true timeout: 15 + - group: "integration-tests" + modules: "integrate-test:depend:jackson integrate-test:oss:minio integrate-test:cacheable" + testcontainers: true + timeout: 30 steps: - name: Checkout code uses: actions/checkout@v5.0.0 with: - fetch-depth: 1 # 浅克隆 + fetch-depth: 1 - - name: Set up JDK 17 + - name: Set up JDK ${{ needs.quick-check.outputs.java-version }} uses: actions/setup-java@v5.0.0 with: - java-version: '17' - distribution: 'graalvm' + java-version: ${{ needs.quick-check.outputs.java-version }} + distribution: 'temurin' cache: gradle - - name: 🎯 Restore Gradle wrapper cache + - name: Restore Gradle wrapper cache uses: actions/cache/restore@v4 with: path: | @@ -177,7 +199,7 @@ jobs: ${{ runner.os }}-deps- ${{ runner.os }}-gradle- - - name: 📦 Restore build cache + - name: Restore build cache uses: actions/cache/restore@v4 with: path: | @@ -192,126 +214,113 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: - gradle-version: '9.0.0' + gradle-version: ${{ needs.quick-check.outputs.gradle-version }} cache-read-only: true cache-write-only: false - # 🐳 优化的 Docker 设置 - - name: Set up Docker Buildx - if: matrix.containers != 'none' - uses: docker/setup-buildx-action@v3 - with: - driver-opts: | - network=host - image=moby/buildkit:v0.12.0 - - - name: 🗂️ Cache Docker layers - if: matrix.containers != 'none' - uses: actions/cache@v4 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-docker-${{ matrix.group }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-docker-${{ matrix.group }}- - ${{ runner.os }}-docker- - - name: Grant execute permission run: chmod +x gradlew - - name: 🧪 Run tests for ${{ matrix.group }} modules + - name: Run tests timeout-minutes: ${{ matrix.timeout }} run: | - echo "🚀 开始执行 ${{ matrix.group }} 模块组测试..." - echo "📚 模块列表: ${{ matrix.modules }}" - echo "🐳 容器配置: ${{ matrix.containers }}" - echo "⏱️ 超时设置: ${{ matrix.timeout }} 分钟" - - # 设置错误处理 set -e - trap 'echo "❌ 测试执行失败,正在收集错误信息..." >> $GITHUB_STEP_SUMMARY' ERR - # 预热 Gradle ./gradlew help --quiet - # 将模块名转换为测试任务 modules="${{ matrix.modules }}" test_tasks="" + + echo "Checking available test tasks for modules: $modules" + for module in $modules; do - if [[ "$module" == *":"* ]]; then - # 子模块格式 (如 rds:rds-shared) - test_tasks="$test_tasks :$module:test" + module_path=":$module" + if [[ "$module" != *":"* ]]; then + module_path=":$module" + fi + + # 检查模块是否有test任务 + if ./gradlew $module_path:tasks --all --quiet 2>/dev/null | grep -E "^test\s" >/dev/null; then + test_tasks="$test_tasks $module_path:test" + echo "✓ Found test task for $module" else - # 根级模块格式 (如 shared) - test_tasks="$test_tasks :$module:test" + echo "⚠ No test task found for $module, will check compilation instead" fi done - echo "🎯 执行测试任务: $test_tasks" - ./gradlew $test_tasks \ - --no-daemon \ - --parallel \ - --build-cache \ - --configuration-cache \ - --continue \ - --quiet \ - -Dorg.gradle.workers.max=4 \ - -Dorg.gradle.jvmargs="-Xmx3g -XX:MaxMetaspaceSize=768m" + if [[ -z "$test_tasks" ]]; then + echo "No test tasks found for any modules in this group" + echo "Running compilation and check tasks instead..." + + compile_tasks="" + for module in $modules; do + module_path=":$module" + if [[ "$module" != *":"* ]]; then + module_path=":$module" + fi + compile_tasks="$compile_tasks $module_path:compileKotlin $module_path:compileTestKotlin" + done + + ./gradlew $compile_tasks \ + --no-daemon \ + --parallel \ + --build-cache \ + --configuration-cache \ + --continue \ + --info \ + -Dorg.gradle.workers.max=3 \ + -Dorg.gradle.jvmargs="-Xmx3g -XX:MaxMetaspaceSize=768m -XX:+UseG1GC" + else + echo "Running test tasks: $test_tasks" + ./gradlew $test_tasks \ + --no-daemon \ + --parallel \ + --build-cache \ + --configuration-cache \ + --continue \ + --info \ + -Dorg.gradle.workers.max=3 \ + -Dorg.gradle.jvmargs="-Xmx3g -XX:MaxMetaspaceSize=768m -XX:+UseG1GC" + fi env: - # 🐳 TestContainers 优化配置 + # TestContainers 配置 TESTCONTAINERS_RYUK_DISABLED: false - TESTCONTAINERS_CHECKS_DISABLE: false TESTCONTAINERS_REUSE_ENABLE: true - TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX: "" - TESTCONTAINERS_REUSE_HASH_LABELS: true - # ⏱️ TestContainers 超时和启动配置 - 优化启动时间 - TESTCONTAINERS_PULL_PAUSE_TIMEOUT: 20 - TESTCONTAINERS_STARTUP_TIMEOUT: 90 - TESTCONTAINERS_CONNECT_TIMEOUT: 30 - # 🚀 Docker 性能优化 - DOCKER_HOST: unix:///var/run/docker.sock - TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: /var/run/docker.sock - TESTCONTAINERS_HOST_OVERRIDE: localhost - DOCKER_BUILDKIT: 1 - BUILDKIT_PROGRESS: plain - # 🎯 JVM 性能调优 - 针对测试环境优化 + TESTCONTAINERS_STARTUP_TIMEOUT: 120 + TESTCONTAINERS_CONNECT_TIMEOUT: 60 + # Gradle 和 JVM 配置 GRADLE_OPTS: "${{ env.GRADLE_OPTS }}" JAVA_OPTS: "${{ env.JVM_OPTS }}" - # 🔧 CI 环境配置 CI: true - GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: false - # 📊 测试并行配置 + # 并行测试配置 JUNIT_PLATFORM_EXECUTION_PARALLEL_ENABLED: true JUNIT_PLATFORM_EXECUTION_PARALLEL_MODE_DEFAULT: concurrent - name: Collect test diagnostics if: failure() run: | - echo "🔍 收集测试诊断信息..." - - # 收集 Gradle 构建日志 find . -name "*.log" -type f -exec echo "=== {} ===" \; -exec cat {} \; || true - # 收集容器日志 - if [[ "${{ matrix.containers }}" != "none" ]]; then - echo "🐳 收集容器日志..." - docker ps -a || true - docker logs $(docker ps -aq --filter "label=org.testcontainers=true") || true + if [[ "${{ matrix.testcontainers }}" == "true" ]]; then + echo "=== TestContainers Status ===" + docker ps -a --filter "label=org.testcontainers=true" || true + echo "=== TestContainers Logs ===" + for container in $(docker ps -aq --filter "label=org.testcontainers=true" 2>/dev/null || true); do + echo "--- Container $container ---" + docker logs "$container" --tail 50 2>/dev/null || echo "No logs available" + done fi - # JVM 堆转储和线程信息 if pgrep -f "org.gradle.launcher.daemon.bootstrap.GradleDaemon" > /dev/null; then - echo "👍 收集 JVM 诊断信息..." jps -v || true fi - # 系统资源使用 - echo "📈 系统资源使用:" free -h || true df -h || true - - name: Upload test results and diagnostics + - name: Upload test results uses: actions/upload-artifact@v4 if: always() with: @@ -323,38 +332,18 @@ jobs: **/*.log retention-days: 5 - - name: 🧼 Smart cleanup containers - if: always() && matrix.containers != 'none' + - name: Cleanup TestContainers + if: always() && matrix.testcontainers == true run: | - echo "🧼 开始智能清理 Docker 资源..." - - # 显示当前资源使用情况 - echo "📈 当前 Docker 资源使用情况:" - docker system df || true - - # 智能清理:保留重用容器,清理测试容器 - echo "🗑️ 清理测试容器(保留重用容器)..." - docker container prune -f --filter "until=30m" --filter "label!=org.testcontainers.reuse.enable=true" || true - - # 清理悬空镜像(但保留基础镜像) - echo "🖼️ 清理悬空镜像..." - docker image prune -f --filter "dangling=true" || true - - # 清理测试网络 - echo "🌐 清理测试网络..." - docker network prune -f --filter "until=30m" || true - - # 清理临时卷 - echo "💾 清理临时卷..." - docker volume prune -f --filter "label!=keep" --filter "label!=org.testcontainers.reuse.enable=true" || true - - # 显示清理后的资源情况 - echo "✨ 清理后 Docker 资源使用情况:" - docker system df || true + echo "Cleaning up TestContainers resources..." + # 清理非复用的 TestContainers + docker container prune -f --filter "label=org.testcontainers=true" --filter "label!=org.testcontainers.reuse.enable=true" || true + docker network prune -f --filter "label=org.testcontainers=true" || true + docker volume prune -f --filter "label=org.testcontainers=true" --filter "label!=org.testcontainers.reuse.enable=true" || true + echo "TestContainers cleanup completed" - # 📊 测试结果汇总 test-results: - name: "📊 Test Results Summary" + name: Test Results Summary needs: [ quick-check, test-matrix ] runs-on: ubuntu-latest if: always() @@ -366,73 +355,74 @@ jobs: path: test-results pattern: test-results-* - - name: Generate comprehensive test summary + - name: Generate test summary run: | - echo "# 🧪 测试结果详细报告" >> $GITHUB_STEP_SUMMARY + echo "# Test Results Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**执行时间:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY - echo "**测试环境:** GitHub Actions (ubuntu-latest)" >> $GITHUB_STEP_SUMMARY + echo "**Execution time:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY + echo "**Test environment:** GitHub Actions (ubuntu-latest)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "## 📈 模块组测试状态" >> $GITHUB_STEP_SUMMARY + echo "## Module Group Test Status" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "| 模块组 | 状态 | 容器依赖 | 耗时 |" >> $GITHUB_STEP_SUMMARY - echo "|---------|--------|----------|------|" >> $GITHUB_STEP_SUMMARY + echo "| Module Group | Status | Container Dependencies | Duration |" >> $GITHUB_STEP_SUMMARY + echo "|--------------|--------|------------------------|----------|" >> $GITHUB_STEP_SUMMARY - # 模块组信息 - 更新为新的分组 - declare -A group_containers=( - ["core-fast"]="无" - ["core-build"]="无" - ["rds-light"]="无" - ["rds-heavy"]="Database (PostgreSQL, MySQL, Redis)" - ["business-ai"]="Cache (Redis)" - ["business-oss"]="Cache (Redis, MinIO)" - ["business-misc"]="Cache (Redis)" - ["security"]="无" - ["data-depend"]="无" + declare -A group_testcontainers=( + ["core-foundation"]="None" + ["core-build-tools"]="None" + ["rds-light"]="None" + ["rds-heavy"]="TestContainers (PostgreSQL, MySQL, Redis)" + ["business-ai-pay"]="TestContainers (Redis)" + ["business-oss"]="TestContainers (Redis, MinIO)" + ["business-communication"]="TestContainers (Redis)" + ["security"]="None" + ["data-processing"]="TestContainers (Redis)" + ["platform-integrations"]="None" + ["testing-tools"]="TestContainers (Database)" + ["integration-tests"]="TestContainers (Full Stack)" ) - for group in core-fast core-build rds-light rds-heavy business-ai business-oss business-misc security data-depend; do - containers="${group_containers[$group]}" + for group in core-foundation core-build-tools rds-light rds-heavy business-ai-pay business-oss business-communication security data-processing platform-integrations testing-tools integration-tests; do + testcontainers="${group_testcontainers[$group]}" if [[ "${{ needs.test-matrix.result }}" == "success" ]]; then - echo "| $group | ✅ 通过 | $containers | - |" >> $GITHUB_STEP_SUMMARY + echo "| $group | ✅ Pass | $testcontainers | - |" >> $GITHUB_STEP_SUMMARY else - echo "| $group | ❌ 失败 | $containers | - |" >> $GITHUB_STEP_SUMMARY + echo "| $group | ❌ Failed | $testcontainers | - |" >> $GITHUB_STEP_SUMMARY fi done echo "" >> $GITHUB_STEP_SUMMARY - # 添加失败分析 if [[ "${{ needs.test-matrix.result }}" != "success" ]]; then - echo "## ❌ 失败分析和建议" >> $GITHUB_STEP_SUMMARY + echo "## Failure Analysis" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "🔍 **常见问题排查:**" >> $GITHUB_STEP_SUMMARY + echo "**Common troubleshooting:**" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "1. **TestContainers 启动失败**" >> $GITHUB_STEP_SUMMARY - echo " - 检查 Docker 服务是否正常" >> $GITHUB_STEP_SUMMARY - echo " - 检查网络连接和镜像拉取" >> $GITHUB_STEP_SUMMARY - echo " - 超时配置可能需要调整" >> $GITHUB_STEP_SUMMARY + echo "1. **TestContainers startup failed**" >> $GITHUB_STEP_SUMMARY + echo " - Check Docker service status" >> $GITHUB_STEP_SUMMARY + echo " - Check network connectivity and image pulling" >> $GITHUB_STEP_SUMMARY + echo " - Timeout configuration may need adjustment" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "2. **内存不足 (OOM)**" >> $GITHUB_STEP_SUMMARY - echo " - JVM 堆内存设置:4GB" >> $GITHUB_STEP_SUMMARY - echo " - Metaspace 设置:1.5GB" >> $GITHUB_STEP_SUMMARY - echo " - 并行 worker 限制:6个" >> $GITHUB_STEP_SUMMARY + echo "2. **Out of memory (OOM)**" >> $GITHUB_STEP_SUMMARY + echo " - JVM heap memory setting: 4GB" >> $GITHUB_STEP_SUMMARY + echo " - Metaspace setting: 1.5GB" >> $GITHUB_STEP_SUMMARY + echo " - Parallel worker limit: 6" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "3. **测试依赖冲突**" >> $GITHUB_STEP_SUMMARY - echo " - 检查并行测试中的端口冲突" >> $GITHUB_STEP_SUMMARY - echo " - 验证数据库连接池配置" >> $GITHUB_STEP_SUMMARY + echo "3. **Test dependency conflicts**" >> $GITHUB_STEP_SUMMARY + echo " - Check port conflicts in parallel tests" >> $GITHUB_STEP_SUMMARY + echo " - Verify database connection pool configuration" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY fi - name: Check overall status run: | if [[ "${{ needs.quick-check.result }}" != "success" ]]; then - echo "❌ Quick check failed" + echo "Quick check failed" exit 1 fi if [[ "${{ needs.test-matrix.result }}" != "success" ]]; then - echo "❌ Test matrix failed" + echo "Test matrix failed" exit 1 fi - echo "✅ All checks passed" + echo "All checks passed" \ No newline at end of file diff --git a/.github/workflows/maven-central-publish.yaml b/.github/workflows/maven-central-publish.yaml index 3cf448a93..d14361751 100644 --- a/.github/workflows/maven-central-publish.yaml +++ b/.github/workflows/maven-central-publish.yaml @@ -3,7 +3,7 @@ name: Publish to Maven Central on: push: branches: [ main ] - tags: [ '🚀*' ] + tags: [ 'v*' ] release: types: [ published ] workflow_dispatch: @@ -13,19 +13,18 @@ on: required: true type: string dry_run: - description: '是否执行试运行(不实际发布)' + description: 'Execute dry run (no actual publish)' type: boolean default: false force_publish: - description: '强制发布(忽略 Maven Central 版本存在性检查)' + description: 'Force publish (ignore Maven Central version existence check)' type: boolean default: false skip_tests: - description: '跳过测试(仅用于紧急发布)' + description: 'Skip tests (for emergency releases only)' type: boolean default: false -# 并发控制:防止同时触发多个发布任务 concurrency: group: maven-publish-${{ github.ref }} cancel-in-progress: false @@ -35,15 +34,16 @@ env: JVM_OPTS: "-Xmx4g -XX:MaxMetaspaceSize=1536m -XX:+UseG1GC -XX:G1HeapRegionSize=16m" jobs: - # 🧪 发布前验证 pre-publish-validation: - name: "🧪 Pre-publish Validation & Maven Central Check" + name: Pre-publish Validation runs-on: ubuntu-latest timeout-minutes: 30 outputs: version: ${{ steps.version-info.outputs.version }} is-snapshot: ${{ steps.version-info.outputs.is-snapshot }} should-publish: ${{ steps.version-info.outputs['should-publish'] }} + java-version: ${{ steps.libs-versions.outputs.java-version }} + gradle-version: ${{ steps.libs-versions.outputs.gradle-version }} steps: - name: Checkout code @@ -51,11 +51,23 @@ jobs: with: fetch-depth: 0 - - name: Set up JDK 17 + - name: Extract versions from libs.versions.toml + id: libs-versions + run: | + JAVA_VERSION=$(sed -n 's/^java\s*=\s*"\(.*\)"/\1/p' gradle/libs.versions.toml | head -n1) + GRADLE_VERSION=$(sed -n 's/^org-gradle\s*=\s*"\(.*\)"/\1/p' gradle/libs.versions.toml | head -n1) + + echo "java-version=$JAVA_VERSION" >> $GITHUB_OUTPUT + echo "gradle-version=$GRADLE_VERSION" >> $GITHUB_OUTPUT + + echo "Extracted Java version: $JAVA_VERSION from libs.versions.toml" + echo "Extracted Gradle version: $GRADLE_VERSION from libs.versions.toml" + + - name: Set up JDK ${{ steps.libs-versions.outputs.java-version }} uses: actions/setup-java@v5.0.0 with: - java-version: '17' - distribution: 'graalvm' + java-version: ${{ steps.libs-versions.outputs.java-version }} + distribution: 'temurin' cache: gradle - name: Cache Gradle wrapper @@ -85,7 +97,7 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: - gradle-version: '9.0.0' + gradle-version: ${{ steps.libs-versions.outputs.gradle-version }} - name: Grant execute permission run: chmod +x gradlew @@ -93,10 +105,8 @@ jobs: - name: Extract version and check Maven Central id: version-info run: | - # 语义化版本验证函数 validate_semver() { local version="$1" - # 支持标准语义化版本格式:x.y.z[-prerelease][+build] if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9\.-]+)?(\+[a-zA-Z0-9\.-]+)?$ ]]; then return 0 else @@ -104,116 +114,104 @@ jobs: fi } - # 确定当前版本 - echo "🔍 确定发布版本..." >> $GITHUB_STEP_SUMMARY + echo "Determining release version..." >> $GITHUB_STEP_SUMMARY if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then version="${{ github.event.inputs.version }}" - echo "📝 手动指定版本: $version" >> $GITHUB_STEP_SUMMARY + echo "Manual version: $version" >> $GITHUB_STEP_SUMMARY elif [[ "${{ github.event_name }}" == "release" ]]; then version="${{ github.event.release.tag_name }}" - version=${version#v} # 移除可能的 'v' 前缀 - echo "🏷️ Release 标签版本: $version" >> $GITHUB_STEP_SUMMARY + version=${version#v} + echo "Release tag version: $version" >> $GITHUB_STEP_SUMMARY elif [[ "${{ github.ref_type }}" == "tag" ]]; then version="${{ github.ref_name }}" - version=${version#v} # 移除可能的 'v' 前缀 - echo "🏷️ 标签触发版本: $version" >> $GITHUB_STEP_SUMMARY + version=${version#v} + echo "Tag triggered version: $version" >> $GITHUB_STEP_SUMMARY else - # push event: parse from libs.versions.toml version=$(sed -n 's/^project\s*=\s*"\(.*\)"/\1/p' gradle/libs.versions.toml | head -n1) - echo "📄 从 libs.versions.toml 读取版本: $version" >> $GITHUB_STEP_SUMMARY + echo "Version from libs.versions.toml: $version" >> $GITHUB_STEP_SUMMARY fi - # 验证版本格式 if ! validate_semver "$version"; then - echo "❌ 版本格式无效: $version" >> $GITHUB_STEP_SUMMARY - echo "版本必须符合语义化版本规范 (x.y.z[-prerelease][+build])" >> $GITHUB_STEP_SUMMARY + echo "Invalid version format: $version" >> $GITHUB_STEP_SUMMARY + echo "Version must follow semantic versioning (x.y.z[-prerelease][+build])" >> $GITHUB_STEP_SUMMARY exit 1 fi echo "version=$version" >> $GITHUB_OUTPUT - echo "✅ 版本格式验证通过: $version" >> $GITHUB_STEP_SUMMARY + echo "Version format validated: $version" >> $GITHUB_STEP_SUMMARY - # 确定快照状态 if [[ "$version" == *"-SNAPSHOT" ]] || [[ "$version" == *"-alpha"* ]] || [[ "$version" == *"-beta"* ]] || [[ "$version" == *"-rc"* ]]; then echo "is-snapshot=true" >> $GITHUB_OUTPUT - echo "📦 预发布版本类型" >> $GITHUB_STEP_SUMMARY + echo "Pre-release version type" >> $GITHUB_STEP_SUMMARY else echo "is-snapshot=false" >> $GITHUB_OUTPUT - echo "🚀 正式发布版本类型" >> $GITHUB_STEP_SUMMARY + echo "Stable release version type" >> $GITHUB_STEP_SUMMARY fi - # 优化的发布决策逻辑:只要 Maven Central 没有该版本就发布 should_publish="false" force_publish="${{ github.event.inputs.force_publish }}" echo "" >> $GITHUB_STEP_SUMMARY - echo "🔍 发布决策分析..." >> $GITHUB_STEP_SUMMARY + echo "Publishing decision analysis..." >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # 强制发布模式 if [[ "$force_publish" == "true" ]]; then should_publish="true" - echo "⚡ **强制发布模式已启用** - 跳过 Maven Central 版本检查" >> $GITHUB_STEP_SUMMARY + echo "Force publish mode enabled - skipping Maven Central version check" >> $GITHUB_STEP_SUMMARY else - # 检查 Maven Central 是否已存在该版本 - echo "🔍 检查 Maven Central 是否存在版本 $version..." >> $GITHUB_STEP_SUMMARY + echo "Checking if version $version exists on Maven Central..." >> $GITHUB_STEP_SUMMARY - # 使用 Maven Central Search API 检查版本是否存在 group="io.github.truenine" search_url="https://search.maven.org/solrsearch/select?q=g:${group}+AND+v:${version}&rows=1&wt=json" - echo " 📡 查询 URL: $search_url" >> $GITHUB_STEP_SUMMARY + echo "Query URL: $search_url" >> $GITHUB_STEP_SUMMARY - # 进行网络请求,设置较短的超时时间 response=$(curl -f -s --max-time 15 "$search_url" 2>/dev/null || echo '{"response":{"numFound":0}}') - # 解析响应,检查是否找到匹配的版本 found=$(echo "$response" | jq -r '.response.numFound' 2>/dev/null || echo "0") if [[ "$found" -gt 0 ]]; then should_publish="false" - echo " ❌ **版本已存在** - Maven Central 上已存在版本 $version,跳过发布" >> $GITHUB_STEP_SUMMARY + echo "Version already exists - Maven Central already has version $version, skipping publish" >> $GITHUB_STEP_SUMMARY else should_publish="true" - echo " ✅ **版本不存在** - Maven Central 上未找到版本 $version,将执行发布" >> $GITHUB_STEP_SUMMARY + echo "Version does not exist - Maven Central does not have version $version, will publish" >> $GITHUB_STEP_SUMMARY fi fi echo "should-publish=$should_publish" >> $GITHUB_OUTPUT - # 最终决策摘要 echo "" >> $GITHUB_STEP_SUMMARY - echo "### 📊 发布决策结果" >> $GITHUB_STEP_SUMMARY + echo "### Publishing Decision Result" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "$should_publish" == "true" ]]; then if [[ "$force_publish" == "true" ]]; then - echo "✅ **发布决策:强制发布** - 将忽略所有检查直接发布" >> $GITHUB_STEP_SUMMARY + echo "Publishing decision: Force publish - will ignore all checks and publish directly" >> $GITHUB_STEP_SUMMARY else - echo "✅ **发布决策:继续发布** - Maven Central 上不存在此版本" >> $GITHUB_STEP_SUMMARY + echo "Publishing decision: Continue publish - this version does not exist on Maven Central" >> $GITHUB_STEP_SUMMARY fi else - echo "⏭️ **发布决策:跳过发布** - Maven Central 上已存在此版本" >> $GITHUB_STEP_SUMMARY + echo "Publishing decision: Skip publish - this version already exists on Maven Central" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY - echo "**触发方式:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY - echo "**检查版本:** $version" >> $GITHUB_STEP_SUMMARY + echo "**Trigger method:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "**Check version:** $version" >> $GITHUB_STEP_SUMMARY - name: Generate pre-publish report run: | - echo "## 🚀 发布准备情况" >> $GITHUB_STEP_SUMMARY + echo "## Publishing Readiness" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "| 检查项 | 状态 |" >> $GITHUB_STEP_SUMMARY - echo "|--------|------|" >> $GITHUB_STEP_SUMMARY - echo "| 版本格式验证 | ✅ 通过 |" >> $GITHUB_STEP_SUMMARY - echo "| Maven Central 版本检查 | ${{ steps.version-info.outputs.should-publish == 'true' && '✅ 未发布' || '❌ 已存在' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Check Item | Status |" >> $GITHUB_STEP_SUMMARY + echo "|------------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Version format validation | Pass |" >> $GITHUB_STEP_SUMMARY + echo "| Maven Central version check | ${{ steps.version-info.outputs.should-publish == 'true' && 'Not published' || 'Already exists' }} |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本:** ${{ steps.version-info.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**类型:** ${{ steps.version-info.outputs.is-snapshot == 'true' && '快照版本' || '正式版本' }}" >> $GITHUB_STEP_SUMMARY - echo "**发布状态:** ${{ steps.version-info.outputs.should-publish == 'true' && '将执行发布' || '跳过发布' }}" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ steps.version-info.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Type:** ${{ steps.version-info.outputs.is-snapshot == 'true' && 'Snapshot version' || 'Stable version' }}" >> $GITHUB_STEP_SUMMARY + echo "**Publishing status:** ${{ steps.version-info.outputs.should-publish == 'true' && 'Will publish' || 'Skip publish' }}" >> $GITHUB_STEP_SUMMARY - # 📦 Maven Central 发布 publish: - name: "📦 Publish to Maven Central" + name: Publish to Maven Central needs: pre-publish-validation if: ${{ needs.pre-publish-validation.outputs.should-publish == 'true' }} runs-on: ubuntu-latest @@ -226,11 +224,11 @@ jobs: with: fetch-depth: 0 - - name: Set up JDK 17 + - name: Set up JDK ${{ needs.pre-publish-validation.outputs.java-version }} uses: actions/setup-java@v5.0.0 with: - java-version: '17' - distribution: 'graalvm' + java-version: ${{ needs.pre-publish-validation.outputs.java-version }} + distribution: 'temurin' cache: gradle - name: Cache Gradle wrapper @@ -258,17 +256,16 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: - gradle-version: '9.0.0' + gradle-version: ${{ needs.pre-publish-validation.outputs.gradle-version }} cache-cleanup: on-success - name: Grant execute permission run: chmod +x gradlew - # 试运行模式 - name: Dry run publication if: github.event.inputs.dry_run == 'true' run: | - echo "🔍 执行发布试运行..." + echo "Executing publication dry run..." ./gradlew publishToMavenLocal \ --no-daemon \ --parallel \ @@ -279,13 +276,11 @@ jobs: GRADLE_OPTS: "${{ env.GRADLE_OPTS }} ${{ env.JVM_OPTS }}" CI: true - # 发布前验证 - name: Pre-publish validation if: github.event.inputs.dry_run != 'true' run: | - echo "🔍 发布前验证..." + echo "Pre-publish validation..." - # 验证必要的凭据 missing_secrets=() [[ -z "${{ secrets.GPG_KEY_ID }}" ]] && missing_secrets+=("GPG_KEY_ID") [[ -z "${{ secrets.GPG_PRIVATE_KEY }}" ]] && missing_secrets+=("GPG_PRIVATE_KEY") @@ -294,19 +289,17 @@ jobs: [[ -z "${{ secrets.GPG_PASSPHRASE }}" ]] && missing_secrets+=("GPG_PASSPHRASE") if [[ ${#missing_secrets[@]} -gt 0 ]]; then - echo "❌ 缺少必要的 Secrets: ${missing_secrets[*]}" >> $GITHUB_STEP_SUMMARY + echo "Missing required secrets: ${missing_secrets[*]}" >> $GITHUB_STEP_SUMMARY exit 1 fi - # 验证网络连接 - echo "🌍 验证网络连接..." + echo "Verifying network connectivity..." curl -f -s --max-time 10 https://oss.sonatype.org/ > /dev/null || { - echo "⚠️ Sonatype 网络连接异常" >> $GITHUB_STEP_SUMMARY + echo "Sonatype network connectivity issue" >> $GITHUB_STEP_SUMMARY } - echo "✅ 验证通过" >> $GITHUB_STEP_SUMMARY + echo "Validation passed" >> $GITHUB_STEP_SUMMARY - # 正式发布(增强版) - name: Publish to Maven Central if: github.event.inputs.dry_run != 'true' uses: nick-fields/retry@v3 @@ -316,34 +309,32 @@ jobs: retry_wait_seconds: 600 shell: bash command: | - echo "🚀 开始发布到 Maven Central (attempt: ${{ github.run_attempt }})..." + echo "Starting publication to Maven Central (attempt: ${{ github.run_attempt }})..." - # 设置错误处理 set -euo pipefail - # 分类错误处理函数 handle_error() { local exit_code=$1 local error_context="$2" - echo "❌ 发布失败 (退出码: $exit_code)" >> $GITHUB_STEP_SUMMARY + echo "Publication failed (exit code: $exit_code)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY case $exit_code in - 1|2) echo "**错误类型:** 构建或配置错误" >> $GITHUB_STEP_SUMMARY ;; - 3|4) echo "**错误类型:** GPG 签名失败" >> $GITHUB_STEP_SUMMARY ;; - 5|6) echo "**错误类型:** Maven Central 连接失败" >> $GITHUB_STEP_SUMMARY ;; - *) echo "**错误类型:** 未知错误" >> $GITHUB_STEP_SUMMARY ;; + 1|2) echo "**Error type:** Build or configuration error" >> $GITHUB_STEP_SUMMARY ;; + 3|4) echo "**Error type:** GPG signing failed" >> $GITHUB_STEP_SUMMARY ;; + 5|6) echo "**Error type:** Maven Central connection failed" >> $GITHUB_STEP_SUMMARY ;; + *) echo "**Error type:** Unknown error" >> $GITHUB_STEP_SUMMARY ;; esac - echo "**错误上下文:** $error_context" >> $GITHUB_STEP_SUMMARY + echo "**Error context:** $error_context" >> $GITHUB_STEP_SUMMARY exit $exit_code } - trap 'handle_error $? "发布执行阶段"' ERR + trap 'handle_error $? "Publication execution phase"' ERR - echo "🔐 验证发布凭据..." >> $GITHUB_STEP_SUMMARY - echo "📦 开始发布流程..." >> $GITHUB_STEP_SUMMARY + echo "Verifying publication credentials..." >> $GITHUB_STEP_SUMMARY + echo "Starting publication process..." >> $GITHUB_STEP_SUMMARY ./gradlew publishToMavenCentral \ --no-daemon \ @@ -358,7 +349,7 @@ jobs: -PmavenCentralPassword="${{ secrets.MAVENCENTRAL_PASSWORD }}" \ -PsigningInMemoryKeyPassword="${{ secrets.GPG_PASSPHRASE }}" - echo "✅ 发布到 Maven Central 成功" >> $GITHUB_STEP_SUMMARY + echo "Successfully published to Maven Central" >> $GITHUB_STEP_SUMMARY env: GRADLE_OPTS: "${{ env.GRADLE_OPTS }} ${{ env.JVM_OPTS }}" MAVENCENTRAL_USERNAME: ${{ secrets.MAVENCENTRAL_USERNAME }} @@ -370,28 +361,27 @@ jobs: - name: Generate publication summary run: | - echo "## 📦 发布完成" >> $GITHUB_STEP_SUMMARY + echo "## Publication Completed" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**状态:** ${{ github.event.inputs.dry_run == 'true' && '试运行完成 🧪' || '正式发布完成 🚀' }}" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Status:** ${{ github.event.inputs.dry_run == 'true' && 'Dry run completed' || 'Official publication completed' }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ github.event.inputs.dry_run }}" != "true" ]]; then - echo "### 📋 发布后检查清单" >> $GITHUB_STEP_SUMMARY + echo "### Post-publication Checklist" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "- [ ] 验证 Maven Central 上的 artifact" >> $GITHUB_STEP_SUMMARY - echo "- [ ] 更新项目文档" >> $GITHUB_STEP_SUMMARY - echo "- [ ] 发布 GitHub Release 说明" >> $GITHUB_STEP_SUMMARY - echo "- [ ] 通知团队成员" >> $GITHUB_STEP_SUMMARY + echo "- [ ] Verify artifacts on Maven Central" >> $GITHUB_STEP_SUMMARY + echo "- [ ] Update project documentation" >> $GITHUB_STEP_SUMMARY + echo "- [ ] Publish GitHub Release notes" >> $GITHUB_STEP_SUMMARY + echo "- [ ] Notify team members" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**Maven Central 链接:** https://search.maven.org/search?q=g:io.github.truenine" >> $GITHUB_STEP_SUMMARY + echo "**Maven Central Link:** https://search.maven.org/search?q=g:io.github.truenine" >> $GITHUB_STEP_SUMMARY else - echo "✅ 试运行成功,所有模块都已正确构建和签名!" >> $GITHUB_STEP_SUMMARY + echo "Dry run successful, all modules built and signed correctly!" >> $GITHUB_STEP_SUMMARY fi - # 🏷️ GitHub Release 创建 create-github-release: - name: "🏷️ Create GitHub Release" + name: Create GitHub Release needs: [ pre-publish-validation, publish ] if: github.event.inputs.dry_run != 'true' && needs.pre-publish-validation.outputs.is-snapshot == 'false' runs-on: ubuntu-latest @@ -410,11 +400,10 @@ jobs: run: | version="${{ needs.pre-publish-validation.outputs.version }}" - # 生成发布说明 cat > release_notes.md << 'EOF' - ## 🚀 Release ${{ needs.pre-publish-validation.outputs.version }} + ## Release ${{ needs.pre-publish-validation.outputs.version }} - ### 📦 Maven Central Artifacts + ### Maven Central Artifacts This release is available on Maven Central Repository: @@ -430,7 +419,7 @@ jobs: ``` - ### 🔗 Links + ### Links - [Maven Central Search](https://search.maven.org/search?q=g:io.github.truenine%20AND%20v:${{ needs.pre-publish-validation.outputs.version }}) - [Project Documentation](https://github.com/TrueNine/compose-server) @@ -458,14 +447,13 @@ jobs: - name: Update release summary run: | - echo "## 🏷️ GitHub Release 创建完成" >> $GITHUB_STEP_SUMMARY + echo "## GitHub Release Created" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本标签:** v${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**Release 链接:** https://github.com/TrueNine/compose-server/releases/tag/v${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Version tag:** v${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Release link:** https://github.com/TrueNine/compose-server/releases/tag/v${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY - # 📋 发布后验证 post-publish-verification: - name: "📋 Post-publish Verification" + name: Post-publish Verification needs: [ pre-publish-validation, publish, create-github-release ] if: github.event.inputs.dry_run != 'true' && always() && needs.publish.result == 'success' runs-on: ubuntu-latest @@ -474,42 +462,40 @@ jobs: steps: - name: Skip verification (save time) run: | - echo "⏭️ 跳过 Maven Central 同步验证以节省时间" - echo "📝 发布已完成,Maven Central 同步通常需要几小时" + echo "Skipping Maven Central sync verification to save time" + echo "Publication completed, Maven Central sync usually takes several hours" - name: Generate verification report run: | - echo "## 🔍 发布验证报告" >> $GITHUB_STEP_SUMMARY + echo "## Publication Verification Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "### 📊 发布状态" >> $GITHUB_STEP_SUMMARY + echo "### Publication Status" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "- ✅ 发布任务已完成" >> $GITHUB_STEP_SUMMARY - echo "- ⏳ Maven Central 同步可能需要几小时" >> $GITHUB_STEP_SUMMARY - echo "- 🔍 建议在 4-6 小时后手动验证可用性" >> $GITHUB_STEP_SUMMARY + echo "- Publication task completed" >> $GITHUB_STEP_SUMMARY + echo "- Maven Central sync may take several hours" >> $GITHUB_STEP_SUMMARY + echo "- Recommend manual verification in 4-6 hours" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "### 🔗 相关链接" >> $GITHUB_STEP_SUMMARY + echo "### Related Links" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "- [Maven Central 搜索](https://search.maven.org/search?q=g:io.github.truenine)" >> $GITHUB_STEP_SUMMARY + echo "- [Maven Central Search](https://search.maven.org/search?q=g:io.github.truenine)" >> $GITHUB_STEP_SUMMARY echo "- [Sonatype Repository](https://oss.sonatype.org/)" >> $GITHUB_STEP_SUMMARY - # 检查 GitHub Release 状态 if [[ "${{ needs.create-github-release.result }}" == "success" ]]; then echo "- [GitHub Release](https://github.com/TrueNine/compose-server/releases/tag/v${{ needs.pre-publish-validation.outputs.version }})" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "✅ **GitHub Release 创建成功**" >> $GITHUB_STEP_SUMMARY + echo "**GitHub Release created successfully**" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.create-github-release.result }}" == "skipped" ]]; then echo "" >> $GITHUB_STEP_SUMMARY - echo "⏭️ **GitHub Release 已跳过**(预发布版本)" >> $GITHUB_STEP_SUMMARY + echo "**GitHub Release skipped** (pre-release version)" >> $GITHUB_STEP_SUMMARY else echo "" >> $GITHUB_STEP_SUMMARY - echo "⚠️ **GitHub Release 创建失败**,请手动创建" >> $GITHUB_STEP_SUMMARY + echo "**GitHub Release creation failed**, please create manually" >> $GITHUB_STEP_SUMMARY fi - # 🚨 失败处理 failure-handler: - name: "🚨 Handle Failure" + name: Handle Failure needs: [ pre-publish-validation, publish, create-github-release, post-publish-verification ] if: always() && (needs.publish.result == 'failure' || needs.create-github-release.result == 'failure') runs-on: ubuntu-latest @@ -518,50 +504,49 @@ jobs: steps: - name: Generate failure report run: | - echo "## ❌ 发布失败报告" >> $GITHUB_STEP_SUMMARY + echo "## Publication Failure Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**触发事件:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY - echo "**失败时间:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Trigger event:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "**Failure time:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "### 🔍 失败状态分析" >> $GITHUB_STEP_SUMMARY + echo "### Failure Status Analysis" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ needs.publish.result }}" == "failure" ]]; then - echo "- ❌ **Maven Central 发布失败**" >> $GITHUB_STEP_SUMMARY - echo " - 检查 GPG 签名配置" >> $GITHUB_STEP_SUMMARY - echo " - 验证 Maven Central 凭据" >> $GITHUB_STEP_SUMMARY - echo " - 确认网络连接正常" >> $GITHUB_STEP_SUMMARY + echo "- Maven Central publication failed" >> $GITHUB_STEP_SUMMARY + echo " - Check GPG signing configuration" >> $GITHUB_STEP_SUMMARY + echo " - Verify Maven Central credentials" >> $GITHUB_STEP_SUMMARY + echo " - Confirm network connectivity" >> $GITHUB_STEP_SUMMARY else - echo "- ✅ Maven Central 发布成功" >> $GITHUB_STEP_SUMMARY + echo "- Maven Central publication succeeded" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.create-github-release.result }}" == "failure" ]]; then - echo "- ❌ **GitHub Release 创建失败**" >> $GITHUB_STEP_SUMMARY - echo " - 检查 GITHUB_TOKEN 权限" >> $GITHUB_STEP_SUMMARY - echo " - 验证标签是否已存在" >> $GITHUB_STEP_SUMMARY - echo " - 确认仓库写入权限" >> $GITHUB_STEP_SUMMARY + echo "- GitHub Release creation failed" >> $GITHUB_STEP_SUMMARY + echo " - Check GITHUB_TOKEN permissions" >> $GITHUB_STEP_SUMMARY + echo " - Verify tag does not already exist" >> $GITHUB_STEP_SUMMARY + echo " - Confirm repository write permissions" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.create-github-release.result }}" == "success" ]]; then - echo "- ✅ GitHub Release 创建成功" >> $GITHUB_STEP_SUMMARY + echo "- GitHub Release creation succeeded" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY - echo "### 🛠️ 建议的修复步骤" >> $GITHUB_STEP_SUMMARY + echo "### Suggested Fix Steps" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "1. 检查上述失败的组件配置" >> $GITHUB_STEP_SUMMARY - echo "2. 验证所有必要的 GitHub Secrets 是否正确配置" >> $GITHUB_STEP_SUMMARY - echo "3. 如果是网络问题,可以重新运行工作流" >> $GITHUB_STEP_SUMMARY - echo "4. 如果问题持续存在,请创建 Issue 报告问题" >> $GITHUB_STEP_SUMMARY + echo "1. Check the configuration of failed components above" >> $GITHUB_STEP_SUMMARY + echo "2. Verify all necessary GitHub Secrets are correctly configured" >> $GITHUB_STEP_SUMMARY + echo "3. If network issue, you can re-run the workflow" >> $GITHUB_STEP_SUMMARY + echo "4. If problems persist, please create an Issue to report the problem" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "### 📞 获取帮助" >> $GITHUB_STEP_SUMMARY + echo "### Get Help" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "- [创建 Issue](https://github.com/TrueNine/compose-server/issues/new)" >> $GITHUB_STEP_SUMMARY - echo "- [查看文档](https://github.com/TrueNine/compose-server/tree/main/docs)" >> $GITHUB_STEP_SUMMARY + echo "- [Create Issue](https://github.com/TrueNine/compose-server/issues/new)" >> $GITHUB_STEP_SUMMARY + echo "- [View Documentation](https://github.com/TrueNine/compose-server/tree/main/docs)" >> $GITHUB_STEP_SUMMARY - # 📊 工作流摘要 workflow-summary: - name: "📊 Workflow Summary" + name: Workflow Summary needs: [ pre-publish-validation, publish, create-github-release, post-publish-verification, failure-handler ] if: always() runs-on: ubuntu-latest @@ -570,45 +555,42 @@ jobs: steps: - name: Generate workflow summary run: | - echo "# 🚀 Maven Central 发布工作流摘要" >> $GITHUB_STEP_SUMMARY + echo "# Maven Central Publication Workflow Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**工作流运行时间:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY - echo "**触发事件:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY - echo "**分支/标签:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY - echo "**提交 SHA:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY + echo "**Workflow execution time:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY + echo "**Trigger event:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "**Branch/Tag:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY + echo "**Commit SHA:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # 任务状态摘要 - echo "## 📋 任务执行状态" >> $GITHUB_STEP_SUMMARY + echo "## Task Execution Status" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "| 任务 | 状态 | 结果 |" >> $GITHUB_STEP_SUMMARY - echo "|------|------|------|" >> $GITHUB_STEP_SUMMARY - echo "| 🧪 发布前验证 | ${{ needs.pre-publish-validation.result }} | ${{ needs.pre-publish-validation.result == 'success' && '✅' || needs.pre-publish-validation.result == 'failure' && '❌' || needs.pre-publish-validation.result == 'skipped' && '⏭️' || '🔄' }} |" >> $GITHUB_STEP_SUMMARY - echo "| 📦 Maven Central 发布 | ${{ needs.publish.result }} | ${{ needs.publish.result == 'success' && '✅' || needs.publish.result == 'failure' && '❌' || needs.publish.result == 'skipped' && '⏭️' || '🔄' }} |" >> $GITHUB_STEP_SUMMARY - echo "| 🏷️ GitHub Release | ${{ needs.create-github-release.result }} | ${{ needs.create-github-release.result == 'success' && '✅' || needs.create-github-release.result == 'failure' && '❌' || needs.create-github-release.result == 'skipped' && '⏭️' || '🔄' }} |" >> $GITHUB_STEP_SUMMARY - echo "| 📋 发布后验证 | ${{ needs.post-publish-verification.result }} | ${{ needs.post-publish-verification.result == 'success' && '✅' || needs.post-publish-verification.result == 'failure' && '❌' || needs.post-publish-verification.result == 'skipped' && '⏭️' || '🔄' }} |" >> $GITHUB_STEP_SUMMARY - - # 版本信息 + echo "| Task | Status | Result |" >> $GITHUB_STEP_SUMMARY + echo "|------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Pre-publish Validation | ${{ needs.pre-publish-validation.result }} | ${{ needs.pre-publish-validation.result == 'success' && 'Pass' || needs.pre-publish-validation.result == 'failure' && 'Failed' || needs.pre-publish-validation.result == 'skipped' && 'Skipped' || 'Running' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Maven Central Publication | ${{ needs.publish.result }} | ${{ needs.publish.result == 'success' && 'Pass' || needs.publish.result == 'failure' && 'Failed' || needs.publish.result == 'skipped' && 'Skipped' || 'Running' }} |" >> $GITHUB_STEP_SUMMARY + echo "| GitHub Release | ${{ needs.create-github-release.result }} | ${{ needs.create-github-release.result == 'success' && 'Pass' || needs.create-github-release.result == 'failure' && 'Failed' || needs.create-github-release.result == 'skipped' && 'Skipped' || 'Running' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Post-publish Verification | ${{ needs.post-publish-verification.result }} | ${{ needs.post-publish-verification.result == 'success' && 'Pass' || needs.post-publish-verification.result == 'failure' && 'Failed' || needs.post-publish-verification.result == 'skipped' && 'Skipped' || 'Running' }} |" >> $GITHUB_STEP_SUMMARY + if [[ "${{ needs.pre-publish-validation.outputs.version }}" != "" ]]; then echo "" >> $GITHUB_STEP_SUMMARY - echo "## 📦 版本信息" >> $GITHUB_STEP_SUMMARY + echo "## Version Information" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**版本号:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "**版本类型:** ${{ needs.pre-publish-validation.outputs.is-snapshot == 'true' && '预发布版本' || '正式版本' }}" >> $GITHUB_STEP_SUMMARY - echo "**发布状态:** ${{ needs.pre-publish-validation.outputs.should-publish == 'true' && '已发布' || '已跳过' }}" >> $GITHUB_STEP_SUMMARY + echo "**Version number:** ${{ needs.pre-publish-validation.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Version type:** ${{ needs.pre-publish-validation.outputs.is-snapshot == 'true' && 'Pre-release version' || 'Stable version' }}" >> $GITHUB_STEP_SUMMARY + echo "**Publication status:** ${{ needs.pre-publish-validation.outputs.should-publish == 'true' && 'Published' || 'Skipped' }}" >> $GITHUB_STEP_SUMMARY fi - # 总体状态 echo "" >> $GITHUB_STEP_SUMMARY - echo "## 🎯 总体状态" >> $GITHUB_STEP_SUMMARY + echo "## Overall Status" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ needs.publish.result }}" == "success" ]]; then - echo "🎉 **发布成功!** 新版本已成功发布到 Maven Central" >> $GITHUB_STEP_SUMMARY + echo "Publication successful! New version has been successfully published to Maven Central" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.publish.result }}" == "skipped" ]]; then - echo "⏭️ **发布已跳过** - Maven Central 上已存在该版本" >> $GITHUB_STEP_SUMMARY + echo "Publication skipped - this version already exists on Maven Central" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.publish.result }}" == "failure" ]]; then - echo "❌ **发布失败** - 请查看错误日志并重试" >> $GITHUB_STEP_SUMMARY + echo "Publication failed - please check error logs and retry" >> $GITHUB_STEP_SUMMARY else - echo "🔄 **工作流进行中** - 请等待完成" >> $GITHUB_STEP_SUMMARY - fi + echo "Workflow in progress - please wait for completion" >> $GITHUB_STEP_SUMMARY + fi \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index ba014395d..79677fb86 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -197,3 +197,4 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - Dependency versions are unified in `gradle/libs.versions.toml` - Use `./gradlew versionCatalogUpdate` to check for dependency updates - Version publishing through Maven Central Repository, naming rule: `io.github.truenine:composeserver-{module-name}` +- 这是一个库项目,类似于springboot \ No newline at end of file diff --git a/README.md b/README.md index 95320954e..fdb4aea76 100644 --- a/README.md +++ b/README.md @@ -1,570 +1,40 @@ # Compose Server -
+Kotlin modular library collection for enterprise server development. -[![Kotlin](https://img.shields.io/badge/Kotlin-2.2.0-7F52FF?style=for-the-badge&logo=kotlin&logoColor=white)](https://kotlinlang.org/) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.4-6DB33F?style=for-the-badge&logo=spring&logoColor=white)](https://spring.io/projects/spring-boot) -[![Jimmer](https://img.shields.io/badge/Jimmer-0.9.105-FF6B35?style=for-the-badge)](https://github.com/babyfish-ct/jimmer) -[![JDK](https://img.shields.io/badge/JDK-24+-orange?style=for-the-badge&logo=openjdk&logoColor=white)](https://openjdk.org/) +## What it is -[![Maven Central](https://img.shields.io/maven-central/v/io.github.truenine/composeserver-shared?style=for-the-badge&logo=apache-maven&logoColor=white&label=Maven%20Central)](https://central.sonatype.com/search?q=g:io.github.truenine) -[![License](https://img.shields.io/badge/License-LGPL%202.1-blue?style=for-the-badge&logo=gnu&logoColor=white)](LICENSE) +30+ modules providing common enterprise functionality: +- Database operations (Jimmer ORM, PostgreSQL, MySQL) +- Object storage (MinIO, Aliyun OSS, Huawei OBS, Volcengine TOS) +- AI integration (LangChain4j) +- Security (Spring Security, OAuth2, crypto) +- Payment (WeChat Pay) +- SMS (Tencent Cloud) +- Caching, data processing, web crawling -[![GitHub Stars](https://img.shields.io/github/stars/TrueNine/compose-server?style=for-the-badge&logo=github&logoColor=white)](https://github.com/TrueNine/compose-server/stargazers) -[![GitHub Issues](https://img.shields.io/github/issues/TrueNine/compose-server?style=for-the-badge&logo=github&logoColor=white)](https://github.com/TrueNine/compose-server/issues) +## Requirements -
+- JDK 17+ +- Kotlin 2.2.0+ +- Spring Boot 3.5.0+ ---- - -
- -## 🚀 Modern Enterprise Kotlin Server Framework - -
- -> **Modular • Enterprise-Grade • Production-Ready** -> A comprehensive modular server-side framework built on modern technology stack - -**Compose Server** is a modern Kotlin enterprise server-side framework library featuring modular architecture design. It provides **30+ specialized modules** -covering AI integration, object storage, database operations, security, payments, messaging, data processing, and monitoring capabilities. All modules are -published to **Maven Central** for selective integration, enabling developers to build production-ready enterprise applications rapidly. - -### 🎯 Target Audience - -- **Enterprise Application Developers** - Building reliable, scalable server-side applications -- **Microservices Architecture Teams** - Seeking unified technology stack and modular solutions -- **AI Application Developers** - Integrating multiple AI capabilities into modern applications -- **Multi-Cloud Storage Users** - Managing different cloud storage services with unified interfaces - -### 💼 Core Use Cases - -- **Enterprise Web Applications** - E-commerce platforms, management systems, business middleware -- **Microservices Architecture** - Distributed systems, cloud-native applications -- **AI-Driven Applications** - Intelligent chatbots, content generation, data analysis -- **Multi-Cloud Storage Systems** - File management, media processing, data backup - ---- - -## ✨ Key Features - -### 🏗️ **Modular Architecture** - -- **30+ Business Modules** - Clear functional boundaries and dependencies -- **Selective Integration** - Choose only needed modules, avoid redundant dependencies -- **Unified Interfaces** - Consistent API design, reduced learning curve - -### 🎯 **Modern Technology Stack** - -- **Kotlin 2.2.0** - Modern JVM language, concise and efficient -- **Spring Boot 3.5.4** - Enterprise framework, production-ready -- **Jimmer 0.9.105** - Modern ORM with strong type safety -- **JDK 24+** - Latest Java features and performance optimizations - -### 🤖 **AI Capabilities** - -- **LangChain4j** - Complete AI application development framework -- **MCP Protocol** - Model Context Protocol support -- **Multi-Model Support** - Compatible with mainstream AI service providers - -### 📦 **Multi-Cloud Storage** - -- **Unified Interface** - Single API for multiple cloud providers -- **MinIO** - Private cloud object storage solution -- **Public Cloud Support** - Aliyun OSS, Huawei OBS, Volcengine TOS - -### 🔐 **Enterprise Security** - -- **Spring Security** - Complete security framework integration -- **OAuth2** - Standardized authentication and authorization -- **Crypto Tools** - Common encryption algorithms encapsulation - -### 💳 **Payment Integration** - -- **WeChat Pay** - Complete payment process encapsulation -- **Unified Interface** - Easy to extend other payment methods - -### 📱 **Messaging & Notifications** - -- **SMS Service** - Tencent Cloud SMS integration -- **Extensible** - Support for multiple notification channels - -### 🗄️ **Data Processing** - -- **CRUD Operations** - Jimmer-based data access layer -- **Database Migration** - Flyway integration with version management -- **PostgreSQL Extensions** - Optimizations for PostgreSQL - ---- - -## 🛠️ Technology Stack - -### 🏗️ Core Framework - -| Technology | Version | Selection Reason | -|-----------------------------------------------------------|---------|----------------------------------------------------------------------------------| -| **[Kotlin](https://kotlinlang.org/)** | 2.2.0 | Modern JVM language, concise and efficient, fully compatible with Java ecosystem | -| **[Spring Boot](https://spring.io/projects/spring-boot)** | 3.5.4 | Enterprise framework, production-ready, rich ecosystem | -| **[Jimmer](https://github.com/babyfish-ct/jimmer)** | 0.9.105 | Modern ORM framework, strong type safety, GraphQL-style queries | -| **[Gradle](https://gradle.org/)** | 9.x | Powerful build tool, supports Kotlin DSL and Version Catalog | - -### 🗄️ Database & Persistence - -| Technology | Version | Use Case | -|-------------------------------------------------------------|---------|-------------------------------------------------------------------------| -| **[PostgreSQL](https://www.postgresql.org/)** | 42.7.7 | Primary database, world's most advanced open source relational database | -| **[Flyway](https://flywaydb.org/)** | 11.10.5 | Database version management and migration tool | -| **[HikariCP](https://github.com/brettwooldridge/HikariCP)** | - | High-performance JDBC connection pool, Spring Boot default | -| **[Caffeine](https://github.com/ben-manes/caffeine)** | 3.2.2 | High-performance local cache library, Guava Cache replacement | - -### 🤖 AI & Machine Learning - -| Technology | Version | Features | -|-------------------------------------------------------------------------|-------------|-----------------------------------------------------------------------| -| **[LangChain4j](https://github.com/langchain4j/langchain4j)** | 1.2.0 | AI application development framework for Java, supports multiple LLMs | -| **[LangChain4j Community](https://github.com/langchain4j/langchain4j)** | 1.1.0-beta7 | Community extensions with more AI service integrations | -| **[MCP Protocol](https://modelcontextprotocol.io/)** | 1.1.0-beta7 | Model Context Protocol, unified AI service interface | - -### 📦 Object Storage - -| Provider | SDK Version | Use Case | -|----------------------------------------------------------------|-------------|-----------------------------------------------------------------------------| -| **[MinIO](https://min.io/)** | 8.5.17 | Private cloud storage, S3-compatible, suitable for self-hosted environments | -| **[Aliyun OSS](https://www.aliyun.com/product/oss)** | 3.18.3 | Public cloud storage, fast access in China | -| **[Huawei OBS](https://www.huaweicloud.com/product/obs.html)** | 3.25.5 | Public cloud storage, enterprise-grade reliability | -| **[Volcengine TOS](https://www.volcengine.com/products/tos)** | 2.9.4 | Public cloud storage, ByteDance cloud service | - -### 🔐 Security & Authentication - -| Technology | Version | Application | -|-------------------------------------------------------------------|---------|----------------------------------------------------------------------| -| **[Spring Security](https://spring.io/projects/spring-security)** | 6.5.2 | Enterprise security framework, authentication and authorization core | -| **[OAuth2](https://oauth.net/2/)** | - | Standardized authentication and authorization protocol | -| **[JWT](https://jwt.io/)** | 4.5.0 | Stateless tokens, suitable for distributed systems | -| **[BouncyCastle](https://www.bouncycastle.org/)** | 1.81 | Cryptographic library, rich cryptographic functions | - -### 💳 Payment & Communication - -| Service | SDK Version | Integration | -|----------------------------------------------------------------|-------------|------------------------------------------------------------------| -| **[WeChat Pay](https://pay.weixin.qq.com/)** | 0.2.17 | Complete payment process encapsulation, multiple payment methods | -| **[Tencent Cloud SMS](https://cloud.tencent.com/product/sms)** | 3.1.1281 | SMS service, verification codes and notification messages | - -### 🔧 Development Tools & Testing - -| Tool | Version | Purpose | -|-------------------------------------------------------|----------|-----------------------------------------------| -| **[JUnit 5](https://junit.org/junit5/)** | 6.0.0-M2 | Modern Java testing framework | -| **[MockK](https://mockk.io/)** | 1.14.5 | Kotlin-specific mocking framework | -| **[TestContainers](https://www.testcontainers.org/)** | 1.21.3 | Integration testing containerization solution | -| **[Spotless](https://github.com/diffplug/spotless)** | 7.2.1 | Code formatting and style checking tool | - ---- - -## 🏗️ Module Architecture - -### 📊 Architecture Overview - -Compose Server adopts a layered modular architecture providing clear functional boundaries and flexible integration: - -``` -🎯 Application Layer - ↓ (selective integration) -🏢 Business Module Layer (30+ modules) - ├── 🤖 AI Services (ai-*) - ├── 📦 Object Storage (oss-*) - ├── 💳 Payment Services (pay-*) - ├── 📱 SMS Services (sms-*) - ├── 🔐 Security (security-*) - ├── 🗄️ Database (rds-*) - ├── 📊 Data Processing (data-*) - ├── 📹 Surveillance (surveillance-*) - └── 🔧 Dependencies (depend-*, ksp-*, psdk-*) - ↓ (all depend on) -🏗️ Infrastructure Layer - ├── 🔧 Shared Foundation (shared) - ├── 📋 Dependency Management (bom) - ├── 🧪 Testing Toolkit (testtoolkit) - ├── ⚡ Caching Abstractions (cacheable) - └── 📚 Version Catalog (version-catalog) -``` - -### 🎨 Module Categories - -#### 🏛️ **Infrastructure Modules** - -| Module | Description | Use Case | -|---------------------|----------------------------------------------------------------|--------------------------------------------------------| -| **shared** | Core foundation library with common utilities and abstractions | Base dependency for all business modules | -| **bom** | Bill of Materials for unified version management | Project dependency and version control | -| **testtoolkit** | Testing toolkit with infrastructure and utilities | Unit testing, integration testing, performance testing | -| **cacheable** | Caching abstraction layer with unified interfaces | Application cache, data cache, session cache | -| **version-catalog** | Gradle version catalog for external projects | External project integration and version sync | - -#### 🤖 **AI Service Modules** - -| Module | Description | Use Case | -|--------------------|--------------------------------------------------|-------------------------------------------------------------| -| **ai-shared** | Common AI service abstractions and interfaces | Unified interface layer for AI capabilities | -| **ai-langchain4j** | LangChain4j integration supporting multiple LLMs | Intelligent dialogue, content generation, document analysis | - -#### 📦 **Object Storage Modules** - -| Module | Description | Use Case | -|------------------------|----------------------------------------------------|-----------------------------------------------------------| -| **oss-shared** | Unified object storage interfaces and abstractions | Unified access layer for storage services | -| **oss-minio** | MinIO private cloud storage implementation | Self-hosted storage, development and testing environments | -| **oss-aliyun-oss** | Aliyun OSS integration | Domestic public cloud storage service | -| **oss-huawei-obs** | Huawei OBS integration | Enterprise-grade public cloud storage | -| **oss-volcengine-tos** | Volcengine TOS integration | ByteDance cloud storage service | - -#### 🗄️ **Database Modules** - -| Module | Description | Use Case | -|-------------------------------------|--------------------------------------------|----------------------------------------| -| **rds-shared** | Common database abstractions and utilities | Data access layer infrastructure | -| **rds-crud** | Jimmer-based CRUD operations encapsulation | Standard database CRUD operations | -| **rds-jimmer-ext-postgres** | PostgreSQL Jimmer extensions | PostgreSQL-specific feature support | -| **rds-flyway-migration-shared** | Common Flyway migration utilities | Database version management foundation | -| **rds-flyway-migration-mysql8** | MySQL 8.x migration support | MySQL database migration | -| **rds-flyway-migration-postgresql** | PostgreSQL migration support | PostgreSQL database migration | - -#### 🔐 **Security Modules** - -| Module | Description | Use Case | -|---------------------|-----------------------------------------------|----------------------------------------------| -| **security-spring** | Spring Security integration and configuration | Web application security, API authentication | -| **security-oauth2** | OAuth2 authentication and authorization | Third-party login, API authorization | -| **security-crypto** | Encryption and decryption utilities | Data encryption, password processing | - -#### 💳 **Payment Modules** - -| Module | Description | Use Case | -|----------------|-------------------------------------|----------------------------------------| -| **pay-shared** | Common payment service abstractions | Unified payment interface definitions | -| **pay-wechat** | WeChat Pay integration | WeChat payments, mini-program payments | - -#### 📱 **Communication Modules** - -| Module | Description | Use Case | -|-----------------|---------------------------------|--------------------------------------| -| **sms-shared** | Common SMS service abstractions | Unified SMS interface | -| **sms-tencent** | Tencent Cloud SMS integration | Verification codes, notification SMS | - -#### 📊 **Data Processing Modules** - -| Module | Description | Use Case | -|------------------|------------------------------------------|-----------------------------------| -| **data-crawler** | Web crawling and data scraping | Data collection, content scraping | -| **data-extract** | Data extraction and transformation tools | Data cleaning, format conversion | - -#### 📹 **Surveillance Modules** - -| Module | Description | Use Case | -|----------------------------|------------------------------------------|--------------------------------------------| -| **surveillance-shared** | Common surveillance service abstractions | Unified surveillance interface definitions | -| **surveillance-hikvision** | Hikvision device integration | Video surveillance, device management | - -#### 🔧 **Dependency & Platform Modules** - -| Module | Description | Use Case | -|------------------------------|---------------------------------|---------------------------------| -| **depend-jackson** | Jackson JSON processing wrapper | JSON serialization optimization | -| **depend-servlet** | Servlet API wrapper | Web application development | -| **depend-springdoc-openapi** | SpringDoc OpenAPI wrapper | API documentation generation | -| **ksp-plugin** | Kotlin Symbol Processing plugin | Code generation and processing | -| **psdk-wxpa** | WeChat Public Account SDK | WeChat ecosystem integration | - ---- - -## 🚀 Quick Start - -### 📋 Requirements - -| Environment | Minimum | Recommended | Notes | -|-----------------|---------|-------------|----------------------------------------------------| -| **JDK** | 24+ | 24+ | Latest Java features and performance optimizations | -| **Kotlin** | 2.2.0+ | 2.2.0+ | Modern JVM language, fully Java compatible | -| **Gradle** | 9.0+ | 9.x | Supports Kotlin DSL and Version Catalog | -| **Spring Boot** | 3.5.0+ | 3.5.4+ | Enterprise framework, production-ready | - -### 📦 Maven Central - -All modules published to Maven Central: [**io.github.truenine**](https://central.sonatype.com/search?q=g:io.github.truenine) - -Current version: **0.0.26** - -### 🔧 Basic Setup - -#### Gradle Kotlin DSL (Recommended) - -```kotlin -// build.gradle.kts -plugins { - kotlin("jvm") version "2.2.0" - kotlin("plugin.spring") version "2.2.0" - id("org.springframework.boot") version "3.5.4" - id("io.spring.dependency-management") version "1.1.7" -} - -repositories { - mavenCentral() -} - -dependencies { - // Core modules (required) - implementation("io.github.truenine:composeserver-shared:0.0.26") - - // Database modules - implementation("io.github.truenine:composeserver-rds-shared:0.0.26") - implementation("io.github.truenine:composeserver-rds-crud:0.0.26") - - // Optional modules (choose as needed) - implementation("io.github.truenine:composeserver-ai-shared:0.0.26") - implementation("io.github.truenine:composeserver-ai-langchain4j:0.0.26") - implementation("io.github.truenine:composeserver-oss-shared:0.0.26") - implementation("io.github.truenine:composeserver-oss-minio:0.0.26") - - // Spring Boot dependencies - implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.babyfish.jimmer:jimmer-spring-boot-starter:0.9.105") - - // Database - runtimeOnly("org.postgresql:postgresql") - - // Testing - testImplementation("io.github.truenine:composeserver-testtoolkit:0.0.26") - testImplementation("org.springframework.boot:spring-boot-starter-test") -} -``` - -#### Version Management with BOM +## Usage ```kotlin dependencies { - // Import BOM for unified version management implementation(platform("io.github.truenine:composeserver-bom:0.0.26")) - - // No need to specify versions, managed by BOM implementation("io.github.truenine:composeserver-shared") - implementation("io.github.truenine:composeserver-rds-shared") - implementation("io.github.truenine:composeserver-rds-crud") -} -``` - -### 📝 Basic Usage Example - -#### 1. Create Spring Boot Application - -```kotlin -@SpringBootApplication -class ComposeServerApplication - -fun main(args: Array) { - runApplication(*args) -} -``` - -#### 2. Configure Database - -```yaml -# application.yml -spring: - datasource: - url: jdbc:postgresql://localhost:5432/compose_server - username: postgres - password: password - driver-class-name: org.postgresql.Driver - -jimmer: - show-sql: true - pretty-sql: true - database-validation-mode: ERROR -``` - -#### 3. Create Entity - -```kotlin -@Entity -@Table(name = "users") -interface User { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long - - val username: String - val email: String - val createdAt: LocalDateTime - val updatedAt: LocalDateTime -} -``` - -#### 4. Create Repository - -```kotlin -@Repository -interface UserRepository : KRepository { - fun findByUsername(username: String): User? - fun existsByUsername(username: String): Boolean -} -``` - -#### 5. Create Service - -```kotlin -@Service -@Transactional(readOnly = true) -class UserService(private val userRepository: UserRepository) { - - fun findById(id: Long): User? = userRepository.findNullable(id) - - @Transactional - fun createUser(username: String, email: String): User { - val user = User { - username = username - email = email - createdAt = LocalDateTime.now() - updatedAt = LocalDateTime.now() - } - return userRepository.save(user) - } -} -``` - -### 🧪 Testing - -```kotlin -@SpringBootTest -@Transactional -class UserServiceTest : IDatabasePostgresqlContainer { - - @Autowired - private lateinit var userService: UserService - - @Test - fun create_user_successfully() { - // Given - val username = "testuser" - val email = "test@example.com" - - // When - val user = userService.createUser(username, email) - - // Then - assertThat(user.username).isEqualTo(username) - assertThat(user.email).isEqualTo(email) - assertThat(user.id).isNotNull() - } + // Add other modules as needed } ``` -### 🚀 Run Application +## Build ```bash -# Start PostgreSQL with Docker -docker run --name postgres \ - -e POSTGRES_DB=compose_server \ - -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=password \ - -p 5432:5432 \ - -d postgres:16 - -# Run application -./gradlew bootRun -``` - ---- - -## 📚 Documentation & Resources - -### 📖 Documentation - -- **[API Documentation](https://javadoc.io/doc/io.github.truenine)** - Complete Javadoc API documentation -- **[GitHub Repository](https://github.com/TrueNine/compose-server)** - Source code, examples, and latest updates -- **[Maven Central](https://central.sonatype.com/search?q=g:io.github.truenine)** - All published modules and versions -- **[Release Notes](https://github.com/TrueNine/compose-server/releases)** - Detailed version changelog - -### 🎯 Module Selection Guide - -**Basic Web Application** - -```kotlin -implementation("io.github.truenine:composeserver-shared") -implementation("io.github.truenine:composeserver-rds-shared") -implementation("io.github.truenine:composeserver-rds-crud") -implementation("io.github.truenine:composeserver-security-spring") -``` - -**AI-Powered Application** - -```kotlin -implementation("io.github.truenine:composeserver-shared") -implementation("io.github.truenine:composeserver-ai-shared") -implementation("io.github.truenine:composeserver-ai-langchain4j") -``` - -**Multi-Cloud Storage Application** - -```kotlin -implementation("io.github.truenine:composeserver-shared") -implementation("io.github.truenine:composeserver-oss-shared") -implementation("io.github.truenine:composeserver-oss-minio") -implementation("io.github.truenine:composeserver-oss-aliyun-oss") -``` - -**E-commerce Payment Application** - -```kotlin -implementation("io.github.truenine:composeserver-shared") -implementation("io.github.truenine:composeserver-pay-shared") -implementation("io.github.truenine:composeserver-pay-wechat") -implementation("io.github.truenine:composeserver-sms-shared") -implementation("io.github.truenine:composeserver-sms-tencent") -``` - ---- - -## 🤝 Contributing - -We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. - -### 🔧 Development Setup - -```bash -# Clone repository -git clone https://github.com/TrueNine/compose-server.git -cd compose-server - -# Build project ./gradlew build - -# Run tests -./gradlew test - -# Format code -./gradlew spotlessApply ``` ---- - -## 📄 License - -This project is licensed under the [LGPL 2.1 License](LICENSE). - ---- - -## 🌟 Support - -- ⭐ Star this repository if you find it helpful -- 🐛 [Report issues](https://github.com/TrueNine/compose-server/issues) -- 💡 [Request features](https://github.com/TrueNine/compose-server/issues/new) -- 📧 Contact: [truenine304@gmail.com](mailto:truenine304@gmail.com) - ---- - -
- -**Built with ❤️ by the Compose Server Team** +## License -
+LGPL 2.1 \ No newline at end of file diff --git a/build-logic/src/main/kotlin/buildlogic.java-conventions.gradle.kts b/build-logic/src/main/kotlin/buildlogic.java-conventions.gradle.kts index 2dc9087e4..bb9a4959e 100644 --- a/build-logic/src/main/kotlin/buildlogic.java-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.java-conventions.gradle.kts @@ -77,11 +77,14 @@ afterEvaluate { dependsOn(configurations.testRuntimeClasspath) - // Configure test output to suppress warnings + // Configure test output for detailed logging testLogging { - showStandardStreams = false + showStandardStreams = true exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - events("passed", "skipped", "failed") + events("passed", "skipped", "failed", "started") + showExceptions = true + showCauses = true + showStackTraces = true } val commonProjectDeps = listOf("testtoolkit", "shared") diff --git a/cacheable/src/main/kotlin/io/github/truenine/composeserver/cacheable/autoconfig/RedisJsonSerializerAutoConfiguration.kt b/cacheable/src/main/kotlin/io/github/truenine/composeserver/cacheable/autoconfig/RedisJsonSerializerAutoConfiguration.kt index 6884655d2..18c1c956d 100644 --- a/cacheable/src/main/kotlin/io/github/truenine/composeserver/cacheable/autoconfig/RedisJsonSerializerAutoConfiguration.kt +++ b/cacheable/src/main/kotlin/io/github/truenine/composeserver/cacheable/autoconfig/RedisJsonSerializerAutoConfiguration.kt @@ -7,6 +7,7 @@ import io.github.truenine.composeserver.depend.jackson.autoconfig.JacksonAutoCon import io.github.truenine.composeserver.logger import java.time.Duration import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.data.redis.cache.RedisCacheConfiguration @@ -24,6 +25,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer * @since 2023-02-20 */ @Configuration +@ConditionalOnBean(RedisConnectionFactory::class) class RedisJsonSerializerAutoConfiguration(@Qualifier(JacksonAutoConfiguration.NON_IGNORE_OBJECT_MAPPER_BEAN_NAME) objectMapper: ObjectMapper) { companion object { @JvmStatic private val log = logger() @@ -41,6 +43,7 @@ class RedisJsonSerializerAutoConfiguration(@Qualifier(JacksonAutoConfiguration.N .disableCachingNullValues() @Bean(name = [ICacheNames.IRedis.HANDLE]) + @ConditionalOnBean(name = [VIRTUAL_THREAD_REDIS_FACTORY_BEAN_NAME]) fun customRedisJsonSerializable(@Qualifier(VIRTUAL_THREAD_REDIS_FACTORY_BEAN_NAME) factory: RedisConnectionFactory): RedisTemplate { log.trace("register redisTemplate factory: {}", factory) val rt = RedisTemplate() @@ -55,6 +58,7 @@ class RedisJsonSerializerAutoConfiguration(@Qualifier(JacksonAutoConfiguration.N } @Bean(name = [ICacheNames.IRedis.CACHE_MANAGER]) + @ConditionalOnBean(name = [VIRTUAL_THREAD_REDIS_FACTORY_BEAN_NAME]) fun cacheManager2h(@Qualifier(VIRTUAL_THREAD_REDIS_FACTORY_BEAN_NAME) factory: RedisConnectionFactory): RedisCacheManager { log.debug("register RedisCacheManager , factory: {}", factory) return asCacheConfig(factory) diff --git a/gradle-plugin/src/test/kotlin/io/github/truenine/composeserver/gradleplugin/dotenv/DotenvLoaderTest.kt b/gradle-plugin/src/test/kotlin/io/github/truenine/composeserver/gradleplugin/dotenv/DotenvLoaderTest.kt index 25f9910d1..d1792dfa8 100644 --- a/gradle-plugin/src/test/kotlin/io/github/truenine/composeserver/gradleplugin/dotenv/DotenvLoaderTest.kt +++ b/gradle-plugin/src/test/kotlin/io/github/truenine/composeserver/gradleplugin/dotenv/DotenvLoaderTest.kt @@ -288,7 +288,7 @@ class DotenvLoaderTest { val envFile = createTempEnvFile( """ - JAVA_OPTS=-Xmx1g + CUSTOM_OPTS=-Xmx1g APP_ENV=production DATABASE_URL=jdbc:postgresql://localhost:5432/mydb """ @@ -304,7 +304,7 @@ class DotenvLoaderTest { val loader = DotenvLoader(project, config) // 验证环境变量已注入 - assertEquals("-Xmx1g", javaExecTask.environment["JAVA_OPTS"]) + assertEquals("-Xmx1g", javaExecTask.environment["CUSTOM_OPTS"]) assertEquals("production", javaExecTask.environment["APP_ENV"]) assertEquals("jdbc:postgresql://localhost:5432/mydb", javaExecTask.environment["DATABASE_URL"]) } diff --git a/testtoolkit/testtoolkit-testcontainers/src/main/kotlin/io/github/truenine/composeserver/testtoolkit/properties/TestcontainersProperties.kt b/testtoolkit/testtoolkit-testcontainers/src/main/kotlin/io/github/truenine/composeserver/testtoolkit/properties/TestcontainersProperties.kt index 637cbad5a..0b65da5ee 100644 --- a/testtoolkit/testtoolkit-testcontainers/src/main/kotlin/io/github/truenine/composeserver/testtoolkit/properties/TestcontainersProperties.kt +++ b/testtoolkit/testtoolkit-testcontainers/src/main/kotlin/io/github/truenine/composeserver/testtoolkit/properties/TestcontainersProperties.kt @@ -111,7 +111,7 @@ data class MinioConfig( /** 是否复用容器,默认复用 */ var reuse: Boolean = true, /** MinIO Docker 镜像 默认使用较新的稳定版本 */ - var image: String = "minio/minio:minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1", + var image: String = "minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1", /** 默认访问密钥 */ var accessKey: String = "minioadmin", diff --git a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesIntegrationTest.kt b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesIntegrationTest.kt index c6aeebbb4..aa87312a5 100644 --- a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesIntegrationTest.kt +++ b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesIntegrationTest.kt @@ -36,10 +36,10 @@ class TestcontainersPropertiesIntegrationTest { @Test fun should_inject_properties_with_defaults() { assertNotNull(testcontainersProperties) - assertEquals("postgres:17.5-alpine3.22", testcontainersProperties.postgres.image) + assertEquals("postgres:17.6-alpine3.22", testcontainersProperties.postgres.image) assertEquals("mysql:8.4.6-oraclelinux9", testcontainersProperties.mysql.image) - assertEquals("redis:8.0.3-alpine3.21", testcontainersProperties.redis.image) - assertEquals("minio/minio:RELEASE.2025-07-23T15-54-02Z", testcontainersProperties.minio.image) + assertEquals("redis/redis-stack:7.2.0-v18", testcontainersProperties.redis.image) + assertEquals("minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1", testcontainersProperties.minio.image) } } diff --git a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesTest.kt b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesTest.kt index 60d7070c0..6c3f8642d 100644 --- a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesTest.kt +++ b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/autoconfig/TestcontainersPropertiesTest.kt @@ -19,7 +19,7 @@ class TestcontainersPropertiesTest { fun should_have_correct_default_postgres_config() { val properties = TestcontainersProperties() - assertEquals("postgres:17.5-alpine3.22", properties.postgres.image) + assertEquals("postgres:17.6-alpine3.22", properties.postgres.image) assertEquals("testdb", properties.postgres.databaseName) assertEquals("test", properties.postgres.username) assertEquals("test", properties.postgres.password) @@ -40,14 +40,14 @@ class TestcontainersPropertiesTest { fun should_have_correct_default_redis_config() { val properties = TestcontainersProperties() - assertEquals("redis:8.0.3-alpine3.21", properties.redis.image) + assertEquals("redis/redis-stack:7.2.0-v18", properties.redis.image) } @Test fun should_have_correct_default_minio_config() { val properties = TestcontainersProperties() - assertEquals("minio/minio:RELEASE.2025-07-23T15-54-02Z", properties.minio.image) + assertEquals("minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1", properties.minio.image) assertEquals("minioadmin", properties.minio.accessKey) assertEquals("minioadmin", properties.minio.secretKey) } diff --git a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/testcontainers/TestcontainersConfigurationHolderTest.kt b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/testcontainers/TestcontainersConfigurationHolderTest.kt index b5fd1f813..f3ca7a953 100644 --- a/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/testcontainers/TestcontainersConfigurationHolderTest.kt +++ b/testtoolkit/testtoolkit-testcontainers/src/test/kotlin/io/github/truenine/composeserver/testtoolkit/testcontainers/TestcontainersConfigurationHolderTest.kt @@ -29,9 +29,9 @@ class TestcontainersConfigurationHolderTest { assertNotNull(properties.minio, "MinIO 配置不应为 null") // 验证默认配置值 - assertEquals("postgres:17.5-alpine3.22", properties.postgres.image, "PostgreSQL 默认镜像应该正确") - assertEquals("redis:8.0.3-alpine3.21", properties.redis.image, "Redis 默认镜像应该正确") - assertEquals("minio/minio:RELEASE.2025-07-23T15-54-02Z", properties.minio.image, "MinIO 默认镜像应该正确") + assertEquals("postgres:17.6-alpine3.22", properties.postgres.image, "PostgreSQL 默认镜像应该正确") + assertEquals("redis/redis-stack:7.2.0-v18", properties.redis.image, "Redis 默认镜像应该正确") + assertEquals("minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1", properties.minio.image, "MinIO 默认镜像应该正确") // 验证配置的完整性 assertTrue(properties.postgres.image.isNotEmpty(), "PostgreSQL 镜像名不应为空") @@ -56,7 +56,7 @@ class TestcontainersConfigurationHolderTest { // 验证在Bean不存在时返回默认配置 assertNotNull(properties, "属性对象不应为 null") - assertEquals("postgres:17.5-alpine3.22", properties.postgres.image, "PostgreSQL 默认镜像应该正确") + assertEquals("postgres:17.6-alpine3.22", properties.postgres.image, "PostgreSQL 默认镜像应该正确") // 验证所有默认配置都可用 assertNotNull(properties.postgres, "PostgreSQL 配置不应为 null")