From d29a4ba8dab43e8a6a6fb7844d21efe5d7d69fdb Mon Sep 17 00:00:00 2001 From: obchain Date: Wed, 27 May 2026 15:41:07 +0530 Subject: [PATCH 1/3] =?UTF-8?q?feat(ci):=20GitHub=20Actions=20workflow=20?= =?UTF-8?q?=E2=80=94=20rust=20+=20go=20+=20frontend=20+=20e2e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four parallel jobs, ubuntu-latest, no deploy step: rust: fmt --check, clippy -D warnings, cargo test on the workspace go: go vet, go test, go build (smoke catches the binary) frontend: pnpm lint, typecheck, build e2e: scripts/e2e-smoke.sh — needs the three above so the integration job only runs once unit checks are green Triggers on push to main and on every pull_request. concurrency group cancels superseded runs on the same ref. RUSTFLAGS=-D warnings keeps warning regressions from sneaking in via test-only targets. Caching: - Swatinem/rust-cache for the workspace (shared between rust + e2e under separate keys so debug + release builds don't thrash each other) - actions/setup-go built-in module cache - actions/setup-node + pnpm store via pnpm/action-setup - actions/setup-python for the WS verifier's websockets lib e2e bumps ENGINE_WAIT_S to 360 s and WS_TIMEOUT_S to 120 s — runners are CPU-modest and cold-start the Deribit instrument enumeration noticeably slower than the dev box. Logs from /tmp/volx-e2e-* upload as an artifact on failure so a regression bisects without re-running the workflow. Deleted the empty deploy.yml scaffold; M3 will reintroduce deployment when public-launch direction is settled. --- .github/workflows/ci.yml | 150 +++++++++++++++++++++++++++++++++++ .github/workflows/deploy.yml | 0 2 files changed, 150 insertions(+) delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e69de29..1f73fef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -0,0 +1,150 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +# A new push to the same branch supersedes the prior run. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 # incremental adds no value in CI, hurts caching + RUSTFLAGS: -D warnings + +jobs: + # --------------------------------------------------------------------------- + # Rust: fmt + clippy + test on the four-crate workspace. + # --------------------------------------------------------------------------- + rust: + name: rust (fmt + clippy + test) + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + + - name: install rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: "1.85" + components: rustfmt, clippy + + - name: cargo cache + uses: Swatinem/rust-cache@v2 + + - run: cargo fmt --all -- --check + - run: cargo clippy --workspace --all-targets -- -D warnings + - run: cargo test --workspace --all-features + + # --------------------------------------------------------------------------- + # Go: vet + test under api/. + # --------------------------------------------------------------------------- + go: + name: go (vet + test) + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + working-directory: api + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: "1.25" + cache-dependency-path: api/go.sum + + - run: go vet ./... + - run: go test ./... + - run: go build -o /tmp/api-bin ./cmd/api + + # --------------------------------------------------------------------------- + # Frontend: lint + typecheck + build. + # --------------------------------------------------------------------------- + frontend: + name: frontend (lint + typecheck + build) + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + working-directory: frontend + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: "9.15.0" + + - uses: actions/setup-node@v4 + with: + node-version: "22" + cache: pnpm + cache-dependency-path: frontend/pnpm-lock.yaml + + - run: pnpm install --frozen-lockfile + - run: pnpm lint + - run: pnpm typecheck + - run: pnpm build + + # --------------------------------------------------------------------------- + # Integration: full local pipeline via scripts/e2e-smoke.sh. + # + # Deribit is reached from the runner — this can flake on upstream outages. + # If the public-net dependency proves too noisy a follow-up will move it + # behind a manual trigger; for now it gates merges because that is the + # entire point of having M1's smoke harness committed. + # --------------------------------------------------------------------------- + e2e: + name: e2e (local pipeline smoke) + runs-on: ubuntu-latest + timeout-minutes: 25 + needs: [rust, go, frontend] + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: "1.85" + + - uses: actions/setup-go@v5 + with: + go-version: "1.25" + cache-dependency-path: api/go.sum + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: cargo cache (release profile) + uses: Swatinem/rust-cache@v2 + with: + # Smoke uses release binaries; reusing the rust job's debug-profile + # cache key would invalidate immediately. Separate namespace. + key: e2e-release + + - run: pip install "websockets>=12,<13" + + - name: run e2e smoke + env: + # ubuntu-latest runners are CPU-modest and cold; give the engine + # more room than the dev-box default. Two engine cycles + safety + # margin after Deribit instrument enumeration. + ENGINE_WAIT_S: "360" + WS_TIMEOUT_S: "120" + PYTHON_BIN: python3 + run: bash scripts/e2e-smoke.sh + + - name: upload smoke logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-logs + path: /tmp/volx-e2e-*/ + if-no-files-found: ignore + retention-days: 7 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index e69de29..0000000 From 48fccc938496179d13647e1a948014822204a021 Mon Sep 17 00:00:00 2001 From: obchain Date: Wed, 27 May 2026 17:55:16 +0530 Subject: [PATCH 2/3] fix(ci): use stable rustc, bump workspace MSRV to 1.89 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first CI run failed with: rustc 1.85.1 is not supported by the following packages: clickhouse@0.15.0 requires rustc 1.89.0 clickhouse-macros@0.3.0 requires rustc 1.89.0 clickhouse-types@0.1.2 requires rustc 1.89.0 Cargo.toml claimed `rust-version = "1.85"` but the clickhouse dep family that landed with the storage layer (#50) pulled in transitive crates whose MSRV is 1.89. Bump the workspace MSRV to match dep reality and let CI track current stable instead of pinning a specific version — otherwise every dep MSRV bump requires a workflow edit. --- .github/workflows/ci.yml | 8 ++++++-- Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f73fef..edca317 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,11 @@ jobs: - name: install rust toolchain uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.85" + # Track current stable. clickhouse 0.15 brought in deps whose MSRV + # is 1.89 — pinning a specific version means we have to chase those + # bumps manually. Cargo.toml's `rust-version` is the authoritative + # MSRV claim; stable here is "the highest rustc that satisfies it". + toolchain: stable components: rustfmt, clippy - name: cargo cache @@ -110,7 +114,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.85" + toolchain: stable - uses: actions/setup-go@v5 with: diff --git a/Cargo.toml b/Cargo.toml index 214d645..055cf9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ [workspace.package] edition = "2024" -rust-version = "1.85" +rust-version = "1.89" version = "0.1.0" license = "MIT" authors = ["obchain "] From 085a740059ece93c2a04c3fb6582693e98a72eb5 Mon Sep 17 00:00:00 2001 From: obchain Date: Wed, 27 May 2026 18:08:22 +0530 Subject: [PATCH 3/3] fix(normalizer): collapse nested if-let into && let chains CI under -D warnings failed on clippy::collapsible_if at the two sink::shutdown paths. Edition 2024 + rustc 1.89+ let-chain syntax collapses the pair into a single `&&`-joined condition. Pre-existing local clippy passed because RUSTFLAGS was not set; CI now exercises the strict warning posture this PR introduces. --- crates/normalizer/src/sink/clickhouse.rs | 8 ++++---- crates/normalizer/src/sink/redis.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/normalizer/src/sink/clickhouse.rs b/crates/normalizer/src/sink/clickhouse.rs index 8280ccc..aab9f13 100644 --- a/crates/normalizer/src/sink/clickhouse.rs +++ b/crates/normalizer/src/sink/clickhouse.rs @@ -185,10 +185,10 @@ impl ClickHouseBatcher { pub async fn shutdown(self) { let Self { tx, join, .. } = self; drop(tx); - if let Some(join) = join { - if let Err(e) = join.await { - error!(error = ?e, "clickhouse worker join error"); - } + if let Some(join) = join + && let Err(e) = join.await + { + error!(error = ?e, "clickhouse worker join error"); } } } diff --git a/crates/normalizer/src/sink/redis.rs b/crates/normalizer/src/sink/redis.rs index 5ef0c13..5ce3df1 100644 --- a/crates/normalizer/src/sink/redis.rs +++ b/crates/normalizer/src/sink/redis.rs @@ -140,10 +140,10 @@ impl RedisPublisher { pub async fn shutdown(self) { let Self { tx, join, .. } = self; drop(tx); - if let Some(join) = join { - if let Err(e) = join.await { - error!(error = ?e, "redis worker join error"); - } + if let Some(join) = join + && let Err(e) = join.await + { + error!(error = ?e, "redis worker join error"); } } }