feat(todomvc-demo): add ?bug=1 reproducible bug for the connector case study #559
Workflow file for this run
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: CI | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| # Workflow-default permissions are minimal — read-only. Individual jobs | |
| # that need more (none in this file at present) must declare their own | |
| # `permissions:` block. The publish workflow lives in release.yml; this | |
| # file is CI only. Hard rule recorded in CONTRIBUTING.md §"Workflow | |
| # security hard rules": every workflow scopes permissions, and no | |
| # workflow in this repo uses `pull_request_target` (the PostHog | |
| # Shai-Hulud 2.0 vector, Nov 24 2025). | |
| permissions: | |
| contents: read | |
| jobs: | |
| ci: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '24' | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # Build first so cross-package type declarations (e.g. @cubenest/rrweb-core's | |
| # dist/*.d.ts) exist before downstream packages typecheck against the | |
| # workspace dependency's published `exports` types. | |
| - run: pnpm build | |
| - run: pnpm lint | |
| - run: pnpm typecheck | |
| # `pnpm test` is vitest-only across all packages — it never launches a | |
| # browser, so the main pipeline stays green without Chrome. The browser | |
| # E2E lives in the separate `e2e-wdio` job below. | |
| - run: pnpm test | |
| # Recipe verifier — the status-aware link check is a HARD gate: a | |
| # PUBLISHED recipe that links to a draft/archived recipe (relatedRecipes | |
| # or inline body link) 404s in prod, so it fails the build here. The | |
| # hero images for every published recipe have now landed, so the | |
| # STRICT_RECIPE_ASSETS gate is on: a published recipe missing its | |
| # `/recipes/assets/<slug>.png` hard-fails here. `pnpm build` above has | |
| # already produced @cubenest/docs-shared's dist/ that this imports. | |
| - run: STRICT_RECIPE_ASSETS=1 node packages/docs-shared/scripts/verify-recipes.mjs | |
| # Plugin/marketplace integrity: manifest shape, mcp-block parity vs the | |
| # repo-root .mcp.json, and the bundled skill copy staying byte-identical | |
| # to packages/peek-cli/skills/peek-skill.md. Fails the `ci` gate on drift. | |
| - run: node packages/docs-shared/scripts/check-plugin.mjs | |
| # @tracelane/wdio browser smoke (Task 2.17). Separate, non-blocking job so a | |
| # Chrome/chromedriver hiccup can't fail the required `ci` gate. The smoke spec | |
| # fails on purpose; the run passes when a < 25 MB .html report was written | |
| # (asserted in e2e/wdio.conf.ts onComplete + e2e/run.mjs exit mapping). | |
| e2e-wdio: | |
| runs-on: ubuntu-latest | |
| # Do not fail the overall workflow if the browser E2E is flaky/unavailable. | |
| continue-on-error: true | |
| # Hard cap so a hung WDIO worker (e.g., chromedriver missing) can't sit | |
| # consuming a runner for 6 hours. WDIO 9 has no default connect-phase | |
| # timeout; if Chrome can't start, the worker waits indefinitely. 15 min | |
| # is generous for the single-spec smoke run that completes in ~30s when | |
| # the runtime is healthy. | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '24' | |
| cache: pnpm | |
| # ubuntu-latest ships Chrome; pin it explicitly so the run is reproducible. | |
| # `install-chromedriver: true` is REQUIRED — the action defaults to false. | |
| # Capture both binary paths via `id:` + outputs and pipe them into WDIO via | |
| # CHROME_PATH/CHROMEDRIVER_PATH (consumed by e2e/wdio.conf.ts). | |
| # | |
| # WHY this matters (May 29 2026 root cause): WDIO 9.27's startWebDriver | |
| # calls setupPuppeteerBrowser + setupChromedriver from @wdio/utils, which | |
| # ignore Chrome/chromedriver on PATH and instead download their own copies | |
| # via @puppeteer/browsers into os.tmpdir(). On GH Actions Ubuntu runners | |
| # that download hangs silently (driver-setup logs are at info level; conf | |
| # ran at warn level). Every e2e-wdio run cancelled at the 15-min cap with | |
| # zero output after "Execution of 1 workers started" — workflow conclusion | |
| # = cancelled => red CI badge on a repo where every push-triggered job | |
| # that mattered (the required `ci` gate + e2e-peek) was actually passing. | |
| # Pointing WDIO at the binaries setup-chrome already installed bypasses | |
| # the Puppeteer download entirely. | |
| - uses: browser-actions/setup-chrome@19ae4b339ee18925ab85cf12c1041150ea4a44c8 # v1 | |
| id: setup-chrome | |
| with: | |
| chrome-version: stable | |
| install-chromedriver: true | |
| - run: pnpm install --frozen-lockfile | |
| # The recorder bundle + workspace deps must be built before the E2E. | |
| - run: pnpm build | |
| - run: pnpm --filter @tracelane/wdio test:e2e | |
| env: | |
| CHROME_PATH: ${{ steps.setup-chrome.outputs.chrome-path }} | |
| CHROMEDRIVER_PATH: ${{ steps.setup-chrome.outputs.chromedriver-path }} | |
| # peek extension Playwright persistent-context smoke (Task 3.29). Separate, | |
| # non-blocking job — a Playwright/chromium download flake or a Chromium | |
| # extension-loading quirk can't fail the required `ci` gate. The smoke | |
| # asserts the unpacked MV3 extension loads + the native-host stdio loop | |
| # ingests into SQLite (see packages/peek-extension/e2e/smoke.spec.ts). | |
| e2e-peek: | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| # Same hard cap as e2e-wdio for the same reason: Playwright's persistent- | |
| # context launches can hang on missing chromium binary downloads or MV3 | |
| # extension load failures. The spec completes in ~30s when healthy. | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '24' | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # Build extension (writes .output/chrome-mv3) + peek-mcp (writes dist/index.js). | |
| - run: pnpm build | |
| # Install Playwright's bundled chromium (NOT chromium_headless_shell — | |
| # the headless shell doesn't load MV3 extensions; the spec sets | |
| # channel: 'chromium' to use the full build). | |
| - run: pnpm --filter @peekdev/extension exec playwright install --with-deps chromium | |
| - run: pnpm --filter @peekdev/extension test:e2e | |
| # peek Windows runtime validation (2026-06-15 Windows-compat audit). Until | |
| # now every CI job ran on ubuntu-latest, so the peek win32 code paths — the | |
| # `\\.\pipe\peek-host` named-pipe bind, the better-sqlite3 Windows prebuild | |
| # (.node dlopen), the backslash-path bin entry guard (pathToFileURL), and the | |
| # %LOCALAPPDATA%/registry-target resolution — were exercised ONLY by unit | |
| # tests that mock process.platform, never on a real Windows kernel. This job | |
| # runs the peek-mcp + peek-cli unit suites on a real Windows runner so those | |
| # branches are validated for real. Scoped to the two peek packages (and their | |
| # workspace deps) to stay fast and avoid unrelated cross-package Windows noise. | |
| # | |
| # Not yet a required check — branch protection still requires only `ci` + `dco` | |
| # (see CLAUDE.md). Promote `ci-windows` to a required context once it has a few | |
| # green runs. continue-on-error is false so its status reflects reality. | |
| ci-windows: | |
| runs-on: windows-latest | |
| # Hard cap: a hung named-pipe bind or a stuck better-sqlite3 install can't | |
| # sit on a (pricier) Windows runner indefinitely. The unit suites finish in | |
| # ~1 min when healthy. | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| # No git credentials are needed after checkout (install/build/test only), | |
| # so don't persist the token in .git/config — reduces token exposure in a | |
| # job that runs repository-controlled code. | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| # Node 24 matches the `ci` job and is >= the better-sqlite3 prebuild | |
| # floor (Node 22+); installing here proves the Windows prebuild loads. | |
| node-version: '24' | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # Build peek-mcp + peek-cli and their workspace deps: peek-cli's tests | |
| # resolve `@peekdev/mcp/db` + `@peekdev/mcp/native-host` via the built | |
| # dist exports, and peek-mcp's stdio smoke test spawns the built bin. | |
| - run: pnpm --filter "@peekdev/mcp..." --filter "@peekdev/cli..." build | |
| - run: pnpm --filter @peekdev/mcp --filter @peekdev/cli typecheck | |
| # The actual point of the job: run on Windows so better-sqlite3's .node | |
| # dlopen, the named-pipe socket-path/host-socket logic, and the | |
| # pathToFileURL entry guard execute on the real platform. | |
| - run: pnpm --filter @peekdev/mcp --filter @peekdev/cli test |