ci(cpp): job 超时 15→30 分钟——vcpkg 重装+新增测试逼近原预算 #2176
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 - Core | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - timeout-minutes: 3 | |
| uses: actions/checkout@v7 | |
| - timeout-minutes: 5 | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: "go.mod" | |
| - name: Install ripgrep | |
| timeout-minutes: 2 | |
| run: | | |
| sudo apt-get update -qq && sudo apt-get install -y -qq ripgrep | |
| rg --version | |
| - name: Architecture guard | |
| timeout-minutes: 5 | |
| run: bash .github/scripts/architecture_guard.sh | |
| - name: Contracts guard | |
| timeout-minutes: 5 | |
| run: bash .github/scripts/contracts_guard.sh | |
| - name: API response guard | |
| timeout-minutes: 5 | |
| run: bash .github/scripts/api_response_guard.sh | |
| - name: Dashboard vNext guard | |
| timeout-minutes: 5 | |
| run: bash scripts/dashboard_vnext_guard.sh | |
| - name: Dashboard vNext guard regression test | |
| timeout-minutes: 5 | |
| run: bash scripts/dashboard_vnext_guard_test.sh | |
| - name: SDK matrix conformance | |
| timeout-minutes: 5 | |
| run: bash scripts/check-sdk-matrix.sh | |
| - name: Normalize Go toolchain env | |
| timeout-minutes: 2 | |
| shell: bash | |
| run: | | |
| go env -u GOROOT || true | |
| go env -u GOTOOLDIR || true | |
| go env -u GOTOOLCHAIN || true | |
| echo "GOCACHE=$RUNNER_TEMP/go-build-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV" | |
| echo "GOMODCACHE=$RUNNER_TEMP/go-mod-${{ github.run_id }}" >> "$GITHUB_ENV" | |
| go version | |
| go env GOROOT GOTOOLDIR GOVERSION GOOS GOARCH | |
| - name: Install buf | |
| timeout-minutes: 5 | |
| shell: bash | |
| env: | |
| BUF_VERSION: "1.47.2" | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "$RUNNER_TEMP/bin" | |
| curl -sSLf "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/buf-Linux-x86_64" -o "$RUNNER_TEMP/bin/buf" | |
| chmod +x "$RUNNER_TEMP/bin/buf" | |
| echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH" | |
| "$RUNNER_TEMP/bin/buf" --version | |
| - name: Lint proto | |
| timeout-minutes: 5 | |
| run: buf lint proto | |
| - name: Go mod download | |
| timeout-minutes: 5 | |
| run: | | |
| for i in 1 2 3; do | |
| go mod download && exit 0 | |
| echo "go mod download failed (attempt $i/3), retrying in 5s..." | |
| sleep 5 | |
| done | |
| exit 1 | |
| - name: Check gofmt | |
| timeout-minutes: 5 | |
| run: | | |
| mapfile -d '' -t go_files < <(git ls-files -z '*.go' || true) | |
| if [[ ${#go_files[@]} -eq 0 ]]; then | |
| exit 0 | |
| fi | |
| fmt_result=$(gofmt -l "${go_files[@]}") | |
| if [[ -n "$fmt_result" ]]; then | |
| echo "The following files need gofmt:" | |
| echo "$fmt_result" | |
| exit 1 | |
| fi | |
| - name: Vet Go code | |
| timeout-minutes: 5 | |
| run: go vet ./... | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - timeout-minutes: 3 | |
| uses: actions/checkout@v7 | |
| - timeout-minutes: 5 | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: "go.mod" | |
| - name: Normalize Go toolchain env | |
| timeout-minutes: 2 | |
| shell: bash | |
| run: | | |
| go env -u GOROOT || true | |
| go env -u GOTOOLDIR || true | |
| go env -u GOTOOLCHAIN || true | |
| echo "GOCACHE=$RUNNER_TEMP/go-build-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV" | |
| echo "GOMODCACHE=$RUNNER_TEMP/go-mod-${{ github.run_id }}" >> "$GITHUB_ENV" | |
| go version | |
| go env GOROOT GOTOOLDIR GOVERSION GOOS GOARCH | |
| - name: Install govulncheck | |
| timeout-minutes: 5 | |
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Go mod download | |
| timeout-minutes: 5 | |
| run: | | |
| for i in 1 2 3; do | |
| go mod download && exit 0 | |
| echo "go mod download failed (attempt $i/3), retrying in 5s..." | |
| sleep 5 | |
| done | |
| exit 1 | |
| - name: Run govulncheck | |
| timeout-minutes: 10 | |
| run: | | |
| echo "Running Go vulnerability scan..." | |
| ~/go/bin/govulncheck ./... | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - timeout-minutes: 3 | |
| uses: actions/checkout@v7 | |
| - timeout-minutes: 5 | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: "go.mod" | |
| - name: Normalize Go toolchain env | |
| timeout-minutes: 2 | |
| shell: bash | |
| run: | | |
| go env -u GOROOT || true | |
| go env -u GOTOOLDIR || true | |
| go env -u GOTOOLCHAIN || true | |
| echo "GOCACHE=$RUNNER_TEMP/go-build-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV" | |
| echo "GOMODCACHE=$RUNNER_TEMP/go-mod-${{ github.run_id }}" >> "$GITHUB_ENV" | |
| go version | |
| go env GOROOT GOTOOLDIR GOVERSION GOOS GOARCH | |
| # Proto 代码无需本地生成 | |
| - name: Go mod download | |
| timeout-minutes: 5 | |
| run: | | |
| for i in 1 2 3; do | |
| go mod download && exit 0 | |
| echo "go mod download failed (attempt $i/3), retrying in 5s..." | |
| sleep 5 | |
| done | |
| exit 1 | |
| - name: Prepare storage directory | |
| timeout-minutes: 1 | |
| run: mkdir -p data/uploads | |
| - name: Unit tests | |
| timeout-minutes: 10 | |
| env: | |
| DB_DRIVER: sqlite | |
| DATABASE_URL: ":memory:" | |
| STORAGE_DRIVER: file | |
| STORAGE_BASE_DIR: data/uploads | |
| run: | | |
| # Only test internal packages (core business logic) | |
| go test -count=1 -coverprofile=coverage.out -covermode=atomic ./internal/... | |
| - name: Upload coverage to Codecov | |
| timeout-minutes: 3 | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: coverage.out | |
| flags: server | |
| fail_ci_if_error: ${{ github.event_name != 'pull_request' }} | |
| verbose: true | |
| disable_search: true | |
| e2e: | |
| name: E2E Tests | |
| # Restored: uses the SQLite config so no external DB is needed. The earlier | |
| # instability came from booting with configs/server.yaml (mysql/postgres) | |
| # in a CI runner with no database service. | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| needs: [test] | |
| steps: | |
| - timeout-minutes: 3 | |
| uses: actions/checkout@v7 | |
| - timeout-minutes: 5 | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: "go.mod" | |
| - name: Normalize Go toolchain env | |
| timeout-minutes: 2 | |
| shell: bash | |
| run: | | |
| go env -u GOROOT || true | |
| go env -u GOTOOLDIR || true | |
| go env -u GOTOOLCHAIN || true | |
| echo "GOCACHE=$RUNNER_TEMP/go-build-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV" | |
| echo "GOMODCACHE=$RUNNER_TEMP/go-mod-${{ github.run_id }}" >> "$GITHUB_ENV" | |
| go version | |
| go env GOROOT GOTOOLDIR GOVERSION GOOS GOARCH | |
| - name: Setup E2E scripts | |
| timeout-minutes: 1 | |
| run: chmod +x scripts/e2e/*.sh | |
| - name: Start Server (SQLite, no external DB) | |
| timeout-minutes: 15 | |
| run: | | |
| set -euo pipefail | |
| go build -o bin/croupier-server ./cmd/server | |
| # Build the agent registration probe so happy-path.sh can exercise | |
| # the Agent→Server TCP handshake (Register + Heartbeat). Without it, | |
| # the agent TCP step is skipped (./bin/e2e-agent-probe absent). | |
| go build -o bin/e2e-agent-probe ./examples/cmd/e2e-agent-probe | |
| # Function-seed helper: inserts the function metadata row that the | |
| # task-lifecycle E2E's POST /tasks requires (no create API exists). | |
| go build -o bin/e2e-function-seed ./examples/cmd/e2e-function-seed | |
| # Each run owns an isolated directory under RUNNER_TEMP. Never | |
| # delete repository data/ or test-data/: CI may run in a worktree | |
| # containing useful local SQLite fixtures. | |
| E2E_DIR="$RUNNER_TEMP/croupier-e2e-${{ github.run_id }}-${{ github.run_attempt }}" | |
| mkdir -p "$E2E_DIR/uploads" | |
| echo "E2E_DIR=$E2E_DIR" >> "$GITHUB_ENV" | |
| echo "E2E_DSN=$E2E_DIR/croupier.db" >> "$GITHUB_ENV" | |
| # Use the SQLite test config so the server boots without a database | |
| # service. Admin/games are seeded from configs/*.json. Redirect | |
| # output to a log file so failures (panic/migrate errors) are | |
| # visible in the failed step instead of being lost to the background. | |
| : > "$E2E_DIR/server.log" | |
| DB_DRIVER=sqlite \ | |
| DATABASE_URL="$E2E_DIR/croupier.db" \ | |
| STORAGE_DRIVER=file \ | |
| STORAGE_BASE_DIR="$E2E_DIR/uploads" \ | |
| ./bin/croupier-server --config configs/test-sqlite.yaml >> "$E2E_DIR/server.log" 2>&1 & | |
| SERVER_PID=$! | |
| echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV | |
| # Wait for server REST to be ready (deterministic readiness probe). | |
| ready=0 | |
| for i in $(seq 1 60); do | |
| if curl -sf http://localhost:18780/healthz > /dev/null; then | |
| echo "Server is ready (after ${i}s)" | |
| ready=1 | |
| break | |
| fi | |
| # If the server process already exited, it panicked — stop early. | |
| if ! kill -0 "$SERVER_PID" 2>/dev/null; then | |
| echo "::error::server process exited before becoming ready" | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| if [ "$ready" -ne 1 ]; then | |
| echo "::error::server did not become ready within 60s; server log:" | |
| cat "$E2E_DIR/server.log" | |
| exit 1 | |
| fi | |
| - name: Run E2E tests | |
| timeout-minutes: 10 | |
| env: | |
| SERVER_URL: http://localhost:18780 | |
| DSN: ${{ env.E2E_DSN }} | |
| run: | | |
| bash scripts/e2e/happy-path.sh | |
| bash scripts/e2e/task-lifecycle.sh | |
| - name: Cleanup | |
| timeout-minutes: 2 | |
| if: always() | |
| run: | | |
| if [ -n "${SERVER_PID:-}" ]; then | |
| kill "$SERVER_PID" 2>/dev/null || true | |
| fi | |
| migrate-matrix: | |
| name: Migration Matrix (MySQL/Postgres/SQLServer) | |
| # Phase 4 of docs/architecture/database-migration-strategy.md: the | |
| # versioned migration executor must work on all four dialects. SQLite is | |
| # covered by the unit tests in internal/svc/migrations_test.go; this job | |
| # runs the integration-tagged matrix against real MySQL, Postgres and | |
| # SQL Server servers (fresh DB → baseline + catch-up, concurrent first | |
| # boot proving the session lock, idempotent second boot). | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| needs: [test] | |
| services: | |
| mysql: | |
| image: mysql:8.4 | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd "mysqladmin ping -h 127.0.0.1 -proot" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| postgres: | |
| image: postgres:16 | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: postgres | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd "pg_isready -U postgres" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| mssql: | |
| image: mcr.microsoft.com/mssql/server:2022-latest | |
| env: | |
| ACCEPT_EULA: "Y" | |
| MSSQL_SA_PASSWORD: "YourStr0ngPassw0rd" | |
| ports: | |
| - 1433:1433 | |
| options: >- | |
| --health-cmd "/opt/mssql-tools18/bin/sqlcmd -C -No -S 127.0.0.1 -U sa -P 'YourStr0ngPassw0rd' -Q 'SELECT 1'" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 30 | |
| env: | |
| TEST_MYSQL_DSN: "root:root@tcp(127.0.0.1:3306)/" | |
| TEST_POSTGRES_DSN: "postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable" | |
| TEST_SQLSERVER_DSN: "sqlserver://sa:YourStr0ngPassw0rd@127.0.0.1:1433" | |
| steps: | |
| - timeout-minutes: 3 | |
| uses: actions/checkout@v7 | |
| - timeout-minutes: 5 | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: "go.mod" | |
| - name: Normalize Go toolchain env | |
| timeout-minutes: 2 | |
| shell: bash | |
| run: | | |
| go env -u GOROOT || true | |
| go env -u GOTOOLDIR || true | |
| go env -u GOTOOLCHAIN || true | |
| echo "GOCACHE=$RUNNER_TEMP/go-build-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV" | |
| echo "GOMODCACHE=$RUNNER_TEMP/go-mod-${{ github.run_id }}" >> "$GITHUB_ENV" | |
| go version | |
| go env GOROOT GOTOOLDIR GOVERSION GOOS GOARCH | |
| - name: Go mod download | |
| timeout-minutes: 5 | |
| run: | | |
| for i in 1 2 3; do | |
| go mod download && exit 0 | |
| echo "go mod download failed (attempt $i/3), retrying in 5s..." | |
| sleep 5 | |
| done | |
| exit 1 | |
| - name: Migration matrix tests | |
| timeout-minutes: 10 | |
| run: | | |
| go test -tags=integration -count=1 -timeout 8m \ | |
| -run 'TestMigrationMatrix' \ | |
| ./internal/svc/ -v | |
| - name: Validate migration directory (atlas) | |
| # Community-edition atlas: verifies the atlas.sum checksum and file | |
| # ordering of embedded SQL migrations. (Rule-based `migrate lint` is | |
| # Pro-only since atlas v0.38.) | |
| timeout-minutes: 5 | |
| uses: ariga/setup-atlas@v0 | |
| with: | |
| cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN || '' }} | |
| - name: atlas migrate validate | |
| timeout-minutes: 3 | |
| run: | | |
| atlas migrate validate --dir "file://internal/db/migrate/migrations" --dir-format goose |