name: Test Every Endpoint on Base Sepolia on: push: branches: [ main, ai-main ] pull_request: branches: [ main ] workflow_dispatch: env: GO_VERSION: '1.25' POSTGRES_DB: mcpserver POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres TEST_SERVER_URL: http://localhost:8080 RPC_URL: https://sepolia.base.org X402_FACILITATOR_URL: https://api.cdp.coinbase.com/platform/v2/x402 jobs: test_endpoints: runs-on: node20 timeout-minutes: 30 services: postgres: image: pgvector/pgvector:pg16 env: POSTGRES_DB: mcpserver POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres ports: - 5432:5432 options: >- --health-cmd "pg_isready -U postgres -d mcpserver" --health-interval 5s --health-timeout 5s --health-retries 10 ollama: image: ollama/ollama:latest ports: - 11434:11434 # no healthcheck here - ollama takes >60s to pull image + start, # act would mark service 'not healthy' and abort job. Let steps poll. env: PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} X402_WALLET_ADDRESS: ${{ secrets.X402_WALLET_ADDRESS }} BLUESKY_DID: ${{ secrets.BLUESKY_DID }} BLUESKY_HOST: ${{ secrets.BLUESKY_HOST }} BLUESKY_APP_PASSWORD: ${{ secrets.BLUESKY_APP_PASSWORD }} AP_HOST: ${{ secrets.AP_HOST }} AP_ACCESS_TOKEN: ${{ secrets.AP_ACCESS_TOKEN }} TWITTER_BEARER_TOKEN: ${{ secrets.TWITTER_BEARER_TOKEN }} CDP_API_KEY_ID: ${{ secrets.CDP_API_KEY_ID }} CDP_API_SECRET: ${{ secrets.CDP_API_SECRET }} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Load model config run: | source config/models.env echo "EMBEDDING_MODEL=$EMBEDDING_MODEL" >> $FORGEJO_ENV echo "STYLE_MODEL=$STYLE_MODEL" >> $FORGEJO_ENV - name: Set up Go uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} cache: true - name: Install Dependencies run: go mod download - name: Verify Code Formatting run: | if [ -n "$(gofmt -l .)" ]; then echo "Code is not formatted correctly. Run 'gofmt -w .'" exit 1 fi - name: Wait for PostgreSQL run: | if ! command -v pg_isready >/dev/null 2>&1; then apt-get update && apt-get install -y postgresql-client fi for i in {1..60}; do if pg_isready -h localhost -U postgres -d mcpserver >/dev/null 2>&1 || \ pg_isready -h postgres -U postgres -d mcpserver >/dev/null 2>&1; then echo "PostgreSQL is ready" exit 0 fi sleep 2 done echo "PostgreSQL failed to start" exit 1 - name: Wait for Ollama run: | for i in {1..90}; do if curl -sf http://localhost:11434/api/tags >/dev/null 2>&1 || \ curl -sf http://ollama:11434/api/tags >/dev/null 2>&1; then echo "Ollama is ready" exit 0 fi echo "waiting for ollama $i/90..." sleep 5 done echo "Ollama failed to start (not healthy, but continuing - pull may still work)" curl -v http://localhost:11434/api/tags || curl -v http://ollama:11434/api/tags || true - name: Pull Ollama Models run: | for host in http://localhost:11434 http://ollama:11434; do if curl -sf $host/api/tags >/dev/null 2>&1; then OLLAMA_HOST=$host break fi done : "${OLLAMA_HOST:=http://localhost:11434}" echo "Using OLLAMA_HOST=$OLLAMA_HOST" if [ -n "${EMBEDDING_MODEL:-}" ]; then echo "Pulling $EMBEDDING_MODEL..." curl -X POST $OLLAMA_HOST/api/pull -d "{\"name\":\"${EMBEDDING_MODEL}\"}" || true fi if [ -n "${STYLE_MODEL:-}" ]; then echo "Pulling $STYLE_MODEL..." curl -X POST $OLLAMA_HOST/api/pull -d "{\"name\":\"${STYLE_MODEL}\"}" || true fi sleep 2 curl -sf $OLLAMA_HOST/api/tags || true - name: Debug CDP Secret Format env: CDP_API_KEY_ID: ${{ secrets.CDP_API_KEY_ID }} CDP_API_SECRET: ${{ secrets.CDP_API_SECRET }} run: | echo "=== CDP SECRET DEBUG ===" echo "KEY_NAME: ${CDP_API_KEY_ID}" echo "SECRET_LEN: ${#CDP_API_SECRET}" echo "SECRET_FIRST_80: ${CDP_API_SECRET:0:80}" echo "HAS_LITERAL_\\n: $(echo -n "$CDP_API_SECRET" | grep -c '\\\\n' || true)" echo "HAS_ACTUAL_NEWLINE: $(echo -n "$CDP_API_SECRET" | grep -c $'\n' || true)" echo "STARTS_WITH: $(echo -n "$CDP_API_SECRET" | head -c 40)" echo "ENDS_WITH: $(echo -n "$CDP_API_SECRET" | tail -c 20)" echo "=== END DEBUG ===" - name: Check Facilitator Supported Networks env: CDP_API_KEY_ID: ${{ secrets.CDP_API_KEY_ID }} CDP_API_SECRET: ${{ secrets.CDP_API_SECRET }} X402_FACILITATOR_URL: https://api.cdp.coinbase.com/platform/v2/x402 run: | echo "Building facilitator checker..." go build -o /tmp/check-facilitator ./cmd/check-facilitator /tmp/check-facilitator - name: Start Test Server run: | chmod +x scripts/start-test-server.sh ./scripts/start-test-server.sh - name: Build MCP Test Client run: | go build -o test-mcp-endpoints ./testClient/mcp - name: Run MCP Endpoint Tests env: RPC_URL: ${{ env.RPC_URL }} run: | ./test-mcp-endpoints - name: Build REST Test Client run: | go build -o test-endpoints ./testClient/rest - name: Run REST Endpoint Tests env: RPC_URL: ${{ env.RPC_URL }} run: | ./test-endpoints - name: Dump Server Logs on Failure if: failure() run: | echo "====== /tmp/mcpserver-test.log ======" cat /tmp/mcpserver-test.log 2>&1 || echo "no log file at /tmp/mcpserver-test.log" echo "====== end server log ======" echo "====== journal (last 200 lines) ======" journalctl --no-pager -n 200 2>&1 | tail -n 200 || true - name: Cleanup if: always() run: | if [ -f /tmp/test-server.pid ]; then kill -TERM $(cat /tmp/test-server.pid) 2>/dev/null || true sleep 2 fi echo "====== server log tail (always) ======" tail -n 500 /tmp/mcpserver-test.log 2>&1 || echo "no log file"