Live-API smoke #15
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: Live-API smoke | |
| # Runs the smoke test against real public APIs (DexScreener, GoPlus, OpenOcean, | |
| # Across, Hyperliquid, Polymarket, Morpho, Pendle, Drift, etc.) on a schedule | |
| # and on-demand. Unit tests mock these APIs; this catches drift between our | |
| # wiring and what the upstream services actually return. | |
| # | |
| # This intentionally runs separately from the standard CI workflow so a | |
| # transient upstream outage doesn't block PRs. | |
| on: | |
| schedule: | |
| # Daily at 09:00 UTC. Picks up endpoint shape changes within a day. | |
| - cron: '0 9 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: 'Git ref to test (default: main)' | |
| required: false | |
| default: 'main' | |
| jobs: | |
| smoke: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.inputs.ref || 'main' }} | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: mcp-server/package-lock.json | |
| - name: Install deps | |
| run: cd mcp-server && npm ci | |
| - name: Compile TypeScript | |
| run: cd mcp-server && node node_modules/typescript/bin/tsc | |
| - name: Run live-API smoke | |
| env: | |
| # CHAINGPT_API_KEY is required for the server to boot, but the | |
| # read-only smoke cases never hit the ChainGPT plugin API itself. | |
| CHAINGPT_API_KEY: ${{ secrets.CHAINGPT_API_KEY || 'smoke-test' }} | |
| MORALIS_API_KEY: ${{ secrets.MORALIS_API_KEY }} | |
| ONEINCH_API_KEY: ${{ secrets.ONEINCH_API_KEY }} | |
| ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} | |
| run: cd mcp-server && node dist/smoke-test.js | |
| - name: Open issue on failure | |
| if: ${{ failure() && github.event_name == 'schedule' }} | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const title = `[smoke] Daily live-API smoke failed — ${new Date().toISOString().slice(0,10)}`; | |
| const body = [ | |
| 'The scheduled live-API smoke run failed.', | |
| '', | |
| `Workflow: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| '', | |
| 'Likely causes:', | |
| '- An upstream API changed its response shape', | |
| '- A rate limit was hit', | |
| '- A protocol moved to a new endpoint', | |
| '', | |
| 'Open the workflow log to see which case(s) failed and which endpoint to inspect.', | |
| ].join('\n'); | |
| // Only open one issue per day, even if the workflow runs multiple times | |
| const today = new Date().toISOString().slice(0, 10); | |
| const { data: existing } = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'smoke-failure', | |
| per_page: 50, | |
| }); | |
| if (existing.some((i) => i.title.includes(today))) { | |
| core.info('Smoke-failure issue for today already exists; skipping.'); | |
| return; | |
| } | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title, | |
| body, | |
| labels: ['smoke-failure', 'live-api'], | |
| }); |