Commit Graph

2 Commits

Author SHA1 Message Date
James Anderson e46e2dbb05 feat(web): add performance benchmark dashboard (#2131)
* feat(web): add performance benchmark dashboard

* fix(web): clean up benchmark dashboard exports

* fix(web): support benchmark runs without baselines

* fix(perf): support targeted main baseline runs

* fix(web): revalidate benchmark commit baselines

* feat(perf): improve vinext trace profiles

* fix(web): neutralize insignificant benchmark diffs

* fix(perf): replace existing benchmark runs

* fix(perf): expose vinext trace frames

* feat(perf): retain complete vinext trace detail

* feat(perf): filter flame graph categories

* fix(web): compact flame graph rows

* fix(perf): replace runs by commit identity

* fix(benchmarks): preserve complete performance traces

* fix(benchmarks): use commit time for performance runs

* fix(benchmarks): store performance profiles in R2

* fix(benchmarks): stream performance profiles to R2

* fix(benchmarks): decode raw performance profiles

* fix(benchmarks): show inclusive filtered profile time

* fix(benchmarks): resize filtered flame graphs

* fix(benchmarks): render narrow flame frames

* perf(benchmarks): bound flame graph detail

* ci(perf): split benchmark publication privileges

* fix(perf): harden benchmark publication

* fix(perf): initialize runner paths in job

* fix(perf): install through vite plus

* fix(perf): disable pnpm hooks during install

* fix(perf): select trusted harness ref

* fix(perf): resolve vite plus for isolated user

* fix(perf): grant isolated tool access

* fix(perf): share benchmark cache cleanup

* fix(perf): harden trace publication

* chore(perf): format migration snapshots

* feat(web): restore benchmarks navigation
2026-06-18 11:41:50 +01:00
James Anderson 1c0bdacda6 feat(apps/web): /compatibility page backed by D1 + deploy-suite ingest (#1239)
* feat(apps/web): /compatibility page backed by D1 + deploy-suite ingest

Adds a /compatibility page to apps/web that visualises Next.js
compatibility over time, populated by the nightly deploy-suite workflow.

  - D1 binding (`vinext-metrics`) with Drizzle schema and migrations.
    Tables are namespaced (`compat_runs`, `compat_file_results`) so
    future metric kinds can live alongside.
  - POST /api/compatibility ingest endpoint. Authenticates with a
    `COMPAT_INGEST_SECRET` worker secret and upserts by
    (kind, runKey).
  - GitHub-style contribution grid (one dot per test file) and a
    pass-rate-over-time line chart. Both are SVG, no chart libs.
    Pass rate excludes Next.js-skipped tests from the denominator.
  - Shared header/footer extracted into app/_components and rendered
    by the root layout. Nav uses next/link for soft client nav.
  - Workflow change: on top of the existing per-test pass/fail/skip
    aggregation, the report job now POSTs results to the ingest
    endpoint. Guarded to only run when (a) filter=all and
    (b) targeting main, so partial runs and branch spot-checks don't
    pollute the historical record.

The first nightly run after merge will seed the production D1.

* address review + add ISR with KV cache

Review fixes (apps/web/app/api/compatibility/route.ts):
  - constant-time secret comparison via SHA-256 + bytewise XOR
  - single-statement atomic upsert with onConflictDoUpdate (no
    SELECT->INSERT race for concurrent retried runs)
  - top-level try/catch with structured error body so workflow logs
    show why ingest failed instead of a generic 500
  - MAX_FILES=2000 cap in validation as defensive bound

Page perf (apps/web/app/compatibility/page.tsx):
  - latest-run and trend D1 queries run in parallel via Promise.all

ISR + KV:
  - new vinext-web-cache KV namespace bound as VINEXT_CACHE
  - worker installs KVCacheHandler once per isolate
  - both pages opt into ISR with revalidate = 300; compat page drops
    force-dynamic

* address bonk re-review

  - Drop the ?kind= query param. Only one kind exists today; gating it
    behind an unused param invited ISR cache pollution. Hardcoded to
    "deploy" with a comment pointing future kinds at a dedicated route.

  - Wrap the DELETE + chunked INSERTs in a single `db.batch()` so a
    crash mid-write can no longer leave a run with zero file results.
    D1 executes batch statements inside one transaction.

  - Resolve workflow expressions once via step-level `env:` and read
    them as `process.env.*` from the github-script body. Removes the
    fragile splicing of `${{ inputs.next-ref || 'v16.2.6' }}` into JS
    string literals (the nested single quotes were the worst offender).
2026-05-15 15:10:36 +00:00