name: hub check # Builds, type-checks, and tests the Hub TS package under hub/. # The Hub is the Feishu-group collaboration + agent runtime half # (spec/System implementation). This is an INTERNAL gate on the Hub's own # health, like checker-check is for the Rust half. on: push: pull_request: workflow_dispatch: jobs: hub-check: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_USER: paradigm POSTGRES_PASSWORD: paradigm POSTGRES_DB: cph_hub_test ports: - 5432:5432 options: >- --health-cmd "pg_isready -U paradigm -d cph_hub_test" --health-interval 5s --health-timeout 5s --health-retries 20 defaults: run: working-directory: hub steps: - uses: actions/checkout@v5 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: npm cache-dependency-path: hub/package-lock.json - name: Install dependencies run: npm ci - name: Audit production Node dependencies run: npm run audit:production - name: Install Linux sandbox dependency run: sudo apt-get update && sudo apt-get install --yes bubblewrap socat - name: Wait for Postgres run: | node <<'NODE' const net = require("node:net"); const deadline = Date.now() + 60000; function tryConnect() { const socket = net.createConnection({ host: "127.0.0.1", port: 5432 }); socket.once("connect", () => { socket.end(); process.exit(0); }); socket.once("error", () => { socket.destroy(); if (Date.now() > deadline) { console.error("Postgres did not become reachable at 127.0.0.1:5432"); process.exit(1); } setTimeout(tryConnect, 1000); }); } tryConnect(); NODE # Prisma client must be generated before tsc can check imports from # @prisma/client. Stub DATABASE_URL so prisma generate works. - name: Generate Prisma client run: DATABASE_URL="postgresql://stub:stub@127.0.0.1:5432/stub" npx prisma generate --schema prisma/schema.prisma - name: Type-check run: npx tsc -p tsconfig.json --noEmit - name: Build run: npm run build - name: Validate Prisma schema run: DATABASE_URL="postgresql://stub:stub@127.0.0.1:5432/stub" npx prisma validate --schema prisma/schema.prisma - name: Install cph binary run: | cd .. cargo install --path crates/cph-cli --locked - name: Prove real Claude SDK Bash sandbox boundary run: | sudo install -d -o "$(id -u)" -g "$(id -g)" -m 0700 /var/lib/cph-test CPH_SANDBOX_TEST_ROOT=/var/lib/cph-test \ /usr/bin/setpriv --no-new-privs \ npx vitest run test/integration/agent-sandbox-linux.test.ts - name: Run unit tests run: npx vitest run test/unit # Integration tests need PostgreSQL + cph. cph is installed above. # PostgreSQL is set up as a service container below. - name: Run integration tests (mock provider, real prisma + cph) run: | npx prisma migrate deploy --schema prisma/schema.prisma npx vitest run test/integration \ --exclude test/integration/real-model.test.ts \ --exclude test/integration/agent-sandbox-linux.test.ts env: DATABASE_URL: postgresql://paradigm:paradigm@127.0.0.1:5432/cph_hub_test - name: Smoke health endpoint run: | PORT=8878 \ NODE_ENV=production \ DATABASE_URL=postgresql://paradigm:paradigm@127.0.0.1:5432/cph_hub_test \ ANTHROPIC_AUTH_TOKEN=smoke \ FEISHU_APP_ID=cli_smoke \ FEISHU_APP_SECRET=smoke_secret \ FEISHU_BOT_OPEN_ID=ou_smoke \ HOST=127.0.0.1 \ HUB_PROJECT_WORKSPACE_ROOT=/tmp/cph-hub-smoke-workspaces \ HUB_PUBLIC_BASE_URL=https://hub.example.test \ HUB_SESSION_SECRET=smoke-session-secret-with-at-least-32-bytes \ HUB_FEISHU_LISTENER_ENABLED=false \ npm start & pid=$! trap 'kill "$pid" 2>/dev/null || true' EXIT for attempt in $(seq 1 30); do if curl --fail --silent "http://127.0.0.1:8878/api/healthz" >/dev/null; then exit 0 fi if ! kill -0 "$pid" 2>/dev/null; then echo "hub server exited before health check passed" wait "$pid" exit 1 fi sleep 1 done curl --fail --silent --show-error "http://127.0.0.1:8878/api/healthz" >/dev/null # Real-model tests are opt-in: set RUN_REAL_MODEL_TESTS=true and provide # OPENROUTER_API_KEY when a branch should hit live OpenRouter. - name: Run real-model integration tests (optional, needs secret) run: npx vitest run test/integration/real-model.test.ts env: OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} RUN_REAL_MODEL_TESTS: ${{ vars.RUN_REAL_MODEL_TESTS }}