refactor: merge dashboard into Worker with typed coverage schema - #13
Merged
Conversation
Converges the separate Cloudflare Pages SvelteKit dashboard and the coverage-tracker Worker into a single Worker serving static SPA assets alongside all API routes under /api/*. Changes: - wrangler.jsonc: add assets config (SPA fallback), nodejs_compat flag, daily cron trigger (30 6 * * *); all routes now under /api/* - migrations/0002_coverage.sql: add coverage_runs (typed columns, upsert on project+commit) and coverage_daily (daily rollup, PK project+day) - src/routes/ci.ts: new ingest endpoint (POST /api/ci/coverage) with zod CoverageReport validation replacing old EAV /ingest route - src/db/rollup.ts: daily rollup cron snapshots runs >14d into coverage_daily and prunes raw rows; idempotent via ON CONFLICT DO UPDATE - src/lib/db.ts: add upsertCoverageRun, getLatestCoverageRun, getLatestCoverage (coverage_daily fallback for dormant repos), getCoverageTrend (DESC LIMIT subquery → ASC display order) - src/lib/metrics.ts: single source of truth for metric-name→column mapping - src/middleware/access.ts: add CF_Authorization cookie fallback for same-origin SPA fetches to /api/* - dashboard: migrate adapter-cloudflare → adapter-static (fallback: index.html); convert +page.server.ts loads to client-side +page.ts; api.ts uses relative /api/* paths (no WORKER service binding) - .github/workflows/deploy-dashboard.yml: replace wrangler pages deploy with wrangler deploy (single Worker + assets) - .github/actions/report/src/run.ts: POST typed fields to /api/ci/coverage instead of metrics array to /ingest; baseline URL → /api/baseline/* - test/: 7 integration tests (routing, rollup, ci auth) using @cloudflare/vitest-pool-workers with readD1Migrations/applyD1Migrations All tests pass (7 Worker + 52 action unit tests); tsc clean; dry-run OK. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…psert idempotency Adds 6 integration tests in test/db.test.ts: - upsertCoverageRun: second call with same commit updates value, no duplicate - getCoverageTrend with 25-day seed: asserts most-recent 20 days returned in ascending order (not oldest 20 — the DESC-LIMIT subquery fix) - getLatestCoverage: null when empty, returns coverage_runs row when present, falls back to coverage_daily for dormant repos, prefers newest daily row when multiple exist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dist/run.js was not rebuilt after run.ts was updated to POST to /api/ci/coverage and fetch baselines from /api/baseline/*. The compiled bundle still had the old /ingest and /baseline/ paths. Rebuilt via `npm run build` in .github/actions/report/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n page) When Cloudflare Access is configured to protect the domain, unauthenticated requests to /api/baseline/* receive an HTML login page (200 OK after redirect) rather than a 404. The unguarded res.json() call in runPRCheck crashed with "Unexpected token '<'". Wrap in try/catch so the action degrades gracefully (no baseline, threshold checks still run). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
adapter-static) and all API routes under/api/*from one apex domain, replacing the separate Cloudflare Pages deploymentcoverage_runs+coverage_daily) replaces the old EAVmetricstable with typed columns; a daily cron rollup snapshots runs older than 14 days intocoverage_dailyfor permanent historyPOST /api/ci/coverageaccepts typed fields via zod validation (replacing/ingestwith a metrics array); GitHub Action updated to matchCF_Authorizationcookie as a fallback so SPA browser fetches to/api/*are authenticated correctlyKey files
wrangler.jsoncassetsconfig for SPA,nodejs_compat, cron triggermigrations/0002_coverage.sqlcoverage_runs+coverage_dailytablessrc/routes/ci.tsPOST /api/ci/coveragewith zod validationsrc/db/rollup.tssrc/lib/db.tsgetCoverageTrend(DESC LIMIT → ASC display),getLatestCoverage(daily fallback)dashboard/adapter-static, client-side loads, relative/api/*calls.github/workflows/deploy-dashboard.ymlwrangler deployreplaceswrangler pages deploy.github/actions/report/src/run.ts/api/ci/coverageTest plan
npm test— 13 Worker integration tests (routing, rollup, CI auth, DB helpers, trend ordering, daily fallback, upsert idempotency)cd .github/actions/report && npx vitest run— 52 action unit testswrangler deploy --dry-run— validates Worker config and asset resolutionwrangler d1 migrations apply coverage --remotehttps://coverage-tracker.zerostash.org/api/webhooks/githubhttps://coverage-tracker.zerostash.org/api/badge/:owner/:repo/:metric.json/(not/api/*)wrangler secret put CF_ACCESS_AUD+wrangler secret put CF_ACCESS_TEAM_DOMAIN✅ (done)🤖 Generated with Claude Code