Repository navigation
T7: notify() #263
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 | |
| # Runs the full per-change gate on every push to main and every pull request: | |
| # lint (biome) → typecheck (tsc via turbo) → dependency-cycle check (madge) → | |
| # tests with the per-package coverage gate (vitest via turbo — each package | |
| # enforces its own 100% line/fn/stmt + ≥90% branch threshold). | |
| # | |
| # ⚠️ GITHUB-HOSTED RUNNERS, ON PURPOSE. This repository is PUBLIC. A self-hosted runner must never run | |
| # a public repository's workflows: any fork can open a pull request, and `pull_request` workflows | |
| # execute the PR's own code — on a self-hosted machine that is arbitrary code execution on a host that | |
| # also holds other repositories' checkouts and credentials. The org's runner group refuses public | |
| # repositories for exactly that reason (allows_public_repositories=false), so a self-hosted label here | |
| # would not even start. Standard GitHub-hosted runners are free for public repositories, which also | |
| # removes the old "hosted minutes are exhausted" constraint. Linux runners (ubuntu-latest) are the | |
| # cheapest and most plentiful; `pnpm ci:local` runs the same gate on a developer's Mac. | |
| # | |
| # What follows from hosted runners: every run starts on a clean VM, so there is no leaked-process or | |
| # stale-port hygiene to do between runs (the port steps in the e2e job are kept; they are cheap and | |
| # still guard against a hung harness inside one run). | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| # Least privilege: nothing in this workflow writes to the repository. A job that needs more asks for it | |
| # itself. | |
| permissions: | |
| contents: read | |
| # One in-flight run per ref; a new push cancels the previous run. | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| check: | |
| name: Lint · Typecheck · Cycles · Coverage | |
| runs-on: ubuntu-latest | |
| # The runner is shared. Without a bound, a hung vitest worker holds it against | |
| # every other repo's queue until someone notices by hand. | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| # pnpm first (setup-node's pnpm cache needs pnpm on PATH). Version comes from | |
| # the root package.json `packageManager` field (pnpm@11.3.0). | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v6 | |
| # vitest 4 (rolldown) requires Node ≥ 20; the SDK targets Node ≥ 18 at runtime, | |
| # but the toolchain runs on 22. | |
| # | |
| # NO `cache: pnpm` since the move. That option round-trips the pnpm store through | |
| # GitHub's cache service, which only pays off when the machine is thrown away. Here | |
| # the store lives at ~/Library/pnpm/store and survives every run — actions/checkout | |
| # wipes node_modules (`git clean -ffdx`) but never touches the store — so the cache | |
| # would be uploading and re-downloading something already on disk. | |
| - name: Setup Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Lint (biome) | |
| run: pnpm lint | |
| - name: Typecheck (tsc) | |
| run: pnpm typecheck | |
| - name: Dependency cycles (madge) | |
| run: pnpm check:cycles | |
| # Every publishable package is public, carries npm's metadata and ships the one version the SDK | |
| # reports about itself — so a release never discovers a drift at publish time. | |
| - name: Publishable packages | |
| run: pnpm check:publishable | |
| # Per-package coverage gate (turbo runs each package's own test:coverage, | |
| # each enforcing 100% line/fn/stmt + ≥90% branch). NOT the root merged | |
| # `pnpm test:coverage`, whose single aggregate threshold the scaffold-only | |
| # stub packages would drag below 100%. | |
| - name: Test + per-package coverage gate (vitest) | |
| run: pnpm exec turbo run test:coverage | |
| # Harness-owned unit tests (e.g. the bundle-assertion library's negative suite). These live in a | |
| # package with no test:coverage script, so `turbo run test:coverage` skipped them silently — the same | |
| # <NONEXISTENT> hole the e2e job exists to close. | |
| - name: Harness unit tests (vitest) | |
| run: pnpm exec turbo run test:unit | |
| # End-to-end harnesses: the REAL SDK booted in real node/bun/deno processes against a | |
| # mock collector, plus the real-framework suites (nuxt / sveltekit / astro / next). | |
| # | |
| # These existed but were OUTSIDE the gate until 2026-07-27: the `check` job runs | |
| # `turbo run test:coverage`, and the four harness packages define only `test:e2e`, so | |
| # turbo reported `<NONEXISTENT>` and skipped them silently. The adversarial review | |
| # (docs/review/e2e-harnesses.md, SEV1 #1) identified that as the root cause of most of | |
| # its ~90 SEV1 findings surviving ~100% unit coverage. | |
| # | |
| # Separate job so it runs alongside `check` and so its extra runtime setup | |
| # (bun, deno) is isolated. Bun and Deno are installed deliberately: the harness SKIPS | |
| # a runtime whose binary is absent (packages/instrumentation-tests/test/runtimes.ts), | |
| # so without them CI would go green while testing strictly less. | |
| # | |
| # Hosted runners are provisioned per job, so the two jobs run in parallel. | |
| e2e: | |
| name: E2E (node · bun · deno · real frameworks) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v6 | |
| # No `cache: pnpm` — see the note in the `check` job. | |
| - name: Setup Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Setup Deno | |
| uses: denoland/setup-deno@v2 | |
| with: | |
| deno-version: v2.x | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Fail loudly if a runtime the harness expects is missing, rather than letting | |
| # runtimes.ts silently skip it and report green. | |
| # | |
| # ⚠️ These three commands were never the thing that could go missing. What the node target | |
| # actually needs is `tsx`, and the harness resolved it only from the WORKSPACE ROOT's | |
| # node_modules/.bin — where pnpm does not put a package's own devDependency, and where | |
| # `git clean -ffdx` removes the stale copy a developer's machine happens to have. So node | |
| # resolved to `undefined` here for as long as this job has existed, its whole instrumentation | |
| # suite was skipped, and the run went green on 133 tests where a developer ran 195. The real | |
| # guard is now inside the harness (instrumentation.e2e.ts THROWS when node does not resolve); | |
| # these version checks remain as a fast, readable failure for a genuinely missing runtime. | |
| - name: Verify the runtime matrix is complete | |
| run: | | |
| node --version | |
| bun --version | |
| deno --version | |
| # Playwright ships a downloader, not the browsers: `pnpm install` does not fetch them, so | |
| # `browser.e2e.ts` fails with "Executable doesn't exist at .../chrome-headless-shell". | |
| # Scoped to chromium — it is the only engine the browser harness drives. | |
| # On a fresh hosted VM this always downloads; it is a few seconds, not a failure. | |
| - name: Install Playwright's Chromium | |
| run: pnpm --filter @bugsee/instrumentation-tests exec playwright install chromium | |
| # The nuxt/sveltekit/astro harnesses each boot a real dev server on a FIXED port. A fresh hosted VM | |
| # starts clean, so this only guards a hung harness within one run (and a developer's machine, where | |
| # the same script is used). The script reads the ports out of the harnesses and fails if it can no | |
| # longer find them, so moving a port cannot quietly disarm it. | |
| - name: Free the harness ports | |
| run: scripts/free-e2e-ports.sh | |
| - name: E2E suites (turbo run test:e2e) | |
| run: pnpm exec turbo run test:e2e | |
| # `always()` so a CANCELLED or failed run cleans up after itself instead of leaving | |
| # the mess for whoever runs next — which is the run that would get blamed for it. | |
| - name: Release the harness ports | |
| if: always() | |
| run: scripts/free-e2e-ports.sh |