Skip to content

CI/CD

CI/CD #41

Workflow file for this run

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/*