ci: add smoke test job with full stack (postgres + mcpd + mcplocal)
Some checks failed
CI/CD / smoke (push) Blocked by required conditions
CI/CD / build (push) Blocked by required conditions
CI/CD / publish-rpm (push) Blocked by required conditions
CI/CD / typecheck (push) Successful in 44s
CI/CD / test (push) Successful in 55s
CI/CD / lint (push) Has been cancelled
Some checks failed
CI/CD / smoke (push) Blocked by required conditions
CI/CD / build (push) Blocked by required conditions
CI/CD / publish-rpm (push) Blocked by required conditions
CI/CD / typecheck (push) Successful in 44s
CI/CD / test (push) Successful in 55s
CI/CD / lint (push) Has been cancelled
Runs in parallel with the build job after lint/typecheck/test pass. Spins up PostgreSQL via services, bootstraps auth, starts mcpd and mcplocal from source, applies smoke fixtures (aws-docs server + 100 prompts), and runs the full smoke test suite. Container management for upstream MCP servers depends on Docker socket availability in the runner — emits a warning if unavailable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,129 @@ jobs:
|
||||
- name: Run tests
|
||||
run: pnpm test:run
|
||||
|
||||
# ── Smoke tests (full stack: postgres + mcpd + mcplocal) ──
|
||||
|
||||
smoke:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, typecheck, test]
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_USER: mcpctl
|
||||
POSTGRES_PASSWORD: mcpctl
|
||||
POSTGRES_DB: mcpctl
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
DATABASE_URL: postgresql://mcpctl:mcpctl@postgres:5432/mcpctl
|
||||
MCPD_PORT: "3100"
|
||||
MCPD_HOST: "0.0.0.0"
|
||||
MCPLOCAL_HTTP_PORT: "3200"
|
||||
MCPLOCAL_MCPD_URL: http://localhost:3100
|
||||
DOCKER_API_VERSION: "1.43"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: pnpm
|
||||
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma client
|
||||
run: pnpm --filter @mcpctl/db exec prisma generate
|
||||
|
||||
- name: Build all packages
|
||||
run: pnpm build
|
||||
|
||||
- name: Push database schema
|
||||
run: pnpm --filter @mcpctl/db exec prisma db push --accept-data-loss
|
||||
|
||||
- name: Seed templates
|
||||
run: node src/mcpd/dist/seed-runner.js
|
||||
|
||||
- name: Start mcpd
|
||||
run: node src/mcpd/dist/main.js &
|
||||
|
||||
- name: Wait for mcpd
|
||||
run: |
|
||||
for i in $(seq 1 30); do
|
||||
if curl -sf http://localhost:3100/health > /dev/null 2>&1; then
|
||||
echo "mcpd is ready"
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for mcpd... ($i/30)"
|
||||
sleep 1
|
||||
done
|
||||
echo "::error::mcpd failed to start within 30s"
|
||||
exit 1
|
||||
|
||||
- name: Bootstrap auth and write credentials
|
||||
run: |
|
||||
RESULT=$(curl -sf -X POST http://localhost:3100/api/v1/auth/bootstrap \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"email":"ci@test.local","password":"ci-smoke-test"}')
|
||||
echo "Auth bootstrapped"
|
||||
mkdir -p ~/.mcpctl
|
||||
echo "$RESULT" | node -e "
|
||||
const res = JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8'));
|
||||
const creds = {token: res.token, mcpdUrl: 'http://localhost:3100', user: 'ci@test.local'};
|
||||
require('fs').writeFileSync(require('os').homedir()+'/.mcpctl/credentials', JSON.stringify(creds));
|
||||
console.log('Credentials written');
|
||||
"
|
||||
|
||||
- name: Create mcpctl CLI wrapper
|
||||
run: |
|
||||
printf '#!/bin/sh\nexec node "%s/src/cli/dist/index.js" "$@"\n' "$GITHUB_WORKSPACE" > /usr/local/bin/mcpctl
|
||||
chmod +x /usr/local/bin/mcpctl
|
||||
|
||||
- name: Start mcplocal
|
||||
run: node src/mcplocal/dist/main.js &
|
||||
|
||||
- name: Wait for mcplocal
|
||||
run: |
|
||||
for i in $(seq 1 30); do
|
||||
if curl -sf http://localhost:3200/health > /dev/null 2>&1; then
|
||||
echo "mcplocal is ready"
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for mcplocal... ($i/30)"
|
||||
sleep 1
|
||||
done
|
||||
echo "::error::mcplocal failed to start within 30s"
|
||||
exit 1
|
||||
|
||||
- name: Apply smoke test fixtures
|
||||
run: mcpctl apply -f src/mcplocal/tests/smoke/fixtures/smoke-data.yaml
|
||||
|
||||
- name: Wait for server instance
|
||||
run: |
|
||||
echo "Waiting for smoke-aws-docs instance..."
|
||||
for i in $(seq 1 60); do
|
||||
STATUS=$(mcpctl get instances -o json 2>/dev/null | \
|
||||
node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8'));const i=Array.isArray(d)?d.find(x=>x.serverName&&x.serverName.includes('aws')):null;console.log(i?.status??'WAITING')}catch{console.log('WAITING')}" 2>/dev/null || echo "WAITING")
|
||||
echo " Instance status: $STATUS ($i/60)"
|
||||
if [ "$STATUS" = "RUNNING" ]; then
|
||||
echo "Instance is running!"
|
||||
break
|
||||
fi
|
||||
if [ "$i" = "60" ]; then
|
||||
echo "::warning::Instance did not reach RUNNING — container management may not be available in CI"
|
||||
echo "API-layer smoke tests will still run"
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
- name: Run smoke tests
|
||||
run: pnpm --filter mcplocal run test:smoke
|
||||
|
||||
# ── Build & package RPM ───────────────────────────────────
|
||||
|
||||
build:
|
||||
|
||||
Reference in New Issue
Block a user