Skip to content

ci: unified workflow (lint + typecheck + build + rust)#100

Merged
Camillebzd merged 12 commits into
smooth-transaction-volume-chartfrom
ci/unified-frontend-workflow
Jun 11, 2026
Merged

ci: unified workflow (lint + typecheck + build + rust)#100
Camillebzd merged 12 commits into
smooth-transaction-volume-chartfrom
ci/unified-frontend-workflow

Conversation

@kyscott18

@kyscott18 kyscott18 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Replaces .github/workflows/lint.yml with a unified .github/workflows/ci.yml running four jobs:

  • lint — Biome 2.1.2 (biome ci)
  • typechecktsc --noEmit (frontend)
  • buildnext build (frontend)
  • rustcargo fmt --check, cargo clippy -D warnings, cargo build (backend workspace)

Notes:

  • lint.yml is removed; its Biome job is rolled into ci.yml.
  • The existing publish-backend.yml (Docker image publish) is unchanged — this adds build/lint CI for Rust, not publishing.
  • The rust job runs in the rust:1.91-slim container (matching the backend Dockerfile) so bindgen's libclang is new enough for the upstream C23 headers from monad-bft. Cargo build is cached via Swatinem/rust-cache.
  • All jobs are workflow_dispatch-able from the Actions tab (also run on pull_request and pushes to main).

Also adds a typecheck script (tsc --noEmit) to frontend/package.json.

⚠️ Known-red check: rust (clippy)

cargo fmt --check and cargo build pass. cargo clippy -D warnings currently fails on 8 pre-existing lint issues in backend/ (this code was never clippy-checked — publish-backend.yml only builds). We are keeping strict -D warnings and fixing those findings in a separate follow-up PR; the rust check here is expected red until then. Findings: large_enum_variant, needless_return, match_like_matches_macro, should_implement_trait (from_str), ptr_arg, clone_on_copy, manual_is_multiple_of, needless_borrow.

Follow-ups (separate PRs)

  1. Fix the 8 backend clippy findings so the rust job goes green.
  2. Unify the two pnpm projects (root + frontend/) into a single root pnpm workspace with root orchestration scripts — deferred because it needs coordinated Vercel deploy-settings changes.

Stacked on #99 for the pnpm lockfile fix; rebase base back to main once #99 merges.

dak-agent Bot and others added 5 commits June 8, 2026 20:48
Switch the TPS Area interpolation from `linear` to `monotone` so the
Transaction volume chart renders as a smooth curve instead of connected
straight segments between data points.
Revert line interpolation to linear and enable Recharts' built-in
animation so newly arriving data points ease into the chart instead
of snapping in. This is the smoothing that was actually requested:
the visible motion of new points appearing, not the line shape.
Switch the X axis to a continuous time scale with a [now - 5min, now]
domain advanced each animation frame, so new points slide in smoothly
from the right edge instead of popping into discrete category slots.
Keeps isAnimationActive disabled to avoid Recharts re-animation loops on
each TPS event. Clamp the domain's left edge to the oldest point so the
chart fills immediately instead of showing an empty 5-minute lead-in.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces frontend/pnpm-lock.yaml with main's lockfile minus the duplicate
keys introduced by PR #97 (so pnpm 10 can parse it). No package versions
change vs main; pnpm install --frozen-lockfile passes.

The previous commit on this branch ran a non-frozen pnpm install, which
silently re-resolved every floating semver in package.json and produced
~2000 lines of incidental lockfile churn. This commit reverses that.
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
monode Ready Ready Preview, Comment Jun 11, 2026 9:05am

Request Review

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR consolidates CI into a single unified ci.yml workflow (replacing lint.yml) with four parallel jobs — Biome lint, TypeScript typecheck, Next.js build, and a Rust job covering fmt/clippy/build — and also ships several frontend and backend improvements found while wiring up the checks.

  • CI: New ci.yml runs lint, typecheck, build, and Rust checks on pull_request, push to main, and workflow_dispatch; the Rust job runs inside rust:1.91-slim to match the backend Dockerfile's libclang requirements, with Swatinem/rust-cache for build caching.
  • Frontend: events-context gains per-subscriber event-type filtering and background-tab message dropping; use-block-execution-tracker is refactored to a ref-based inflight-block map for O(1) transaction updates; tps-chart adds a rAF-driven sliding window with progressive segment animation.
  • Backend: Eight pre-existing Clippy warnings are resolved (large_enum_variant, needless_return, match_like_matches_macro, should_implement_trait, ptr_arg, clone_on_copy, manual_is_multiple_of, needless_borrow).

Confidence Score: 5/5

Safe to merge — the CI wiring is correct, the Rust clippy fixes are mechanical and verified, and the frontend refactors are well-structured with no logic regressions.

The workflow change is additive and mirrors the existing lint job patterns. The Rust changes fix all 8 listed clippy warnings correctly. The frontend changes (inflight-block ref map, event-type filtering, sliding TPS chart) are logically sound. The only issue is a team style-rule violation on one useRef call, which has no runtime impact.

frontend/hooks/use-block-execution-tracker.ts — contains the useRef style-rule violation; all other files look clean.

Important Files Changed

Filename Overview
.github/workflows/ci.yml New unified CI workflow — lint, typecheck, build, and Rust jobs are correctly structured; Rust job installs git before checkout and uses appropriate rust:1.91-slim container with rust-cache.
frontend/hooks/use-block-execution-tracker.ts Major O(N²) → O(1) refactor using a ref-based inflight map; logic is sound, but useRef<number
frontend/contexts/events-context.tsx Adds per-subscriber event-type filtering via ReadonlySet, background-tab message dropping, and useMemo on the context value — all look correct.
frontend/components/network-activity-tracker/tps-chart.tsx Adds rAF-driven sliding window and progressive segment animation via useSlidingNow/drawHistory/buildTicks; intentional 60fps re-renders for smooth chart scrolling, rAF naturally pauses in hidden tabs.
backend/src/lib/server.rs Boxes EventData in the enum variant to fix large_enum_variant; removes needless return and rewrites match-as-bool with matches!(); all changes are safe mechanical clippy fixes.
backend/src/lib/event_listener.rs Renames from_str to from_name (avoids should_implement_trait warning) and replaces % 100 == 0 with is_multiple_of(100); both are correct clippy-driven cleanups.
backend/src/lib/event_filter.rs Changes &Vec to &[T] (ptr_arg fix) and removes a redundant borrow on is_native_transfer (needless_borrow fix); both are correct and safe.
backend/src/bin/client.rs Removes redundant as u64 casts from u64 timestamp subtractions; correct since both operands are already u64.
backend/src/lib/serializable_event.rs Removes .clone() on a Copy type (clone_on_copy fix); trivially correct.
frontend/hooks/use-events.ts Threads eventTypes through to subscribe(); all callers use module-level constants so the dep-array reference is stable — no spurious re-subscriptions.
frontend/hooks/use-block-state-tracker.ts Adds BLOCK_STATE_EVENT_TYPES module-level constant and passes it to useEvents for filtered delivery; no logic changes.
frontend/hooks/use-swap-events.ts Adds SWAP_EVENT_TYPES = ['TxnLog'] filter; hook already only cared about TxnLog events so this is a correct narrowing with no behaviour change.
frontend/hooks/use-total-transactions.ts Adds TXN_HEADER_EVENT_TYPES = ['TxnHeaderStart'] filter; narrows subscription to the only event type the hook processes.
frontend/hooks/use-transfer-events.ts Adds TRANSFER_EVENT_TYPES = ['TxnCallFrame', 'TxnLog'] filter matching what the hook already handled.
frontend/package.json Adds typecheck script (tsc --noEmit) needed by the new CI typecheck job.
frontend/pnpm-lock.yaml Removes duplicate entries introduced by the prior lockfile merge conflict; lockfile is now clean.
frontend/pnpm-workspace.yaml Adds allowBuilds for sharp and unrs-resolver to allow postinstall scripts for those native packages.

Sequence Diagram

sequenceDiagram
    participant WS as WebSocket
    participant EC as EventsContext
    participant UE as useEvents (hook)
    participant H as Consumer Hook

    WS->>EC: onmessage(raw)
    Note over EC: Drop if visibilityState === hidden
    EC->>EC: JSON.parse → ServerMessage
    loop for each event in Events[]
        EC->>EC: "eventType = evt.payload.type"
        loop for each Subscriber
            alt "sub.eventTypes === null OR has(eventType)"
                EC->>UE: callback(evt)
                UE->>H: onEventRef.current(evt)
            else filtered out
                EC-->>EC: skip
            end
        end
    end
    Note over UE: Subscribes with stable module-level eventTypes[] constant
Loading

Reviews (6): Last reviewed commit: "fix(backend): resolve clippy lints (#101..." | Re-trigger Greptile

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml
Comment on lines +43 to +57
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: frontend/pnpm-lock.yaml
- run: pnpm install --frozen-lockfile

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 next build runs without required env vars

frontend/config/env.ts exposes NEXT_PUBLIC_EVENTS_WS_URL via getEnvOrThrow, which throws if the variable is unset. While the getter is lazy and won't fire during the webpack compile pass itself, any page that calls publicEnv.EVENTS_WS_URL during server-side rendering or static generation will cause next build to throw and fail the job. Consider adding an env: block (using GitHub Actions secrets) or providing dummy values so the build job gives reliable signal rather than potentially failing for a config reason instead of a code reason.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/ci.yml
Line: 43-57

Comment:
**`next build` runs without required env vars**

`frontend/config/env.ts` exposes `NEXT_PUBLIC_EVENTS_WS_URL` via `getEnvOrThrow`, which throws if the variable is unset. While the getter is lazy and won't fire during the webpack compile pass itself, any page that calls `publicEnv.EVENTS_WS_URL` during server-side rendering or static generation will cause `next build` to throw and fail the job. Consider adding an `env:` block (using GitHub Actions secrets) or providing dummy values so the build job gives reliable signal rather than potentially failing for a config reason instead of a code reason.

How can I resolve this? If you propose a fix, please make it concise.

@kyscott18 kyscott18 force-pushed the ci/unified-frontend-workflow branch from 90e1aac to 75e5e79 Compare June 9, 2026 13:58
@kyscott18 kyscott18 changed the base branch from main to smooth-transaction-volume-chart June 9, 2026 13:59
@kyscott18 kyscott18 changed the title ci: unified frontend workflow (lint + typecheck + build) ci: unified workflow (lint + typecheck + build + rust) Jun 9, 2026
…ipeline (#98)

**Motivation:**

After ~1h on node.monad.xyz the renderer process is killed for OOM. There is
no single growing array — every component bounds its state — but at ~200 TPS
the per-event fan-out from EventsContext drives enough short-lived allocations
to fragment the heap. Backgrounded tabs are worse because the browser does not
throttle WebSocket onmessage.

**Modifications:**

1. Memoize EventsContext value so consumers don't re-render every time
   TopAccesses updates.
2. Drop WebSocket messages while document.visibilityState === 'hidden' to
   avoid running the dispatch + decode pipeline for an invisible tab.
3. Move the in-flight block's transactions out of React state into a
   ref-backed Map<txnIndex, Transaction>. Per-event updates are now O(1)
   instead of O(N), and the block is materialized into React state once at
   BlockFinalized/BlockVerified.
4. Allow subscribers to register an eventTypes filter on subscribe, and
   apply it at dispatch time so swap/transfer/totals hooks no longer run
   on BlockStart/TxnHeaderStart/etc.

**Result:**

Live event dispatch does far less work per WebSocket message, in-flight
blocks no longer reallocate their transactions array on every txn event,
and a backgrounded tab is effectively idle until it becomes visible again.

Co-authored-by: dak-agent[bot] <284037069+dak-agent[bot]@users.noreply.github.com>
* feat(tps-chart): smoothly extend the line to each new point

Switch the X axis to a continuous time scale whose right edge eases
toward the newest point's timestamp each animation frame. A freshly
appended point sits just past the edge (clipped by allowDataOverflow)
and is revealed sliding in from the right instead of snapping into a
discrete category slot; the animation halts once the edge catches up, so
the chart is still between points. isAnimationActive stays disabled to
avoid Recharts re-animation loops on every TPS event.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: update pnpm lockfile and allow sharp/unrs-resolver builds

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* drawing lines smoothly between the points creation

* fix the x absis to have only 1 now

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…orkflow

# Conflicts:
#	frontend/components/network-activity-tracker/tps-chart.tsx
* fix(backend): resolve auto-fixable clippy lints

Addresses 6 of the 8 clippy findings surfaced by the new rust CI job:
- needless_return (server.rs)
- match_like_matches_macro (server.rs)
- ptr_arg: &Vec<T> -> &[T] (event_filter.rs)
- needless_borrow (event_filter.rs)
- manual_is_multiple_of (event_listener.rs)
- clone_on_copy (serializable_event.rs)

Remaining (require manual judgment, deferred): large_enum_variant
(server.rs), should_implement_trait for from_str (event_listener.rs).

* fix(backend): resolve non-auto-fixable clippy lints

- large_enum_variant: box the 640-byte Event variant of EventDataOrMetrics
  (Event(Box<EventData>)). Since From::from infers its parameter type from
  the argument (deref coercion does not apply), the match-site call passes
  &*event_data to select From<&EventData>; construction uses Box::new(..).
- should_implement_trait: rename inherent EventName::from_str -> from_name
  (and its single caller) so it no longer shadows std::str::FromStr::from_str.

* fix(backend): remove redundant u64 casts in client (unnecessary_cast)

Surfaced once the lib compiled clean: timestamp_ns is u64, so the
(u64 - u64) as u64 casts are redundant; drop the cast and parens.
@Camillebzd Camillebzd merged commit 709e2d3 into smooth-transaction-volume-chart Jun 11, 2026
10 checks passed
@Camillebzd Camillebzd deleted the ci/unified-frontend-workflow branch June 11, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants