ci: migrate workflows to ubuntu-latest runners - #283
Conversation
The wave-rf-runners ARC pool must not serve a public repo (and GitHub-hosted standard runners are free for public repos), so all 11 jobs move to ubuntu-latest. Two follow-on fixes the pool's runner-pod env used to paper over: - publish-dev/release: add docker/setup-buildx-action — dockers_v2's linux/amd64+arm64 manifest needs a docker-container builder now that the preset BUILDX_BUILDER (remote BuildKit VM) is gone. No QEMU needed; Dockerfile.goreleaser is $BUILDPLATFORM-pinned/COPY-only. - setup-env/ci: pnpm/playwright/astro cache keys hashed the three pre-#190 lockfile paths, which no longer exist — constant key that never invalidated. Key on the root pnpm-lock.yaml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Free Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughMigrated GitHub Actions jobs from custom runner infrastructure to GitHub-hosted ChangesRunner and cache consolidation
🎯 2 (Simple) | ⏱️ ~12 minutes Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
The fixture stamped seq 61 at cutoff+1s with cutoff computed at table-construction time, while findGapSequence recomputes cutoff at call time — so the test only passed when <1s elapsed before the parallel subtest ran. Microseconds locally/on ARC pods; >1s on a loaded 2-core hosted runner (first GH-hosted run on #283 caught it, 0x3d vs 0x3e). Minute margins match the sparseSequences fixture and are unexceedable inside the suite's 15s binary timeout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two more pre-existing timing knife-edges surfaced by the runner migration (#283), both test-only: - query.test.ts max_execution_time_ms: a zero-row query on a tiny table can complete sub-millisecond and beat the 1ms deadline before cancellation is ever observed, so a single attempt is a coin flip. The enforced property is existential — a 1ms budget must produce deadline 500s — so retry via waitForCondition (unique event_id per attempt, never cache-served) and pass on the first deadline error. Broken enforcement still fails: every attempt succeeds and the wait times out. - batching.test.ts 500-item flush test: the ack rides 500 sequential JetStream publish-fsyncs (5104ms observed on APFS vs a 5000ms bound), and when the ack outlasts the 5s linger the timer fires mid-publish, splits the batch, and the buffer never holds 500 rows — the size-trigger property is unobservable in that regime, not merely slow (review finding). Now: 15s sanity bound on the ack; strict <5s flush assertion only when the publish beat the linger with margin (ack <4s); integrity-only verification otherwise; 45s explicit test timeout so the worst honest path clears the 30s default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
📚 Docs preview is live → https://a714ddb2-wavehouse-docs.wave-rf.workers.dev
|
## What This branch rebuilds the docs landing experience around a **live** `@wavehouse/sdk` consumer and, in the process, turns the docs from "a polished landing bolted onto stock Starlight" into one coherent, branded, accessible system. Four loosely-coupled workstreams plus the fixes the review gate shook loose: 1. **Live-demo hero panel** — the landing page now renders real data from [stats.wavehouse.dev](https://stats.wavehouse.dev). 2. **Site-wide design-system pass** — one radius scale, one button shape, AA-correct light theme, branded Starlight chrome, a wide-screen layout that uses the space. 3. **Mermaid diagrams** — fixed the label-clipping bug, made big diagrams readable (vertical layout + click-to-zoom), and set a house style. 4. **Docs-accuracy corrections** + **backend/test fixes** surfaced by getting `make ci` honestly green and 7 rounds of dual-reviewer self-review. A focused **"Where this deviates from Astro/Starlight defaults"** section is near the bottom, since that's easy to lose track of. --- ## 1. Live-demo hero panel (`docs/src/components/LiveDemo.astro`, new) The hero's visual column is a real SDK consumer against the public read-only role on the WaveHouse-Stats dogfood deployment (`PUBLIC_WAVEHOUSE_STATS_URL`-overridable): - **Live counts** — stars, forks, events-over-7d (168h), open issues/PRs, lifetime total — from **one cached `gh_summary` pipe call**. `setCount()` writes every `[data-wh-live="<key>"]` on the page, so the same fetch also feeds the hero star chip and the closer-band chip. - **Live activity feed** — backfilled from the server-curated/deduped cached `gh_activity_recent` pipe, then a live SSE `stream()` tail. The **stream connects before the backfill** so nothing lands in the gap; a composite-key dedup absorbs the overlap and webhook redeliveries. - **Live "wow" metrics** — `⚡ ingested → live in ~N ms` (per-event, 30-sample median, skew-clamped → Stats#33) and an **events/min sparkline** (`gh_events_per_minute` pipe → Stats#34). - **Three-tier graceful degradation**: `gh_summary` → per-number pipes; `gh_activity_recent` → a structured-query backfill; both gone → a layout-stable SSR skeleton with an "offline" pill. A stats-stack rollback makes the panel slower, never blank. - **SSE normalization** (load-bearing): live rows are raw producer payloads, so `normTs()` converts zone-less ClickHouse timestamps → ISO-8601 UTC; the wire filter is type-only (an `action` IN-filter would drop rows whose `action` is absent), with a `VERBS` allowlist as the final arbiter. - **View-transition lifecycle**: per-mount re-init + teardown (SSE `close()`, all timers). `is:global` styles because feed rows are runtime-created DOM. `Hero.astro` drops `terminalLines`, the `.wh-terminal` block, and the `.wh-hero__mesh` SVG; the `pnpm add` hint becomes a **click-to-copy command chip**; the "View on GitHub" `↗` glyph finally renders (Starlight parses `icon: external` into an object, so the old string compare never matched). Built on the upstream pipes filed + merged on WaveHouse-Stats: **#18** (`gh_activity_recent`), **#19** (`gh_summary`). Per-visitor load is 2 cached, singleflight-collapsed pipe hits + SSE (was 3 uncached reads + SSE). ## 2. Site-wide design-system / UI consistency pass (`docs/src/styles/global.css`) A measured audit (every page × both themes, computed-style harness) drove a unification: - **Radius** — ~11 ad-hoc values collapsed to one scale (`--radius-xs/sm/md/lg/pill` = 4/8/12/16/999px). All buttons 8px; cards/panels/code-frames/tables 12px (no more 1px frame lip). - **Buttons** — the same CTA rendered three ways; the closer-band pills are now 8px rectangles matching the hero. - **Light theme (AA)** — accent-as-text was 2.6:1; new `--wh-accent-text` role (6:1) rewired through links/sidebar/focus-ring/stats. Status hues (amber/emerald/rose) got light overrides; page bg stepped darker so white cards read as layers (was 1.04:1, flat). - **Layout** — `--sl-content-width` is now a responsive track (45rem → 50rem ≥72rem → 58rem ≥100rem; prose held to 46rem so text stays ~70–75ch while code/tables/diagrams use the width). `.main-frame` caps + centers at ≥100rem, killing ~590px of one-sided dead space at 2560px. **Zero horizontal overflow across 14 pages × 8 widths (320–2560) × both themes.** - **Grid background** — was a hero-only shrinking center-blob, invisible in light; now two page-level fixed layers (full-bleed signal-field grid + breathing hero glow), visible in both themes, scoped via `body:has(.wh-hero)`. Required `body:has(.wh-hero){background:transparent}` to defeat Starlight's layered opaque body background. - **Starlight chrome** — pagination, tables, blockquotes, search trigger, and the sidebar (group eyebrows + hover + current item) are now branded. (The old sidebar selector `…nav > ul > li > a` matched 0 elements — the DOM has no nested `nav` — so it was a silent no-op until rewritten.) ## 3. Mermaid diagrams — clipping fix, vertical layout, click-to-zoom The most visible regressions you flagged on the preview: - **Label clipping (`Buffer Consumer` → `Buffer Consume`).** Root cause: the build-time Chromium measures each node's box, then the browser displays it — and `global.css` renders node labels at **font-weight 500** while Mermaid measured them at the default **400**, so every box came out ~1px too narrow and the longest label in each node clipped on the right. Present on `main` too (across all 116 nodes), which is why it kept coming back. Fixed **upstream** in [`astro-themed-mermaid`](https://github.com/Wave-RF/astro-themed-mermaid) (new `measurementCss` option, v0.3.0) that injects the consumer's label metrics into the render page so Mermaid measures what the browser shows. `mermaid-theme.mjs` passes the node-label weight/letter-spacing + a 1.5px safety pad; selectors are bare (`.nodeLabel p`) because Mermaid measures before the flowchart `<svg>` wrapper exists. **Verified 0/116 nodes clip** after the fix. - **Diagrams "side-by-side and hard to see."** The diagrams themselves are byte-identical to `main` (same source, same Mermaid config, no version bump) — nothing in the geometry regressed. What you were seeing is the `.diagram-pair` wrapper (the DIY-vs-WaveHouse comparison): it flipped to a **side-by-side row at ≥1500px**, shrinking each diagram to ~450px on a wide monitor. That ≥1500px variant is **removed** — the pair now always stacks vertically at full content width. - **Click-to-zoom** (`MermaidZoom.astro`, new) — clicking any diagram opens it in a lightbox: small diagrams scale up (capped 2.5×), wide ones show at natural size with pan-scroll for full detail. Esc / backdrop / button closes; keyboard-focusable (Enter). View-transition-safe (one delegated `document` listener, re-enhanced on `astro:page-load`). The clone is re-id'd so its id-scoped inline `<style>` (font, themed fills) and `url(#…)` refs keep working. - **House style** — `AGENTS.md` §"Authoring Mermaid diagrams": author vertically (`TB`/`TD`) over horizontal (`LR`) so diagrams fit the page; never sit two large diagrams side-by-side; keep labels short. > **Cross-repo note:** the `astro-themed-mermaid` dependency is pinned to the v0.3.0 **fix commit** while [Wave-RF/astro-themed-mermaid#1](Wave-RF/astro-themed-mermaid#1) (draft) awaits a human merge — the PR-discipline gate blocks an agent from publishing/merging it. Once it's merged and tagged, the pin moves from the SHA to `#v0.3.0`. ## 4. Docs-accuracy corrections (prose, surfaced by the review gate) Each is a code↔docs accuracy fix: all ten `?table=` curls quoted (unquoted `?` aborts on zsh before curl runs — the first runnable landing command was one); `/v1/admin/query` example gains its missing `Authorization` header; the silent 10k `limit` cap, `time_range` `until` semantics, and admin-only callouts + error tables documented across `/v1/schema*` and `/v1/dlq/stats`; the DLQ payload corrected to the `EventMessage` envelope (+`X-DLQ-*` headers); `wh.dlq.stream()` marked non-functional (#197); the fictional "SSE/WS fan-out" removed from `ingest-pipeline.md`; schema-refresh 404 caveats in the quickstarts; and the false "secretless ⇒ no token validates / pure public deployment" framing removed from `api.md` / `access-control.md` / `configuration.md` (see #291 below). ## 5. Backend / test fixes (surfaced by the gate) - **`fix(mq)` #287** — embedded NATS installed its own SIGINT handler (`NoSigs` unset), racing graceful shutdown → panic (exit 2, coverage counters never flushed → 0.0% gate) or `os.Exit(0)` past all defers. Both option literals get `NoSigs: true`; both owners `WaitForShutdown()`. - **`fix(e2e)` 30s orchestrator budget** — removing the NATS early-exit exposed a ~15s OTel exporter dial-backoff on clean shutdown (filed **#288**); the old 10s budget SIGKILLed before the coverage flush. - **Test de-flakes (cherry-picked from #283)** — batching size-trigger re-anchored to `startTime`; the 1ms deadline-500 test rewrapped in `waitForCondition`. ## 6. Docs preview / tooling - **Sticky preview comment** (`ci.yml`) now shows the **commit subject (linked)** and **upload time (UTC)** alongside the URL, so a stale preview is obvious at a glance. - `screenshot.mjs`: `networkidle` → `load` (the SSE stream never goes idle); the screenshot-ready signal moved to the visual column's entrance, independent of live data. - `@wavehouse/sdk` is a docs **workspace dep**; `check-docs` / `dev-docs` gained a `build-ts` prerequisite. --- ## Where this deviates from Astro/Starlight defaults The bits a future reader (or Starlight upgrade) needs to know are non-stock: **Config (`docs/astro.config.mjs`)** - **Component overrides** — `Hero`, `SiteTitle`, `Footer`, `Head` are all replaced with local components. `SiteTitle` renders a custom `<WaveMark/>` (theme-aware `currentColor`) and Starlight's `logo` is deliberately omitted so it never renders; `Footer` re-renders Starlight's `EditLink`/`LastUpdated`/`Pagination` itself (overriding `Footer` drops them) and now also mounts `<MermaidZoom/>`; `Head` live-swaps the theme-adaptive favicon. - **Expressive Code** — `borderRadius: calc(0.75rem - 1px)` (so the frame's outer corner lands at exactly 12px; EC adds the border width and derives inner corners from the same base), custom `codeFontFamily`/`uiFontFamily`, `frames.shadowColor`, themes pinned to `github-dark`/`github-light`, and `shiki.langAlias` (`env→bash`, `dns→ini`). - **Markdown pipeline** — `syntaxHighlight.excludeLangs: ["mermaid"]`; remark `[remarkMath, mermaid.remarkInjectClassdefs]`; rehype `[mermaid.rehypeMermaid, rehypeKatex]`. Mermaid is the in-house [`astro-themed-mermaid`](https://github.com/Wave-RF/astro-themed-mermaid) integration (build-time SVG via headless Chromium + a per-diagram disk render cache), themed entirely from CSS variables. - **Plugins beyond stock** — `starlight-image-zoom`, `starlight-llm-tools`, and `starlight-links-validator` (**conditionally dropped** when `WAVEHOUSE_DOCS_WATCH` is set, so the dev rebuild loop doesn't fail on a mid-edit dangling link). - **Other** — `trailingSlash: "never"`; explicit favicon set + full Open Graph / Twitter image meta that Starlight doesn't emit; `customCss` = the design system + KaTeX; custom `sidebar`; `lastUpdated`; Tailwind 4 via `@tailwindcss/vite` inside a Starlight site. **CSS-level Starlight overrides (`global.css`)** — remapped `--sl-*` tokens (`--sl-color-text-accent`, the responsive `--sl-content-width`, `--sl-sidebar-width`); branded pagination/tables/blockquotes/search-trigger/sidebar; `.main-frame` ultrawide cap; and the `body:has(.wh-hero){background:transparent}` workaround for Starlight's layered opaque body background. **Deploy** — the site is **not** built by Cloudflare Workers Builds (no headless browser there for Mermaid); it ships from the CI tail steps (`wrangler deploy` on main, `wrangler versions upload` per PR), and a `cloudflare-md-router` Worker provides `.md` content negotiation. Workers Builds must stay disconnected from the Worker or it double-deploys. --- ##⚠️ Security finding filed, not fixed here — #291 The docs gate surfaced a pre-existing auth-forgery vulnerability: a secretless deployment (the default compose quickstart, no `WH_AUTH_JWT_SECRET`) verifies HMAC tokens against `[]byte("")`, so anyone can forge `{"role":"admin"}` signed with the empty string and reach `/v1/admin/query`. Verified against golang-jwt v5.3.1. Per maintainer decision it's tracked in **#291** for a security-reviewed fail-closed fix and kept **out of this docs PR** — which only removes the sentences that restated the masking "secretless ⇒ no token validates" claim. ## Verification - `make ci` green locally; `astro check` + full docs build green; markdownlint/biome/typecheck clean. - Mermaid: 0/116 node labels clip after the fix (measured on the rebuilt site); click-to-zoom verified open/clone/Esc across pages; diagram-pair confirmed vertical. - Live demo: headless Playwright across three data paths (pipes-live, new-pipes-blocked, full blackout) + the 10 viewport×theme sweep, no-overflow, view-transition round-trip. ## Follow-ups - Merge + tag [Wave-RF/astro-themed-mermaid#1](Wave-RF/astro-themed-mermaid#1) as **v0.3.0**, then switch the docs pin from the SHA to `#v0.3.0`. - #291 (auth fail-closed fix), #286 (query-builder playground), #288 (OTel shutdown backoff). - WaveHouse-Stats #20 (embed capacity / SSE fan-out), #21 (stats page as public destination). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve conflicts in tests/e2e/sdk/{batching,query}.test.ts by taking main's
de-flaked versions: the startTime-anchored batching assertion and .selectAll()
in the max_execution_time test. Both branches had made the same de-flake
rewrite; main's two refinements supersede the branch's, and main's new #223
column-allowlist suite in query.test.ts merged in cleanly. The resolved files
match main exactly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Why
Prep for flipping the repo public: the
wave-rf-runnersARC pool must never serve a public repo (GitHub's hard rule on self-hosted + public), and GitHub-hosted standard runners are free for public repos — with publicubuntu-latestbeing the 4-core/16 GB tier. Reverses the #77 calculus, exactly as planned in the public-launch gates.What
runs-on: [wave-rf-runners]→ubuntu-latest— all 11 jobs across all 10 workflows.docker/setup-buildx-actioninpublish-dev.yml+release.yml(d7f5e7f= v4.1.0, SHA verified against upstream):dockers_v2builds thelinux/amd64+arm64manifest via buildx, and the hosted default docker driver can't do multi-platform — the runner-podBUILDX_BUILDER(remote BuildKit VM) used to provide this. No QEMU needed:Dockerfile.goreleaserstages are$BUILDPLATFORM-pinned / COPY-only by design.goreleaser-validate.ymlcorrectly stays buildx-free (build --single-targetnever touchesdockers_v2).clients/ts/,tests/e2e/sdk/,docs/lockfiles — paths deleted in the refactor(sdk)!: remove WebSockets + consolidate tooling/coverage #190 root-workspace consolidation — sohashFiles()was empty and the keys degenerated to constants that never invalidated. Now keyed on the rootpnpm-lock.yaml. Old degenerate entries stay reachable via unchangedrestore-keys, so the first run warm-starts and re-saves under the correct key.No falcondev cache-server or registry-proxy references existed in any workflow (the redirects were runner-pod env) —
actions/cachefalls back to GitHub's backend transparently. Footprint ~2–3 GB vs the 10 GB/repo cap.Verification
make cigreen locally (full pipeline incl. integration + e2e)wave-rf-runners/self-hosted/BUILDX_BUILDERreferencesWatch-items (post-merge)
publish-dev.ymlrun — watch it. (A pre-merge dispatch from this branch would clobber the rolling:devtag, so deliberately not done.)clickhouse/clickhouse-server:latestunauthenticated; hosted runners share egress IPs, so rate-limit flakes become possible. If they appear: GHCR mirror or registry login.ci.yml4-core comment describes the post-flip state. Well inside the 45-min cap either way.@dependabot rebasefor the bot ones), same dynamic as ci: migrate workflows to ARC runners on self-hosted infra #77.🤖 Generated with Claude Code