feat(workflows): add MySQL and PostgreSQL configurations to unit test workflow

- Introduced MySQL and PostgreSQL environment variables in the unit test workflow for better database integration during testing.
- Configured MySQL and PostgreSQL services in the workflow to ensure proper database connectivity and health checks.
- Updated the sandbox-v2 environment file to include database connection details for local testing.

Made-with: Cursor
This commit is contained in:
Max 2026-03-12 20:49:34 +08:00
parent 7a5c573f10
commit c7b36aa3b5
3 changed files with 148 additions and 31 deletions

View file

@ -54,6 +54,21 @@ YAO_CI_SANDBOX_IMAGE=yaoapp/tai-sandbox-test:latest
# -- Tunnel -- # -- Tunnel --
YAO_CI_TUNNEL=true YAO_CI_TUNNEL=true
# ========================================
# Database (MySQL / PostgreSQL / SQLite)
# ========================================
MYSQL_TEST_HOST=127.0.0.1
MYSQL_TEST_PORT=3308
MYSQL_TEST_USER=test
MYSQL_TEST_PASS=123456
PG_TEST_HOST=127.0.0.1
PG_TEST_PORT=5432
PG_TEST_USER=test
PG_TEST_PASS=123456
SQLITE_DB=./app/db/yao.db
# ======================================== # ========================================
# Legacy variable mapping (migrate later) # Legacy variable mapping (migrate later)
# ======================================== # ========================================

View file

@ -33,6 +33,11 @@ env:
YAO_RUNTIME_HEAP_AVAILABLE: 550000000 YAO_RUNTIME_HEAP_AVAILABLE: 550000000
YAO_RUNTIME_PRECOMPILE: true YAO_RUNTIME_PRECOMPILE: true
MYSQL_TEST_HOST: "127.0.0.1"
MYSQL_TEST_PORT: "3308"
MYSQL_TEST_USER: "test"
MYSQL_TEST_PASS: "123456"
REDIS_TEST_HOST: "127.0.0.1" REDIS_TEST_HOST: "127.0.0.1"
REDIS_TEST_PORT: "6379" REDIS_TEST_PORT: "6379"
REDIS_TEST_DB: "2" REDIS_TEST_DB: "2"
@ -42,6 +47,11 @@ env:
MONGO_TEST_USER: "root" MONGO_TEST_USER: "root"
MONGO_TEST_PASS: "123456" MONGO_TEST_PASS: "123456"
PG_TEST_HOST: "127.0.0.1"
PG_TEST_PORT: "5432"
PG_TEST_USER: "test"
PG_TEST_PASS: "123456"
jobs: jobs:
# ============================================================================= # =============================================================================
# Environment Setup & Verification # Environment Setup & Verification
@ -60,6 +70,37 @@ jobs:
MONGO_INITDB_ROOT_PASSWORD: 123456 MONGO_INITDB_ROOT_PASSWORD: 123456
MONGO_INITDB_DATABASE: test MONGO_INITDB_DATABASE: test
mysql:
image: mysql:8.0
ports:
- 3308:3306
env:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: test
MYSQL_PASSWORD: 123456
MYSQL_DATABASE: test
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1"
--health-interval=10s
--health-timeout=5s
--health-retries=5
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
postgres:
image: postgres:14
ports:
- 5432:5432
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: 123456
POSTGRES_DB: test
options: >-
--health-cmd="pg_isready -U test"
--health-interval=10s
--health-timeout=5s
--health-retries=5
strategy: strategy:
matrix: matrix:
go: ["1.25"] go: ["1.25"]
@ -147,10 +188,13 @@ jobs:
--user-id "${YAO_CI_OAUTH_USER_ID}" \ --user-id "${YAO_CI_OAUTH_USER_ID}" \
--team-id "${YAO_CI_OAUTH_TEAM_ID}" \ --team-id "${YAO_CI_OAUTH_TEAM_ID}" \
--scope "${YAO_CI_OAUTH_SCOPE:-tai:tunnel}" \ --scope "${YAO_CI_OAUTH_SCOPE:-tai:tunnel}" \
--ttl "${YAO_CI_OAUTH_TTL:-24h}") --ttl "${YAO_CI_OAUTH_TTL:-24h}" 2>/dev/null | tail -1 | tr -d '[:space:]')
echo -n "{\"client_id\":\"$CID\",\"tai_id\":\"$TID\",\"machine_id\":\"ci-runner\",\"server\":\"http://${YAO_CI_BRIDGE_IP}:${YAO_CI_HTTP_PORT}\",\"yao_grpc_addr\":\"${YAO_CI_BRIDGE_IP}:${YAO_CI_GRPC_PORT}\",\"access_token\":\"$TOKEN\",\"scope\":\"${YAO_CI_OAUTH_SCOPE}\",\"expires_at\":\"2099-01-01T00:00:00Z\",\"registered\":true}" \ local JSON="{\"client_id\":\"$CID\",\"tai_id\":\"$TID\",\"machine_id\":\"ci-runner\",\"server\":\"http://${YAO_CI_BRIDGE_IP}:${YAO_CI_HTTP_PORT}\",\"yao_grpc_addr\":\"${YAO_CI_BRIDGE_IP}:${YAO_CI_GRPC_PORT}\",\"access_token\":\"$TOKEN\",\"scope\":\"${YAO_CI_OAUTH_SCOPE}\",\"expires_at\":\"2099-01-01T00:00:00Z\",\"registered\":true}"
| base64 > "$OUT" echo -n "$JSON" | base64 -w0 > "$OUT"
echo ""
echo "Credentials JSON (debug): $JSON" | head -c 200
echo "..."
echo "Generated credentials for $CID → $OUT" echo "Generated credentials for $CID → $OUT"
} }
@ -263,49 +307,103 @@ jobs:
} }
echo "=== Environment Verification ===" echo "=== Environment Verification ==="
echo ""
echo "--- Yao ---" # ── 1. Service Health ──
echo ""
echo "--- 1. Service Health ---"
echo "[Yao]"
check "Yao HTTP (/.well-known/yao)" curl -sf http://127.0.0.1:5099/.well-known/yao check "Yao HTTP (/.well-known/yao)" curl -sf http://127.0.0.1:5099/.well-known/yao
check "Yao gRPC port" nc -z 127.0.0.1 9099 check "Yao gRPC port" nc -z 127.0.0.1 9099
echo "" echo "[tai-docker]"
echo "--- tai-docker ---"
check "tai-docker HTTP (/healthz)" curl -sf http://127.0.0.1:${YAO_CI_TAI_HTTP_PORT}/healthz check "tai-docker HTTP (/healthz)" curl -sf http://127.0.0.1:${YAO_CI_TAI_HTTP_PORT}/healthz
check "tai-docker gRPC port" nc -z 127.0.0.1 ${YAO_CI_TAI_GRPC_PORT} check "tai-docker gRPC port" nc -z 127.0.0.1 ${YAO_CI_TAI_GRPC_PORT}
echo "" echo "[tai-k8s]"
echo "--- tai-k8s ---"
check "tai-k8s HTTP (/healthz)" curl -sf http://127.0.0.1:8100/healthz check "tai-k8s HTTP (/healthz)" curl -sf http://127.0.0.1:8100/healthz
check "tai-k8s gRPC port" nc -z 127.0.0.1 ${YAO_CI_TAI_K8S_GRPC_PORT} check "tai-k8s gRPC port" nc -z 127.0.0.1 ${YAO_CI_TAI_K8S_GRPC_PORT}
echo "" echo "[K8s (k3d)]"
echo "--- Tai Tunnel Registration ---" check "kubectl get nodes" kubectl --kubeconfig=$RUNNER_TEMP/kubeconfig-tai.yml get nodes
sleep 5
echo "tai-docker tunnel logs:" echo "[Data Stores]"
docker logs tai-docker 2>&1 | grep -iE "tunnel|register|connected" | tail -5 || true MONGO_CID=$(docker ps -qf "ancestor=mongo:6.0" | head -1)
echo "tai-k8s tunnel logs:" check "MongoDB ping" docker exec "$MONGO_CID" mongosh --quiet \
docker logs tai-k8s 2>&1 | grep -iE "tunnel|register|connected" | tail -5 || true -u ${MONGO_TEST_USER} -p ${MONGO_TEST_PASS} --authenticationDatabase admin \
--eval "db.runCommand({ping:1})"
MYSQL_CID=$(docker ps -qf "ancestor=mysql:8.0" | head -1)
check "MySQL ping" docker exec "$MYSQL_CID" mysqladmin ping -h 127.0.0.1 \
-u ${MYSQL_TEST_USER} -p${MYSQL_TEST_PASS}
PG_CID=$(docker ps -qf "ancestor=postgres:14" | head -1)
check "PostgreSQL ping" docker exec "$PG_CID" pg_isready -U ${PG_TEST_USER}
check "Redis ping" docker exec redis redis-cli ping
# ── 2. Network Topology ──
echo ""
echo "--- 2. Network Topology ---"
BRIDGE_IP=${YAO_CI_BRIDGE_IP}
echo " docker0 bridge IP: ${BRIDGE_IP}"
echo "[Runner → Bridge]"
check "Bridge IP exists" ip addr show docker0
check "Bridge IP reachable" ping -c1 -W2 ${BRIDGE_IP}
echo "[Runner → Tai Docker API]"
check "Tai Docker API (tcp://127.0.0.1:${YAO_CI_TAI_DOCKER_PORT})" \
nc -z 127.0.0.1 ${YAO_CI_TAI_DOCKER_PORT}
echo "[Runner → Tai K8s API proxy]"
check "Tai K8s API (127.0.0.1:${YAO_CI_TAI_K8S_PORT})" \
nc -z 127.0.0.1 ${YAO_CI_TAI_K8S_PORT}
echo "[tai-docker → Yao via bridge]"
check "tai-docker→Yao HTTP (bridge)" \
docker exec tai-docker wget -q -O /dev/null --timeout=3 \
http://${BRIDGE_IP}:${YAO_CI_HTTP_PORT}/.well-known/yao
check "tai-docker→Yao gRPC (bridge)" \
docker exec tai-docker nc -z -w3 ${BRIDGE_IP} ${YAO_CI_GRPC_PORT}
echo "[tai-k8s → Yao via bridge]"
check "tai-k8s→Yao HTTP (bridge)" \
docker exec tai-k8s wget -q -O /dev/null --timeout=3 \
http://${BRIDGE_IP}:${YAO_CI_HTTP_PORT}/.well-known/yao
check "tai-k8s→Yao gRPC (bridge)" \
docker exec tai-k8s nc -z -w3 ${BRIDGE_IP} ${YAO_CI_GRPC_PORT}
echo "[tai-k8s → k3d API server]"
K3D_IP=$(docker inspect k3d-tai-test-server-0 2>/dev/null \
| jq -r '.[0].NetworkSettings.Networks["k3d-tai-test"].IPAddress' 2>/dev/null || echo "")
if [ -n "$K3D_IP" ] && [ "$K3D_IP" != "null" ]; then
check "tai-k8s→k3d API (${K3D_IP}:6443)" \
docker exec tai-k8s nc -z -w3 ${K3D_IP} 6443
else
echo " [SKIP] k3d IP not found"
fi
# ── 3. Tai Tunnel Registration ──
echo ""
echo "--- 3. Tai Tunnel Registration ---"
sleep 5
echo "tai-docker tunnel logs:"
docker logs tai-docker 2>&1 | grep -iE "tunnel|register|connect" | tail -5 || true
echo "tai-k8s tunnel logs:"
docker logs tai-k8s 2>&1 | grep -iE "tunnel|register|connect" | tail -5 || true
check "tai-docker tunnel connected" \
bash -c 'docker logs tai-docker 2>&1 | grep -qiE "tunnel.*(connected|registered|established)"'
check "tai-k8s tunnel connected" \
bash -c 'docker logs tai-k8s 2>&1 | grep -qiE "tunnel.*(connected|registered|established)"'
# Check if Tai instances appear registered via Yao
WELL_KNOWN=$(curl -sf http://127.0.0.1:5099/.well-known/yao 2>/dev/null || echo "{}") WELL_KNOWN=$(curl -sf http://127.0.0.1:5099/.well-known/yao 2>/dev/null || echo "{}")
echo "Yao .well-known/yao:" echo "Yao .well-known/yao:"
echo "$WELL_KNOWN" | jq . 2>/dev/null || echo "$WELL_KNOWN" echo "$WELL_KNOWN" | jq . 2>/dev/null || echo "$WELL_KNOWN"
echo ""
echo "--- K8s (k3d) ---"
check "kubectl get nodes" kubectl --kubeconfig=$RUNNER_TEMP/kubeconfig-tai.yml get nodes
echo ""
echo "--- MongoDB ---"
check "MongoDB ping" mongosh --quiet --host 127.0.0.1 --port 27017 \
-u root -p 123456 --authenticationDatabase admin \
--eval "db.runCommand({ping:1})"
echo ""
echo "--- Redis ---"
check "Redis ping" docker exec redis redis-cli ping
echo "" echo ""
echo "==========================================" echo "=========================================="
if [ $FAILED -gt 0 ]; then if [ $FAILED -gt 0 ]; then

View file

@ -35,6 +35,9 @@ func main() {
os.Exit(1) os.Exit(1)
} }
savedStdout := os.Stdout
os.Stdout, _ = os.Open(os.DevNull)
config.Conf = config.LoadFrom(filepath.Join(root, ".env")) config.Conf = config.LoadFrom(filepath.Join(root, ".env"))
config.Conf.Root = root config.Conf.Root = root
@ -42,6 +45,7 @@ func main() {
cfg.Session.IsCLI = true cfg.Session.IsCLI = true
warnings, err := engine.Load(cfg, engine.LoadOption{Action: "run"}) warnings, err := engine.Load(cfg, engine.LoadOption{Action: "run"})
os.Stdout = savedStdout
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "ci-token: engine.Load failed: %v\n", err) fmt.Fprintf(os.Stderr, "ci-token: engine.Load failed: %v\n", err)
os.Exit(1) os.Exit(1)