* test(cli,tui): add in-process source coverage gates (#1484) CLI and TUI source had no coverage gate: CLI tests spawned the built binary out-of-process (coverage never saw clients/cli/src) and the TUI had only two smoke tests. Regressions there were invisible to CI. CLI: - Rewrite __tests__/helpers/cli-runner.ts to invoke runCli() in-process (capture process.std*.write, map thrown errors to an exit code), preserving the CliResult shape so all existing tests run unchanged and clients/cli/src is now measured under v8 instrumentation. - cli.ts: program.exitOverride() so a commander usage error throws (catchable in-process) instead of tearing down the worker; --help / --version still exit cleanly. Drop the dead, never-imported main(). - Add a thin out-of-process e2e.test.ts that spawns the built binary for the shebang / process.exit paths the in-process runner can't reach. - Add @vitest/coverage-v8, a per-file gate (90/85/80/50) excluding only src/index.ts (binary bootstrap), and pool: 'forks' for capture isolation. cli.ts lands at ~98% lines / 100% functions. TUI: - Add @vitest/coverage-v8 and an interim per-file gate over the non-React logic (logger.ts, components/tabsConfig.ts, utils/*); the Ink components, App.tsx, and hooks/ are excluded with a documented follow-up (#1501). Add tests covering the included modules (100%). Wiring + docs: - CI runs each client's test:coverage; root test:cli / test:tui (used by validate) and root test:coverage now enforce the gates. - gitignore clients/**/coverage; update AGENTS.md and client READMEs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): clarify in-process runner footguns from PR #1502 review Review notes on the in-process CLI test runner (no behavior change): - Warn in runCli's docblock that --help/--version must NOT go through the in-process runner: exitOverride only re-throws non-zero exits, so exitCode 0 falls through to process.exit(0) and would kill the vitest worker. Those belong in the out-of-process e2e.test.ts layer. - Document that a timeout orphans the uncancellable invokeCli promise (its stdio subprocess stays alive; later writes hit the restored stdout) — a known, acceptable trade-off on the hang-only failure path. - Fix a stale reference to the removed main() (errors now route through index.ts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): fix remaining stale main() reference in vitest exclusion comment PR #1502 re-review caught a second stale `main()` mention (the first was fixed in 52c23e41). src/index.ts inlines the bootstrap as runCli(process.argv).then(...).catch(handleError) — there is no main(). Comment-only; no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: compose root test:coverage from per-client scripts Replace the brittle inline cd-chain with a composition of the existing test:cli / test:tui scripts plus a new matching test:web. Behavior is unchanged (web → cli → tui coverage gates) but there's a single source of truth for each client's coverage invocation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
82 lines
2.7 KiB
YAML
82 lines
2.7 KiB
YAML
name: Run install, format, lint, build, and test on every push
|
|
|
|
on: [push]
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: '20.x'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies (root + all clients)
|
|
# The root postinstall (scripts/install-clients.mjs) cascades
|
|
# `npm install` into clients/web, clients/cli, clients/tui, and
|
|
# clients/launcher, so this single step sets up every client.
|
|
run: npm install
|
|
|
|
- name: Check formatting
|
|
working-directory: ./clients/web
|
|
run: npm run format:check
|
|
|
|
- name: Run linter
|
|
working-directory: ./clients/web
|
|
run: npm run lint
|
|
|
|
- name: Run Build
|
|
working-directory: ./clients/web
|
|
run: npm run build
|
|
|
|
- name: Run tests with coverage
|
|
working-directory: ./clients/web
|
|
run: npm run test:coverage
|
|
|
|
- name: Run CLI tests with coverage
|
|
# In-process runCli() tests under v8 instrumentation + a thin
|
|
# out-of-process E2E layer; enforces the per-file gate for
|
|
# clients/cli/src (#1484).
|
|
working-directory: ./clients/cli
|
|
run: npm run test:coverage
|
|
|
|
- name: Run TUI tests with coverage
|
|
# Enforces the per-file gate for the TUI's non-React logic modules
|
|
# (interim scope — see clients/tui/vitest.config.ts and #1501).
|
|
working-directory: ./clients/tui
|
|
run: npm run test:coverage
|
|
|
|
- name: Build CLI, TUI, and launcher
|
|
run: npm run build:cli && npm run build:tui && npm run build:launcher
|
|
|
|
- name: Smoke test launcher
|
|
run: |
|
|
node clients/launcher/build/index.js --help
|
|
node clients/launcher/build/index.js --cli --help
|
|
node clients/launcher/build/index.js --tui --help
|
|
|
|
- name: Smoke test prod web launcher (end-to-end)
|
|
# Starts `mcp-inspector --web` against the built clients/web/dist (from
|
|
# the "Run Build" step) and asserts GET / serves the SPA (HTTP 200) with
|
|
# the injected auth token — the prod web path the --help smoke can't
|
|
# reach (#1486).
|
|
run: npm run smoke:web
|
|
|
|
- name: Cache Playwright browsers
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-${{ runner.os }}-${{ hashFiles('clients/web/package-lock.json') }}
|
|
|
|
- name: Install Playwright browsers
|
|
working-directory: ./clients/web
|
|
run: npx playwright install --with-deps chromium
|
|
|
|
- name: Run Storybook play-function tests
|
|
working-directory: ./clients/web
|
|
run: npm run test:storybook
|