CI/CD #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [ "main" ] | |
| pull_request: | |
| branches: [ "main" ] | |
| # ─────────────────────────────────────────────────────── | |
| # Job 1 — 编译 + 单元测试 + Go 编译检查 | |
| # ─────────────────────────────────────────────────────── | |
| jobs: | |
| build-and-test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # ── Java 环境 ── | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| cache: maven | |
| - name: Maven Build & Unit Tests | |
| run: mvn -B -ntp clean test | |
| - name: Upload Surefire Reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: surefire-reports | |
| path: | | |
| **/target/surefire-reports/*.txt | |
| **/target/surefire-reports/*.xml | |
| # ── Go 编译检查 ── | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go_client/go.mod | |
| cache-dependency-path: go_client/go.sum | |
| - name: Go Client Build Check | |
| working-directory: go_client | |
| run: | | |
| go mod download | |
| go test ./... | |
| go build -o /dev/null main.go | |
| # ─────────────────────────────────────────────────────── | |
| # Job 2 — 集成测试 (Nacos + Java Provider + 三端客户端) | |
| # ─────────────────────────────────────────────────────── | |
| integration-test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| needs: build-and-test | |
| services: | |
| nacos: | |
| image: nacos/nacos-server:v2.3.1-slim | |
| env: | |
| MODE: standalone | |
| NACOS_AUTH_ENABLE: "false" | |
| JVM_XMS: 256m | |
| JVM_XMX: 256m | |
| JVM_XMN: 128m | |
| ports: | |
| - 8848:8848 | |
| - 9848:9848 | |
| options: >- | |
| --health-cmd "curl -sf http://localhost:8848/nacos/v1/console/health/readiness || exit 1" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| --health-start-period 30s | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # ── 设置工具链 ── | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| cache: maven | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.x' | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go_client/go.mod | |
| cache-dependency-path: go_client/go.sum | |
| - name: Install Python gRPC Dependencies | |
| run: pip install grpcio grpcio-tools protobuf | |
| # ── 构建 JAR 包 ── | |
| - name: Build Jars (skip tests) | |
| run: mvn -B -ntp -DskipTests clean package | |
| # ── 确认 Nacos 就绪 ── | |
| - name: Wait For Nacos | |
| run: | | |
| echo "=== Nacos 容器状态 ===" | |
| docker ps --filter "name=nacos" --format "table {{.ID}}\t{{.Status}}\t{{.Ports}}" | |
| echo "等待 HTTP 端口 8848..." | |
| timeout 120s bash -c 'until echo > /dev/tcp/localhost/8848; do sleep 1; done' | |
| echo "等待 gRPC 端口 9848..." | |
| timeout 120s bash -c 'until echo > /dev/tcp/localhost/9848; do sleep 1; done' | |
| echo "验证 Nacos Readiness API..." | |
| timeout 60s bash -c 'until curl -sf http://localhost:8848/nacos/v1/console/health/readiness > /dev/null; do sleep 2; done' | |
| echo "✅ Nacos 已就绪" | |
| # ── 启动 RPC Provider ── | |
| - name: Start RPC Provider | |
| run: | | |
| # 构建 classpath | |
| CP="rpc-provider/target/rpc-provider-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-transport-netty/target/rpc-transport-netty-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-core/target/rpc-core-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-common/target/rpc-common-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-api/target/rpc-api-1.0-SNAPSHOT.jar" | |
| CP="$CP:$(mvn -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout -pl rpc-provider -am)" | |
| nohup java \ | |
| -Dlogback.configurationFile=rpc-core/src/main/resources/logback.xml \ | |
| -Drpc.protocol=grpc \ | |
| -cp "$CP" \ | |
| com.xiaoyu.rpc.provider.ProviderApp > server.log 2>&1 & | |
| echo "等待 Provider 端口 8080..." | |
| timeout 60s bash -c 'until echo > /dev/tcp/localhost/8080; do sleep 1; done' | |
| echo "✅ Provider 已启动" | |
| head -20 server.log | |
| # ── 等待服务注册完成 ── | |
| - name: Wait For Service Registration | |
| run: | | |
| echo "等待 HelloService 注册到 Nacos..." | |
| if timeout 60s bash -c 'until grep -q "Service registered: com.xiaoyu.rpc.api.HelloService" server.log; do sleep 1; done'; then | |
| echo "✅ HelloService 注册成功" | |
| else | |
| echo "❌ 注册超时,最近日志:" | |
| tail -100 server.log | |
| exit 1 | |
| fi | |
| # ── 并行运行三端客户端 ── | |
| - name: Run Multi-Client Integration Tests | |
| run: | | |
| mkdir -p .ci-results | |
| # --- Java 客户端 --- | |
| run_java() { | |
| CP="rpc-consumer/target/rpc-consumer-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-transport-netty/target/rpc-transport-netty-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-core/target/rpc-core-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-common/target/rpc-common-1.0-SNAPSHOT.jar" | |
| CP="$CP:rpc-api/target/rpc-api-1.0-SNAPSHOT.jar" | |
| CP="$CP:$(mvn -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout -pl rpc-consumer -am)" | |
| echo "[Java] 开始运行..." | |
| if timeout 120s java \ | |
| -Dlogback.configurationFile=rpc-core/src/main/resources/logback.xml \ | |
| -Drpc.protocol=grpc -Drpc.serializer=protobuf \ | |
| -cp "$CP" com.xiaoyu.rpc.consumer.ConsumerApp | tee java-client.log \ | |
| && grep -q "Result1:" java-client.log \ | |
| && grep -q "Result2:" java-client.log; then | |
| echo "PASS" > .ci-results/java | |
| else | |
| echo "[Java] ❌ 失败" | |
| echo "FAIL" > .ci-results/java | |
| fi | |
| } | |
| # --- Python 客户端 --- | |
| run_python() { | |
| echo "[Python] 开始运行..." | |
| if timeout 120s bash -c 'cd python_client && python client.py' | tee python-client.log \ | |
| && grep -q "Message: Success" python-client.log; then | |
| echo "PASS" > .ci-results/python | |
| else | |
| echo "[Python] ❌ 失败" | |
| echo "FAIL" > .ci-results/python | |
| fi | |
| } | |
| # --- Go 客户端 --- | |
| run_go() { | |
| echo "[Go] 开始运行..." | |
| if timeout 120s bash -c 'cd go_client && go run main.go' | tee go-client.log \ | |
| && grep -q "Message: Success" go-client.log; then | |
| echo "PASS" > .ci-results/go | |
| else | |
| echo "[Go] ❌ 失败" | |
| echo "FAIL" > .ci-results/go | |
| fi | |
| } | |
| # 并行启动三个客户端 | |
| run_java & | |
| run_python & | |
| run_go & | |
| wait | |
| # ── 聚合结果 ── | |
| - name: Check Results | |
| run: | | |
| JAVA=$(cat .ci-results/java 2>/dev/null || echo "FAIL") | |
| PY=$(cat .ci-results/python 2>/dev/null || echo "FAIL") | |
| GO=$(cat .ci-results/go 2>/dev/null || echo "FAIL") | |
| echo "╔══════════════════════════════════╗" | |
| echo "║ 集成测试结果 ║" | |
| echo "╠══════════════════════════════════╣" | |
| printf "║ Java : %-22s║\n" "$JAVA" | |
| printf "║ Python : %-22s║\n" "$PY" | |
| printf "║ Go : %-22s║\n" "$GO" | |
| echo "╚══════════════════════════════════╝" | |
| if [[ "$JAVA" != "PASS" || "$PY" != "PASS" || "$GO" != "PASS" ]]; then | |
| echo "::error::至少一个客户端测试失败" | |
| exit 1 | |
| fi | |
| echo "✅ 全部通过" | |
| # ── 失败时输出诊断日志 ── | |
| - name: Dump Nacos Logs (on failure) | |
| if: failure() | |
| run: | | |
| echo "=== Nacos 容器日志 (最后 200 行) ===" | |
| docker logs "${{ job.services.nacos.id }}" 2>&1 | tail -200 || true | |
| echo "" | |
| echo "=== Java Provider 日志 ===" | |
| cat server.log 2>/dev/null || echo "(无日志文件)" | |
| - name: Upload CI Logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: integration-logs | |
| path: | | |
| server.log | |
| java-client.log | |
| python-client.log | |
| go-client.log | |
| .ci-results/* |