Merge pull request #371 from ai-2070/renovate/lock-file-maintenance #5873
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
| name: CI | |
| on: | |
| push: | |
| # Branches only — without this filter GitHub fires `push` | |
| # events on tag pushes too, so every `cli-v*` / `deck-v*` | |
| # release tag spawns a duplicate CI run alongside its | |
| # release workflow. The release workflows themselves run | |
| # their own build + tests against the same SHA; we don't | |
| # need CI to repeat them per tag. | |
| branches: ["**"] | |
| paths: | |
| - "net/**" | |
| - "go/**" | |
| - ".github/workflows/ci.yml" | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| unit-tests: | |
| name: Unit tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-unit-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Run unit tests | |
| run: cargo test --lib --features "net redex cortex netdb" | |
| # Doctests live in `///` comment blocks across `src/` and `sdk/src/`. | |
| # `cargo test --lib` does not execute them — they need a separate | |
| # `cargo test --doc` invocation. Same feature set as the unit-test | |
| # run so doc examples gated on those features compile. | |
| - name: Run doctests | |
| if: ${{ !cancelled() }} | |
| run: cargo test --doc --features "net redex cortex netdb" | |
| # `deck` is a separate workspace member (TUI operator console). | |
| # It's a binary-only package — `[[bin]]` with no `[lib]` — so | |
| # `--lib` / `--doc` would fail with "no library targets found". | |
| # Its `#[test]` modules live alongside the binary sources; | |
| # `--bins` compiles them into the binary's test harness. | |
| - name: Run Deck unit tests | |
| if: ${{ !cancelled() }} | |
| run: cargo test -p net-deck --bins | |
| integration-tests: | |
| name: Integration tests (Net, 3-node, Mikoshi, RedEX, CortEX, NetDB, nRPC, Dataforts, MeshDB, MeshOS) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-integration-${{ hashFiles('**/Cargo.lock') }} | |
| # nextest gives us per-test process isolation, smarter scheduling, | |
| # and `--no-fail-fast` semantics across grouped test binaries. | |
| # Tests below are batched by feature set so cargo recompiles the | |
| # library at most once per group instead of once per `--test` flag. | |
| - name: Install cargo-nextest | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: nextest | |
| # redis and jetstream integration tests are intentionally skipped: | |
| # `required-features = ["redis" | "jetstream"]` in Cargo.toml excludes | |
| # them from compilation under this feature set. Wire them in separately | |
| # once CI service containers are added. | |
| # === Bus + FFI (no features) ======================================== | |
| - name: Bus + FFI | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast | |
| --test bus_shutdown_drain | |
| --test bus_stranded_flush | |
| --test ffi_shutdown_race | |
| --test ffi_poll_buffer | |
| # === Net mesh + capability + discovery + migration + nRPC dispatch == | |
| # All --features net tests share one compile. | |
| - name: Net mesh, capability, migration, nRPC dispatch | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features net | |
| --test integration_net | |
| --test three_node_integration | |
| --test channel_auth | |
| --test channel_auth_hardening | |
| --test connect_post_start | |
| --test failure_detector_matrix | |
| --test parallel_bind_stress | |
| --test peer_death_evicts_peer_map | |
| --test send_subprotocol_malformed | |
| --test subnet_enforcement | |
| --test integration_placement_filter_callback | |
| --test capability_broadcast | |
| --test capability_multihop | |
| --test capability_scope | |
| --test capability_auth_call_path | |
| --test capability_auth_conformance | |
| --test capability_schema_doc_guard | |
| --test chain_discovery | |
| --test cross_lang_capability_fixtures | |
| --test migration_integration | |
| --test migration_target_failure_mid_chunking | |
| --test netsocket_production_defaults | |
| --test parsed_packet_short_input | |
| --test proxy_coverage_gaps | |
| --test stream_config_and_error_display | |
| # === NAT traversal ================================================== | |
| - name: NAT traversal | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features "net nat-traversal" | |
| --test connect_direct | |
| --test nat_classify | |
| --test peer_death_clears_capability_index | |
| --test punch_keepalive | |
| --test punch_keepalive_timing | |
| --test reflex_probe | |
| --test reflex_override | |
| --test rendezvous_ack | |
| --test rendezvous_coordinator | |
| # === Port mapping (UPnP-IGD / NAT-PMP / PCP) ======================== | |
| - name: Port mapping | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features "net port-mapping" | |
| --test port_mapping_null | |
| --test port_mapping_real_router | |
| # === RedEX ========================================================== | |
| # `redex` chains to `net` in Cargo.toml (redex = ["net", ...]) so a | |
| # single --features redex covers the e2e suite as well. | |
| - name: RedEX | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features redex | |
| --test integration_redex | |
| --test redex_replication_dst | |
| --test redex_replication_e2e | |
| # === CortEX + nRPC service surface ================================== | |
| # `tool` chains to `cortex` (see `tool = ["cortex"]` in | |
| # Cargo.toml), so adding it here is feature-graph-cheap and | |
| # keeps `integration_tool_announce` — the substrate-side | |
| # serve_tool / announce / tool_metadata.fetch contract pin — | |
| # in this group rather than spawning a fourth compile pass. | |
| - name: CortEX + nRPC + AI Tools | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features "cortex tool" | |
| --test integration_cortex_adapter | |
| --test integration_cortex_tasks | |
| --test integration_cortex_memories | |
| --test cortex_ryw_global_cap | |
| --test integration_mesh_cancel | |
| --test integration_nrpc_loopback | |
| --test integration_nrpc_mesh | |
| --test integration_nrpc_streaming | |
| --test integration_nrpc_client_streaming | |
| --test integration_nrpc_duplex | |
| --test integration_nrpc_service_discovery | |
| --test integration_nrpc_predicate_header | |
| --test integration_nrpc_cross_lang | |
| --test integration_nrpc_cross_lang_streaming | |
| --test integration_tool_announce | |
| --test nrpc_inbound_dispatcher | |
| --test queue_group_dispatch | |
| --test aggregator_fold_query | |
| --test aggregator_registry_rpc | |
| # === NetDB ========================================================== | |
| - name: NetDB | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features netdb | |
| --test integration_netdb | |
| --test netdb_builder_and_accessors | |
| # === Dataforts (greedy + gravity) =================================== | |
| - name: Dataforts greedy + gravity | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features dataforts | |
| --test dataforts_greedy_e2e | |
| --test dataforts_gravity_e2e | |
| # === Scheduled-stream batched drain (Linux sendmmsg send path) ====== | |
| # The whole NRPC_SEND_LOOP_BATCHING_PLAN gate, in one compile. The | |
| # scheduled-stream egress ships packets via the send loop's batched, | |
| # group-by-destination drain, which calls `sendmmsg` behind | |
| # `cfg(target_os = "linux")` — a block that does not compile on the | |
| # macOS dev host, so this Linux job is the gate that actually compiles | |
| # AND exercises it. `dataforts` pulls in `net`, so all three drain | |
| # tests build under one feature set: | |
| # - send_drain_depth — floods 16 concurrent scheduled streams, | |
| # prints the packets/syscall-collapse factor; | |
| # - scheduled_stream — pins the scheduled-vs-direct routing; | |
| # - scheduled_stream_integrity — fetches blobs over reliable scheduled | |
| # streams and asserts BYTE-FOR-BYTE delivery through the batch path | |
| # (incl. a tiny-send-buffer phase that forces the sendmmsg partial | |
| # -send / EWOULDBLOCK tail), the integrity check the others can't make. | |
| # `--no-capture` surfaces the measurement + verified-blob/flush counts. | |
| - name: Scheduled-stream batched drain (Linux sendmmsg path) | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features dataforts --no-capture | |
| --test send_drain_depth | |
| --test scheduled_stream | |
| --test scheduled_stream_integrity | |
| # === Batched ingress (Linux recvmmsg receive path) ================== | |
| # The NRPC_RECV_LOOP_BATCHING_PLAN gate. The mesh receive loop drains the | |
| # socket via `recvmmsg` (BatchedPacketReceiver) when | |
| # `MeshNodeConfig::with_batched_ingress(true)` is set — a path behind | |
| # `cfg(target_os = "linux")` that does not compile on the macOS dev host, | |
| # so this Linux job is the gate that compiles AND exercises it. | |
| # - batched_ingress_integrity — fetches blobs concurrently into a | |
| # fetcher built with batched ingress and asserts BYTE-FOR-BYTE | |
| # delivery, then that the batched recv path actually carried the bulk | |
| # (`recv_batch_stats().syscalls > 0`) — the assertion that only fires | |
| # on Linux where the recvmmsg path is live. | |
| # - recv_drain_depth — floods a node with fire-and-forget datagrams (no | |
| # reliability, so no retransmit-exhaustion flakiness) and asserts the | |
| # recvmmsg path collapsed syscalls (`packets > syscalls`), printing the | |
| # packets/syscall factor — the heavy-load recv analogue of | |
| # send_drain_depth. | |
| # `--no-capture` surfaces the packets/recvmmsg-batch collapse counts. | |
| - name: Batched ingress (Linux recvmmsg path) | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features dataforts,batched-ingress --no-capture | |
| --test batched_ingress_integrity | |
| --test recv_drain_depth | |
| # === Dataforts blob e2e (multi-node + migration) ==================== | |
| # `redex-disk` is required so MeshBlobAdapter can spin up a real | |
| # on-disk RedEX per node — separate from the in-memory dataforts | |
| # group above so the on-disk paths get compiled. | |
| - name: Dataforts blob e2e | |
| if: ${{ !cancelled() }} | |
| run: cargo nextest run --no-fail-fast --features "dataforts redex-disk" --test dataforts_blob_e2e | |
| # === Transport C ABI error-code mirror ============================== | |
| # Parses `include/net_transport.h` and asserts every `#define | |
| # NET_*` matches its Rust `pub const NET_*` sibling. Gated on | |
| # `net + dataforts + netdb + redex-disk` per the test's cfg. | |
| - name: Transport error-code mirror | |
| if: ${{ !cancelled() }} | |
| run: cargo nextest run --no-fail-fast --features "net dataforts netdb redex-disk" --test transport_error_codes | |
| # === Dataforts net-blob CLI ========================================= | |
| # Pulls in clap via the `cli` feature; kept separate so the | |
| # non-CLI dataforts groups don't pay the clap compile cost. | |
| - name: Dataforts net-blob CLI | |
| if: ${{ !cancelled() }} | |
| run: cargo nextest run --no-fail-fast --features "dataforts cli" --test net_blob_cli | |
| # === Dataforts blob v0.3 conformance (Tree + CDC + RS) ============== | |
| # Phase-pinned end-to-end conformance tests for the v0.3 blob | |
| # storage track. Each test runs at CI-feasible scale (default | |
| # parameters tuned for the runner's per-test memory budget; the | |
| # 100 GiB real-scale variant in the Tree test is `#[ignore]`'d | |
| # and opt-in via `-- --ignored` for release validators): | |
| # | |
| # - Tree (Phase A8): byte-identical round-trip, determinism, | |
| # manifest LRU effectiveness, manifest-body-explosion guard. | |
| # - CDC (Phase B4): end-to-end determinism, dedup-after-edit | |
| # ratio under one-byte flip + suffix-shift insert. | |
| # - RS (Phase C9): round-trip with all chunks present, m-chunk- | |
| # loss reconstruction, m+1-loss unrecoverable, cross-adapter | |
| # determinism. | |
| - name: Dataforts blob v0.3 conformance | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features dataforts | |
| --test dataforts_blob_v3_tree_conformance | |
| --test dataforts_blob_v3_cdc_conformance | |
| --test dataforts_blob_v3_rs_conformance | |
| --test dataforts_blob_v3_composed_conformance | |
| # === MeshDB ========================================================= | |
| # `meshdb` chains to cortex → redex → net, so a single | |
| # --features meshdb covers the test's `feature = "net" + "meshdb"` | |
| # gate. | |
| - name: MeshDB | |
| if: ${{ !cancelled() }} | |
| run: cargo nextest run --no-fail-fast --features meshdb --test meshdb_subprotocol_wire | |
| # === MeshOS + Deck ================================================== | |
| # `meshos` chains to cortex → redex → net. The pipeline test pins | |
| # the contract between MeshOsLoop reconcile → admit → | |
| # ActionDispatcher across phases; the deck test pins the operator | |
| # surface (DeckClient → AdminCommands → in-process MeshOsRuntime) | |
| # that Deck-the-binary composes against. Both share the same | |
| # `meshos` gate and run in one cargo invocation. | |
| - name: MeshOS + Deck | |
| if: ${{ !cancelled() }} | |
| run: > | |
| cargo nextest run --no-fail-fast --features meshos | |
| --test meshos_pipeline | |
| --test deck_pipeline | |
| loom-tests: | |
| name: Loom concurrency models | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| # Loom builds need their own cache key — the `--cfg loom` | |
| # RUSTFLAGS pulls in a different set of dev-deps (`loom` | |
| # itself is `[target.'cfg(loom)'.dev-dependencies]`) and | |
| # rebuilds every atomic-touching crate with loom's | |
| # substitute primitives. Sharing the cache with non-loom | |
| # jobs would just thrash both. | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-loom-${{ hashFiles('**/Cargo.lock') }} | |
| # Loom tests exhaustively explore thread interleavings; release | |
| # mode is mandatory (debug builds are too slow to converge in CI | |
| # time budget). The models in `loom_models.rs` use loom's | |
| # substitute atomics standalone, not the production types, so | |
| # the test only imports from `loom` itself. | |
| # | |
| # `--no-default-features` skips compiling the `net` feature's | |
| # `adapter::net` module: tokio gates `tokio::net::*` out under | |
| # `#![cfg(not(loom))]`, and `adapter::net::{proxy, router, | |
| # transport}` use `tokio::net::UdpSocket` extensively. Trying | |
| # to compile the lib's net stack under `--cfg loom` fails on | |
| # the missing tokio::net module. The loom test itself doesn't | |
| # touch the net stack, so this is purely a build-time gate | |
| # for the lib that the test target implicitly depends on. | |
| - name: Run loom models | |
| run: cargo test --release --no-default-features --test loom_models | |
| env: | |
| RUSTFLAGS: --cfg loom | |
| rust-sdk-tests: | |
| name: Rust SDK tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net/sdk | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-sdk-${{ hashFiles('**/Cargo.lock') }} | |
| # Feature set covers every SDK integration test except | |
| # `redis_dedup_contract` (gated on `redis`, deferred until CI | |
| # service containers land — same policy as the main crate's | |
| # `integration_redis`). Without this width, tests gated on | |
| # `cortex` / `testing` / `compute` / `nat-traversal` / | |
| # `port-mapping` / `tool` / `macros` compile to empty test | |
| # binaries and the contract goes silently unverified. | |
| # `cargo test` auto-discovers every `tests/*.rs` file under | |
| # `sdk/tests/`; the step name calls out the load-bearing | |
| # ones so a missing test binary is obvious in the CI log: | |
| # - mesh_stream_backpressure — substrate flow-control pin | |
| # - mesh_rpc_bidi_typed — Phase E client-streaming + | |
| # duplex typed SDK surface (5 tests). Gated on | |
| # `feature = "net" + "cortex"`, both present here. | |
| # - tool_serve_round_trip — Mesh::serve_tool + call_tool + | |
| # watch_tools live two-mesh path. Gated on | |
| # `feature = "tool" + "cortex"`. | |
| # - tool_format_golden_vectors — T-1 byte-equality | |
| # verifier (openai / anthropic / mcp / gemini lowering + | |
| # reverse). Gated on `feature = "tool"`. | |
| # - tool_event_golden_vectors — T-2 ToolEvent envelope | |
| # round-trip verifier. Gated on `feature = "tool"`. | |
| # - tool_macro — `#[tool]` proc-macro | |
| # expansion + serve-helper round-trip. Gated on | |
| # `feature = "macros" + "cortex"`. | |
| - name: Run Rust SDK tests (includes mesh_stream_backpressure, mesh_rpc_bidi_typed, tool_*) | |
| run: cargo test --features "net cortex dataforts testing compute nat-traversal port-mapping aggregator tool macros" | |
| # SDK doctests — `///` examples in `sdk/src/`. Same feature set | |
| # as the test run so doc examples gated on those features | |
| # compile. | |
| - name: Run Rust SDK doctests | |
| if: ${{ !cancelled() }} | |
| run: cargo test --doc --features "net cortex testing compute nat-traversal port-mapping tool macros" | |
| node-tests: | |
| name: Node bindings tests (vitest) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net/bindings/node | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-node-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Install npm dependencies | |
| run: npm i | |
| # Build napi binding with the features the vitest suite covers: | |
| # `net` for the mesh surface + `cortex` for the CortEX / NetDB | |
| # tests + `compute` for the MeshDaemon / migration tests + | |
| # `groups` for the `ReplicaGroup` / `ForkGroup` / `StandbyGroup` | |
| # tests (Stages 3 + 4 of `SDK_COMPUTE_SURFACE_PLAN` and | |
| # `SDK_GROUPS_SURFACE_PLAN`) + `test-helpers` so | |
| # `_testInjectSyntheticPeer` is exported for the group-placement | |
| # fixtures. | |
| # | |
| # `cortex` transitively enables redex + netdb via the binding's | |
| # feature graph. Skip the `redis` default — the Node suite | |
| # doesn't hit it, and pulling it in would need a service | |
| # container. | |
| # | |
| # Invoke napi directly (not `npm run build:test`) so we can pass | |
| # `--no-default-features` to suppress `redis`; the package.json | |
| # scripts bake `redis` in for consumers who want the full | |
| # surface from source. | |
| - name: Build native module | |
| working-directory: net/crates/net/bindings/node | |
| run: npx napi build --platform --no-default-features --features net,cortex,compute,groups,meshos,deck,meshdb,aggregator,tool,test-helpers | |
| # Compile the sibling .ts shims (meshdb.ts, mesh_rpc.ts, errors.ts) | |
| # into .js so `require('../meshdb')` in the test suite resolves. | |
| # `napi build` only produces the native `.node` artifact; the | |
| # AsyncIterable shim that augments MeshQueryStream is plain TS | |
| # that needs its own tsc pass. | |
| - name: Build TypeScript shims | |
| working-directory: net/crates/net/bindings/node | |
| run: npm run build:ts | |
| - name: Run tests | |
| run: npm test | |
| sdk-ts-tests: | |
| name: TypeScript SDK tests (vitest + tsc) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net/sdk-ts | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-sdk-ts-${{ hashFiles('**/Cargo.lock') }} | |
| # `sdk-ts/package.json` carries `@net-mesh/core: file:../bindings/node` | |
| # as a devDependency, so `npm i` over there picks up the sibling | |
| # binding from the working tree. The binding's `.node` cdylib has | |
| # to be built first or `npm test` will fail to load it. | |
| # | |
| # Feature flags MUST include `redis` even though the suite never | |
| # opens a Redis connection: `sdk-ts/src/redis-dedup.ts` does a | |
| # real `export { RedisStreamDedup } from '@net-mesh/core'`, and the | |
| # napi-generated `index.d.ts` only carries the `RedisStreamDedup` | |
| # declaration when the binding was built with the `redis` | |
| # feature. Without it, tsc fails the SDK build with | |
| # `Module '"@net-mesh/core"' has no exported member | |
| # 'RedisStreamDedup'`. The runtime side is also satisfied — the | |
| # `.node` cdylib carries the class — but the runtime never opens | |
| # a connection because no SDK code instantiates the helper in | |
| # the test suite. | |
| # | |
| # `test-helpers` is required so `_testInjectSyntheticPeer` is | |
| # exported for the group-placement fixtures — | |
| # `sdk-ts/test/groups.test.ts` uses the same hook the bindings | |
| # suite does. | |
| - name: Build native module | |
| working-directory: net/crates/net/bindings/node | |
| run: | | |
| npm i --ignore-scripts | |
| npx napi build --platform --no-default-features --features redis,net,cortex,compute,groups,meshos,deck,meshdb,aggregator,tool,test-helpers,dataforts | |
| - name: Install npm dependencies | |
| run: npm i | |
| # `tsc` first — the v0.11 `originHash` widening (u32 → u64, | |
| # number → bigint) cascaded through every method signature and | |
| # interface in the SDK's source. Type-check failures here mean | |
| # the SDK's type surface drifted away from the binding's | |
| # generated `.d.ts`; surface them as a CI failure rather than | |
| # only as a `npm run build` failure on a developer workstation. | |
| - name: Type-check (tsc) | |
| run: npm run build | |
| # vitest auto-discovers everything under `test/`. Notable | |
| # deck-specific coverage exercised by this step: | |
| # - test/deck.test.ts — Symbol.asyncDispose hook shape + | |
| # runtime drain. The runtime test promotes the "binding | |
| # stale" skip to a hard failure when CI=true, so a | |
| # misconfigured --features list (missing `deck`) above | |
| # fails loudly rather than silently skipping. | |
| - name: Run vitest | |
| run: npm test | |
| python-tests: | |
| name: Python bindings tests (pytest) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net/bindings/python | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| # Match `net/crates/net/rust-toolchain.toml` directly so the | |
| # pinned 1.96.0 toolchain is installed up-front rather than | |
| # auto-fetched mid-`maturin develop` by rustup (which has flaked | |
| # — partial download leaves `rustc` absent on the new toolchain). | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: "1.96.0" | |
| components: clippy, rustfmt, llvm-tools-preview | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-python-${{ hashFiles('**/Cargo.lock') }} | |
| # maturin develop requires a virtualenv (refuses to install into | |
| # the system Python). Create one and prepend it to PATH so every | |
| # subsequent step resolves `maturin`, `pip`, `pytest`, and the | |
| # installed `net` extension from the venv. | |
| - name: Create virtualenv | |
| run: | | |
| python -m venv .venv | |
| echo "${PWD}/.venv/bin" >> "$GITHUB_PATH" | |
| echo "VIRTUAL_ENV=${PWD}/.venv" >> "$GITHUB_ENV" | |
| - name: Install maturin and pytest | |
| # pytest-timeout surfaces the offending test on hangs — | |
| # without it, a deadlock anywhere in the suite ticks the | |
| # job-level timeout-minutes and the CI log gives no hint | |
| # which test was stuck. 60 s is generous for unit/integration | |
| # mesh tests on GHA; the longest legitimate test in the | |
| # suite is well under that. | |
| run: pip install --upgrade pip maturin pytest pytest-timeout | |
| # `net,cortex,compute,groups,meshdb,meshos,deck` mirrors the | |
| # Node binding's feature set for tests. `groups` is needed so | |
| # `test_groups.py` can import `ReplicaGroup` / `ForkGroup` / | |
| # `StandbyGroup` / `GroupError`; `meshdb` / `meshos` / `deck` | |
| # enable the corresponding test modules (each guarded by | |
| # `pytest.skip` when the feature is absent) plus the stub-drift | |
| # test's MeshDB class coverage. Default `redis` is omitted | |
| # because the suite doesn't exercise the Redis adapter. | |
| - name: Build and install bindings | |
| run: maturin develop --no-default-features --features net,cortex,compute,groups,meshdb,meshos,deck,aggregator,tool | |
| # `--timeout-method=thread` is critical for this FFI-heavy | |
| # suite: the default `signal` method only works while Python | |
| # is between bytecode instructions, so a deadlock inside a | |
| # pyo3 call (or in a Rust-spawned thread we're waiting on) | |
| # never gets interrupted. Thread-mode wakes a watchdog after | |
| # the deadline regardless of where the test is blocked and | |
| # dumps a full Python + C frame for the hung test. | |
| # | |
| # `--timeout=30` so even if a hang lands 19 min into the | |
| # run, the watchdog still has a minute of budget to dump the | |
| # offender before the 20-minute job ceiling fires. | |
| # | |
| # `-s` (`--capture=no`) disables pytest's stdout/stderr | |
| # capture so timeout dumps + faulthandler traces appear in | |
| # the GHA log live, not buffered behind a hung test's exit. | |
| # `PYTHONFAULTHANDLER=1` enables faulthandler at interpreter | |
| # startup so a hard hang in a Rust FFI call (where the | |
| # pytest-timeout thread can't print through pytest's capture) | |
| # still dumps a C-level stack when SIGSEGV/SIGABRT fires or | |
| # when the watchdog sends the dump signal. | |
| - name: Run tests | |
| env: | |
| PYTHONFAULTHANDLER: "1" | |
| PYTHONUNBUFFERED: "1" | |
| run: pytest -v -s --timeout=30 --timeout-method=thread | |
| sdk-py-tests: | |
| name: Python SDK tests (sdk-py, pytest) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net/sdk-py | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| # sdk-py is the pure-Python layer over the `net-mesh` bindings. | |
| # Its `tests/conftest.py` stubs the native `net` extension before | |
| # any SDK module loads, so the test run does not need maturin or | |
| # the Rust toolchain. `--no-deps` skips resolving the runtime | |
| # requirement against PyPI. | |
| - name: Install sdk-py (no deps) + test deps | |
| run: | | |
| pip install --upgrade pip | |
| pip install --no-deps -e . | |
| pip install pytest pydantic | |
| # pytest auto-discovers `tests/` per pyproject.toml's | |
| # `testpaths`. Notable deck-specific coverage: | |
| # - tests/test_deck_wrapper.py — wrapper-level | |
| # DeckClient.from_seed kwarg forwarding + | |
| # __enter__/__exit__ dunder dispatch (stubs the raw | |
| # pyo3 class so this stays a pure-Python test). | |
| - name: Run tests | |
| run: pytest -v | |
| go-tests: | |
| name: Go bindings tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: go/go.mod | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-go-${{ hashFiles('**/Cargo.lock') }} | |
| # The Go bindings link against SIX cdylibs via cgo: | |
| # - `-lnet` (libnet.so, the main `net-mesh` crate) from net.go | |
| # - `-lnet_compute` (libnet_compute.so, the `net-compute-ffi` | |
| # workspace member at bindings/go/compute-ffi) from compute.go | |
| # - `-lnet_meshdb` (libnet_meshdb.so, the `net-meshdb-ffi` | |
| # workspace member at bindings/go/meshdb-ffi) from meshdb.go | |
| # - `-lnet_meshos` (libnet_meshos.so, the `net-meshos-ffi` | |
| # workspace member at bindings/go/meshos-ffi) from meshos.go | |
| # - `-lnet_deck` (libnet_deck.so, the `net-deck-ffi` | |
| # workspace member at bindings/go/deck-ffi) from deck.go | |
| # - `-lnet_rpc` (libnet_rpc.so, the `net-rpc-ffi` | |
| # workspace member at bindings/go/rpc-ffi) from | |
| # mesh_rpc.go / mesh_rpc_typed.go / tool.go. Added in the | |
| # NET_GO_NRPC_PORT slices (G-1..G-5) — without it the | |
| # typed/streaming/tool tests fail at link. | |
| # All six end up in `net/crates/net/target/release/`. | |
| # | |
| # Features: | |
| # - `net-mesh` needs `netdb,dataforts,redex-disk,nat-traversal,redis` | |
| # for the mesh + cortex + blob + NAT + redis-dedup FFI surfaces | |
| # exercised by the Go test suite. `redis` only gates the | |
| # `RedisStreamDedup` symbol export — the dedup helper itself is | |
| # an in-memory LRU and does not need a Redis server at runtime. | |
| # - `net-compute-ffi` needs `test-helpers` so the FFI symbol | |
| # `net_compute_test_inject_synthetic_peer` (referenced by | |
| # `groups_testhelpers.go`) is exported. | |
| # - `net-meshdb-ffi`, `net-meshos-ffi`, `net-deck-ffi`, | |
| # `net-rpc-ffi` have no extra features beyond their defaults. | |
| # | |
| # Built as one cargo invocation so feature unification on the | |
| # shared `net-mesh` dep doesn't cause a second compilation pass. | |
| - name: Build net + net_compute + net_meshdb + net_meshos + net_deck + net_rpc cdylibs | |
| working-directory: net/crates/net | |
| run: > | |
| cargo build --release | |
| -p net-mesh -p net-compute-ffi -p net-meshdb-ffi -p net-meshos-ffi -p net-deck-ffi -p net-rpc-ffi | |
| --features "net-mesh/netdb,net-mesh/dataforts,net-mesh/redex-disk,net-mesh/nat-traversal,net-mesh/redis,net-compute-ffi/test-helpers" | |
| # `integration_test.go` gates its suite behind RUN_INTEGRATION_TESTS=1 | |
| # so local developers can run quick unit-style passes without the | |
| # full mesh setup. CI wants the full coverage. | |
| - name: Run Go tests | |
| working-directory: go | |
| env: | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/net/crates/net/target/release | |
| RUN_INTEGRATION_TESTS: "1" | |
| run: go test -v ./... | |
| # Run again with `-tags test_helpers` so the test-only files | |
| # (`groups_testhelpers.go`, `groups_test.go`, | |
| # `capability_aggregation_e2e_test.go`) compile and execute. | |
| # These reference FFI symbols gated behind the `test-helpers` | |
| # cargo feature on `net-compute-ffi` (already enabled in the | |
| # build step above) — without the Go build tag they're | |
| # excluded from the package compile and silently skipped. | |
| - name: Run Go tests (test_helpers) | |
| working-directory: go | |
| env: | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/net/crates/net/target/release | |
| RUN_INTEGRATION_TESTS: "1" | |
| run: go test -v -tags test_helpers ./... | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.lock') }} | |
| # Stage 4 of PANIC_AUDIT_AND_LINT_HARDENING_PLAN.md: production | |
| # code (lib + bins) is denied for the four panic-hygiene + unsafe | |
| # lints declared in `Cargo.toml`'s `[lints.clippy]` table. This | |
| # step has no `-A` overrides — any new `.unwrap()` / | |
| # `.expect()` / undocumented `unsafe` block / multi-op unsafe | |
| # block in lib / bin code fails CI here. `--all-targets` | |
| # coverage for OTHER clippy lints lives in the next step. | |
| - name: Run clippy (production code, strict) | |
| run: cargo clippy --all-features --lib --bins -- -D warnings | |
| # `--all-targets` adds clippy coverage for tests / benches / | |
| # examples. Tests are allowed to `.unwrap()` / `.expect()` freely | |
| # (~5000 sites across the test surface) and rarely contain | |
| # `unsafe`. The four lints from `[lints.clippy]` are silenced | |
| # here with `-A`. The `clippy::disallowed_methods` rule | |
| # (driven by `clippy.toml`) is silenced inside each test module | |
| # via inner `#![allow(clippy::disallowed_methods)]` attributes | |
| # — Cargo's `[lints]`-table-vs-CLI precedence quirks make a | |
| # blanket `-A` flag here unreliable. Every OTHER clippy lint | |
| # still fails on warning across all targets via `-D warnings`. | |
| - name: Run clippy (all targets, test surface allowed to panic) | |
| run: > | |
| cargo clippy --all-features --all-targets -- | |
| -D warnings | |
| -A clippy::unwrap_used | |
| -A clippy::expect_used | |
| -A clippy::undocumented_unsafe_blocks | |
| -A clippy::multiple_unsafe_ops_per_block | |
| # The `clippy` job above lints only the root `net` package — `cargo | |
| # clippy` without `--workspace` doesn't traverse workspace members, | |
| # and the bindings each need a different feature combination so a | |
| # single `--workspace --all-features` invocation isn't workable | |
| # either (the Python and Node bindings carry build-tool-specific | |
| # default features that conflict in CI). This matrix lints each | |
| # FFI / SDK crate with the same feature flags its build / test job | |
| # uses, so a clippy regression in any binding fails CI before it | |
| # lands. | |
| ffi-clippy: | |
| name: FFI clippy (${{ matrix.crate.name }}) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| crate: | |
| - name: rust-sdk | |
| path: net/crates/net/sdk | |
| # `full` enables every SDK feature flag (net, cortex, | |
| # compute, groups, redis, jetstream). Mirrors the | |
| # `rust-sdk-tests` job's surface plus the optional | |
| # adapter features. | |
| features: --features full | |
| - name: node | |
| path: net/crates/net/bindings/node | |
| # Mirrors the `node-tests` napi build (no redis default, | |
| # plus `test-helpers` so the test-only FFI symbols are | |
| # included in the lint set, plus `meshos,deck,meshdb` so | |
| # the MeshOS / Deck / MeshDB NAPI surfaces compile). | |
| features: --no-default-features --features net,cortex,compute,groups,meshos,deck,meshdb,aggregator,tool,test-helpers | |
| - name: python | |
| path: net/crates/net/bindings/python | |
| # Mirrors the `python-tests` `maturin develop` invocation | |
| # (plus `meshos,deck` so the corresponding pyo3 surfaces | |
| # are linted, plus `aggregator` so the aggregator pyo3 | |
| # surface is linted in lockstep with the test job). | |
| features: --no-default-features --features net,cortex,compute,groups,meshos,deck,aggregator,tool | |
| - name: go-compute-ffi | |
| path: net/crates/net/bindings/go/compute-ffi | |
| # Default features only — the cdylib production build | |
| # ships without `test-helpers`, and that is the surface | |
| # we want CI to enforce against. The `test-helpers` | |
| # symbols are exercised by the `go test` suite, not by | |
| # consumers. | |
| features: "" | |
| - name: go-rpc-ffi | |
| # nRPC FFI shim — carries the dispatcher trampolines | |
| # (`net_rpc_set_handler_dispatcher`, | |
| # `net_rpc_set_client_streaming_handler_dispatcher`, | |
| # `net_rpc_set_duplex_handler_dispatcher`, | |
| # `net_rpc_set_streaming_handler_dispatcher`) consumed | |
| # by `go/mesh_rpc.go`. Lint-coverage gap closed when the | |
| # streaming-serve dispatcher landed (G-1 of | |
| # NET_GO_NRPC_PORT). | |
| path: net/crates/net/bindings/go/rpc-ffi | |
| features: "" | |
| - name: go-meshdb-ffi | |
| path: net/crates/net/bindings/go/meshdb-ffi | |
| features: "" | |
| - name: go-meshos-ffi | |
| path: net/crates/net/bindings/go/meshos-ffi | |
| features: "" | |
| - name: go-deck-ffi | |
| path: net/crates/net/bindings/go/deck-ffi | |
| features: "" | |
| - name: sdk-macros | |
| # `net-mesh-sdk-macros` ships the `#[tool]` attribute | |
| # proc-macro. Linted separately from the SDK because the | |
| # proc-macro crate doesn't inherit feature flags from | |
| # its consumers — its public surface is the macro's | |
| # generated code, which the SDK's `tool_macro` | |
| # integration test covers separately at runtime. | |
| path: net/crates/net/sdk-macros | |
| features: "" | |
| - name: cli | |
| path: net/crates/net/cli | |
| # `net-cli` pulls the SDK in with the explicit feature | |
| # set its Cargo.toml declares; clippy honors that. | |
| # `--all-targets` covers the bin + integration test | |
| # crates under `tests/`. | |
| features: "" | |
| - name: deck | |
| path: net/crates/net/deck | |
| # The deck TUI binary's `unit-tests` step at the top | |
| # of this workflow runs its `#[cfg(test)] mod tests` | |
| # blocks, but clippy lints + module-level dead-code | |
| # checks weren't covered until this matrix entry. | |
| # Default features only — matches the cargo invocation | |
| # the test step uses, so what the binary ships gets | |
| # linted (not the `demo` feature, which is dev-only). | |
| features: "" | |
| - name: aggregator-daemon | |
| path: net/crates/net/aggregator-daemon | |
| # `net-aggregator-daemon` is a lib + bin crate that | |
| # hosts an AggregatorRegistry + the | |
| # `aggregator.registry` RPC service. `--all-targets` | |
| # covers the bin, lib, and the integration test crate | |
| # under `tests/`. Default features — the crate's | |
| # Cargo.toml pins its SDK feature set. | |
| features: "" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-clippy-ffi-${{ matrix.crate.name }}-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Run clippy | |
| working-directory: ${{ matrix.crate.path }} | |
| run: cargo clippy ${{ matrix.crate.features }} --all-targets -- -D warnings | |
| ffi-tests: | |
| # Executes `cargo test --lib` for each FFI shim crate. The | |
| # `ffi-clippy` matrix above lints these but never runs their | |
| # internal `#[cfg(test)] mod tests {}` blocks; pre-fix, ~85 | |
| # Rust unit tests in `bindings/go/*-ffi` and ~32 in the | |
| # node/python NAPI/PyO3 surfaces were silently uncovered. The | |
| # `rust-sdk` member is omitted — the dedicated `rust-sdk-tests` | |
| # job already covers its tests with a broader feature set. | |
| # | |
| # Notable deck-specific coverage in `go-deck-ffi`: | |
| # - ice_simulate_unknown_variant_leaves_husk_retryable | |
| # - ice_commit_unknown_variant_leaves_husk_retryable | |
| # (both use a thread-local fault-injection switch on | |
| # `build_core_proposal` to exercise the failure-branch | |
| # invariant — the husk stays retry-able when the variant | |
| # is unrecognised) | |
| # - audit_query_setters_set_last_error_on_null_query | |
| # (pins the last-error envelope on every NULL-arm return) | |
| name: FFI tests (${{ matrix.crate.name }}) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| crate: | |
| - name: node | |
| path: net/crates/net/bindings/node | |
| features: --no-default-features --features net,cortex,compute,groups,meshos,deck,aggregator,tool,test-helpers | |
| - name: python | |
| path: net/crates/net/bindings/python | |
| features: --no-default-features --features net,cortex,compute,groups,meshos,deck,aggregator,tool | |
| - name: go-compute-ffi | |
| path: net/crates/net/bindings/go/compute-ffi | |
| features: "" | |
| - name: go-rpc-ffi | |
| path: net/crates/net/bindings/go/rpc-ffi | |
| features: "" | |
| - name: go-meshdb-ffi | |
| path: net/crates/net/bindings/go/meshdb-ffi | |
| features: "" | |
| - name: go-meshos-ffi | |
| path: net/crates/net/bindings/go/meshos-ffi | |
| features: "" | |
| - name: go-deck-ffi | |
| path: net/crates/net/bindings/go/deck-ffi | |
| features: "" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-test-ffi-${{ matrix.crate.name }}-${{ hashFiles('**/Cargo.lock') }} | |
| # napi-rs links `napi_*` runtime symbols at load time (Node | |
| # provides them inside its embedded V8); a standalone | |
| # `cargo test --lib` binary can't resolve them at link time. | |
| # Lazy-linking flags (`-z lazy`, `--allow-shlib-undefined`, | |
| # `LD_BIND_NOT=1`) defer resolution but modern Ubuntu's | |
| # `-z now` hardening still trips before main() and the | |
| # binary fails with `undefined symbol: napi_get_reference_value` | |
| # / exit 127. | |
| # | |
| # Hard fix: build a tiny `libnapi_stub.so` that exports every | |
| # napi symbol the binding references as a no-op, then | |
| # `LD_PRELOAD` it before running cargo test. The dynamic | |
| # linker finds the symbol in the stub, the process starts, | |
| # and the tests run their pure-Rust helpers | |
| # (`bigint_u64`, capability conversion, etc.) without ever | |
| # invoking the stubs at runtime — none of these tests reach | |
| # the napi-rs runtime code path. | |
| # | |
| # Other matrix members don't need this and would silently | |
| # mask real link-time bugs if the stub were set globally. | |
| - name: Build napi stub library | |
| if: matrix.crate.name == 'node' | |
| working-directory: ${{ matrix.crate.path }} | |
| run: | | |
| cat > /tmp/napi_stub.c <<'CEOF' | |
| // No-op stubs for every napi_* symbol the napi-rs runtime | |
| // references. The cargo-test binary calls none of these at | |
| // runtime — the pure-Rust unit tests this matrix entry | |
| // covers don't exercise napi-rs's JS-bridge code path — | |
| // but the dynamic linker needs symbol *definitions* to load | |
| // the binary at all. Every stub returns 0 (napi_ok) so | |
| // even if a stub IS called by accident, the caller sees a | |
| // benign "success with no value" result. | |
| #include <stddef.h> | |
| typedef int napi_status; | |
| #define NAPI_STUB(name) napi_status name() { return 0; } | |
| NAPI_STUB(napi_get_reference_value) | |
| NAPI_STUB(napi_create_reference) | |
| NAPI_STUB(napi_delete_reference) | |
| NAPI_STUB(napi_reference_ref) | |
| NAPI_STUB(napi_reference_unref) | |
| NAPI_STUB(napi_module_register) | |
| NAPI_STUB(napi_set_instance_data) | |
| NAPI_STUB(napi_get_instance_data) | |
| NAPI_STUB(napi_create_function) | |
| NAPI_STUB(napi_throw) | |
| NAPI_STUB(napi_throw_error) | |
| NAPI_STUB(napi_throw_type_error) | |
| NAPI_STUB(napi_get_undefined) | |
| NAPI_STUB(napi_get_null) | |
| NAPI_STUB(napi_get_global) | |
| NAPI_STUB(napi_create_object) | |
| NAPI_STUB(napi_create_array) | |
| NAPI_STUB(napi_create_array_with_length) | |
| NAPI_STUB(napi_create_string_utf8) | |
| NAPI_STUB(napi_create_string_latin1) | |
| NAPI_STUB(napi_create_string_utf16) | |
| NAPI_STUB(napi_create_double) | |
| NAPI_STUB(napi_create_int32) | |
| NAPI_STUB(napi_create_uint32) | |
| NAPI_STUB(napi_create_int64) | |
| NAPI_STUB(napi_create_bigint_int64) | |
| NAPI_STUB(napi_create_bigint_uint64) | |
| NAPI_STUB(napi_create_bigint_words) | |
| NAPI_STUB(napi_get_value_bigint_int64) | |
| NAPI_STUB(napi_get_value_bigint_uint64) | |
| NAPI_STUB(napi_get_value_bigint_words) | |
| NAPI_STUB(napi_get_value_bool) | |
| NAPI_STUB(napi_get_value_double) | |
| NAPI_STUB(napi_get_value_int32) | |
| NAPI_STUB(napi_get_value_uint32) | |
| NAPI_STUB(napi_get_value_int64) | |
| NAPI_STUB(napi_get_value_string_utf8) | |
| NAPI_STUB(napi_get_value_string_latin1) | |
| NAPI_STUB(napi_get_value_string_utf16) | |
| NAPI_STUB(napi_get_boolean) | |
| NAPI_STUB(napi_typeof) | |
| NAPI_STUB(napi_get_property) | |
| NAPI_STUB(napi_set_property) | |
| NAPI_STUB(napi_has_property) | |
| NAPI_STUB(napi_delete_property) | |
| NAPI_STUB(napi_define_class) | |
| NAPI_STUB(napi_define_properties) | |
| NAPI_STUB(napi_get_property_names) | |
| NAPI_STUB(napi_get_all_property_names) | |
| NAPI_STUB(napi_call_function) | |
| NAPI_STUB(napi_new_instance) | |
| NAPI_STUB(napi_instanceof) | |
| NAPI_STUB(napi_is_array) | |
| NAPI_STUB(napi_get_array_length) | |
| NAPI_STUB(napi_get_element) | |
| NAPI_STUB(napi_set_element) | |
| NAPI_STUB(napi_create_buffer) | |
| NAPI_STUB(napi_create_buffer_copy) | |
| NAPI_STUB(napi_create_external_buffer) | |
| NAPI_STUB(napi_get_buffer_info) | |
| NAPI_STUB(napi_is_buffer) | |
| NAPI_STUB(napi_create_arraybuffer) | |
| NAPI_STUB(napi_create_external_arraybuffer) | |
| NAPI_STUB(napi_get_arraybuffer_info) | |
| NAPI_STUB(napi_is_arraybuffer) | |
| NAPI_STUB(napi_wrap) | |
| NAPI_STUB(napi_unwrap) | |
| NAPI_STUB(napi_remove_wrap) | |
| NAPI_STUB(napi_create_error) | |
| NAPI_STUB(napi_create_type_error) | |
| NAPI_STUB(napi_create_range_error) | |
| NAPI_STUB(napi_get_and_clear_last_exception) | |
| NAPI_STUB(napi_is_exception_pending) | |
| NAPI_STUB(napi_open_handle_scope) | |
| NAPI_STUB(napi_close_handle_scope) | |
| NAPI_STUB(napi_open_escapable_handle_scope) | |
| NAPI_STUB(napi_close_escapable_handle_scope) | |
| NAPI_STUB(napi_escape_handle) | |
| NAPI_STUB(napi_run_script) | |
| NAPI_STUB(napi_get_node_version) | |
| NAPI_STUB(napi_get_version) | |
| NAPI_STUB(napi_create_promise) | |
| NAPI_STUB(napi_resolve_deferred) | |
| NAPI_STUB(napi_reject_deferred) | |
| NAPI_STUB(napi_is_promise) | |
| NAPI_STUB(napi_get_uv_event_loop) | |
| NAPI_STUB(napi_create_threadsafe_function) | |
| NAPI_STUB(napi_get_threadsafe_function_context) | |
| NAPI_STUB(napi_call_threadsafe_function) | |
| NAPI_STUB(napi_acquire_threadsafe_function) | |
| NAPI_STUB(napi_release_threadsafe_function) | |
| NAPI_STUB(napi_ref_threadsafe_function) | |
| NAPI_STUB(napi_unref_threadsafe_function) | |
| NAPI_STUB(napi_add_env_cleanup_hook) | |
| NAPI_STUB(napi_remove_env_cleanup_hook) | |
| NAPI_STUB(napi_add_async_cleanup_hook) | |
| NAPI_STUB(napi_remove_async_cleanup_hook) | |
| NAPI_STUB(napi_fatal_error) | |
| NAPI_STUB(napi_fatal_exception) | |
| NAPI_STUB(napi_async_init) | |
| NAPI_STUB(napi_async_destroy) | |
| NAPI_STUB(napi_make_callback) | |
| NAPI_STUB(napi_create_async_work) | |
| NAPI_STUB(napi_delete_async_work) | |
| NAPI_STUB(napi_queue_async_work) | |
| NAPI_STUB(napi_cancel_async_work) | |
| NAPI_STUB(napi_open_callback_scope) | |
| NAPI_STUB(napi_close_callback_scope) | |
| NAPI_STUB(napi_create_date) | |
| NAPI_STUB(napi_get_date_value) | |
| NAPI_STUB(napi_is_date) | |
| NAPI_STUB(napi_object_freeze) | |
| NAPI_STUB(napi_object_seal) | |
| NAPI_STUB(napi_strict_equals) | |
| NAPI_STUB(napi_coerce_to_bool) | |
| NAPI_STUB(napi_coerce_to_number) | |
| NAPI_STUB(napi_coerce_to_string) | |
| NAPI_STUB(napi_coerce_to_object) | |
| NAPI_STUB(napi_is_error) | |
| NAPI_STUB(napi_get_named_property) | |
| NAPI_STUB(napi_set_named_property) | |
| NAPI_STUB(napi_has_named_property) | |
| NAPI_STUB(napi_get_prototype) | |
| NAPI_STUB(napi_get_cb_info) | |
| NAPI_STUB(napi_get_new_target) | |
| NAPI_STUB(napi_add_finalizer) | |
| NAPI_STUB(napi_create_typedarray) | |
| NAPI_STUB(napi_is_typedarray) | |
| NAPI_STUB(napi_get_typedarray_info) | |
| NAPI_STUB(napi_create_dataview) | |
| NAPI_STUB(napi_is_dataview) | |
| NAPI_STUB(napi_get_dataview_info) | |
| NAPI_STUB(napi_create_symbol) | |
| NAPI_STUB(napi_check_object_type_tag) | |
| NAPI_STUB(napi_type_tag_object) | |
| NAPI_STUB(node_api_get_module_file_name) | |
| NAPI_STUB(node_api_create_external_string_latin1) | |
| NAPI_STUB(node_api_create_external_string_utf16) | |
| NAPI_STUB(node_api_symbol_for) | |
| NAPI_STUB(node_api_create_property_key_latin1) | |
| NAPI_STUB(node_api_create_property_key_utf16) | |
| NAPI_STUB(node_api_create_property_key_utf8) | |
| NAPI_STUB(node_api_create_buffer_from_arraybuffer) | |
| CEOF | |
| gcc -shared -fPIC -o /tmp/libnapi_stub.so /tmp/napi_stub.c | |
| - name: Run tests (node — napi symbols stubbed) | |
| if: matrix.crate.name == 'node' | |
| working-directory: ${{ matrix.crate.path }} | |
| env: | |
| RUSTFLAGS: "-C link-arg=-Wl,--unresolved-symbols=ignore-all -C link-arg=-Wl,--allow-shlib-undefined" | |
| LD_PRELOAD: "/tmp/libnapi_stub.so" | |
| run: cargo test --lib ${{ matrix.crate.features }} | |
| - name: Run tests | |
| if: matrix.crate.name != 'node' | |
| working-directory: ${{ matrix.crate.path }} | |
| run: cargo test --lib ${{ matrix.crate.features }} | |
| cli-tests: | |
| # `net-cli`'s test surface is broader than the FFI shims: | |
| # unit tests inside `src/`, plus integration-test crates under | |
| # `tests/` that spawn the binary via `assert_cmd`. The crate | |
| # has no lib target, so `cargo test --lib` would silently skip | |
| # everything; `cargo test -p net-cli` runs every target cargo | |
| # auto-discovers, so a new `tests/foo.rs` doesn't need a CI | |
| # edit. | |
| # | |
| # Current surface (informational; not a check): | |
| # | |
| # src/main.rs — humantime duration parser | |
| # src/output.rs — format resolver | |
| # src/error.rs — exit-code discriminator pin | |
| # src/parsers.rs — parse_u64_flexible | |
| # src/commands/ice.rs — confirmation-gate logic | |
| # src/commands/identity.rs — iso8601 formatter | |
| # tests/help.rs — help-text + version surface | |
| # tests/exit_codes.rs — documented exit codes | |
| # tests/dry_run.rs — admin verb `--dry-run` envelope | |
| name: Net CLI tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-cli-${{ hashFiles('**/Cargo.lock') }} | |
| # Toolchains for the typegen downstream type-checks (E-2 / E-3). Without | |
| # these, tests/typegen_downstream_{ts,python}.rs self-skip; installing | |
| # them here makes those checks actually run. | |
| - name: Install Node + TypeScript | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| - name: Install tsc | |
| run: npm install -g typescript@6 | |
| - name: Install Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install mypy + pydantic | |
| run: python -m pip install --upgrade mypy pydantic | |
| - name: Run net-cli tests | |
| run: cargo test -p net-cli | |
| aggregator-daemon-tests: | |
| # `net-aggregator-daemon` is a lib + bin crate. The lib hosts | |
| # the `boot` / `run` entry points + config parsing + template | |
| # validation; the bin is a thin `Cli::parse + run` shim. Unit | |
| # tests live in `src/lib.rs`'s `#[cfg(test)] mod tests`; | |
| # integration tests live in `tests/boot_and_query.rs` and | |
| # drive a real two-node mesh handshake against the daemon's | |
| # registry-RPC surface. `cargo test -p net-aggregator-daemon` | |
| # picks up every target automatically — new `tests/foo.rs` | |
| # entries don't need a CI edit. | |
| name: Aggregator daemon tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-aggregator-daemon-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Run net-aggregator-daemon tests | |
| run: cargo test -p net-aggregator-daemon | |
| fmt: | |
| name: Format | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| doc: | |
| name: Documentation | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| defaults: | |
| run: | |
| working-directory: net/crates/net | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| net/crates/net/target/ | |
| key: ${{ runner.os }}-cargo-doc-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Build documentation | |
| run: cargo doc --no-deps --all-features | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # `cargo doc --all-features` only docs the current package | |
| # (the root `net-mesh` crate). Workspace members live in | |
| # their own crates; `net-cli` and `deck` both have | |
| # substantial module-level docstrings that document the | |
| # subcommand / TUI surface contracts — keep them | |
| # warning-free. | |
| - name: Build net-cli documentation | |
| run: cargo doc -p net-cli --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| - name: Build deck documentation | |
| run: cargo doc -p net-deck --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| - name: Build net-aggregator-daemon documentation | |
| run: cargo doc -p net-aggregator-daemon --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # `net-mesh-sdk` is a substantial workspace member with most | |
| # of the user-facing AI tool / nrpc / mesh / netdb docstrings. | |
| # Pinning `--features full` so the full doc surface (tool + | |
| # macros + nrpc + cortex + compute + groups + meshos + deck | |
| # + dataforts + meshdb + aggregator + local + nat-traversal | |
| # + redis + jetstream) is verified warning-free in lockstep | |
| # with the `ffi-clippy` `rust-sdk` lint job. | |
| - name: Build net-mesh-sdk documentation | |
| run: cargo doc -p net-mesh-sdk --no-deps --features full | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # `#[tool]` proc macro crate. User-facing macro docs live | |
| # here; the SDK depends on them via `pub use net_sdk_macros::tool;`. | |
| - name: Build net-mesh-sdk-macros documentation | |
| run: cargo doc -p net-mesh-sdk-macros --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # `net-rpc-ffi` is the cgo-facing nRPC shim. Its public | |
| # surface (extern "C" fn signatures + ABI version constants | |
| # + handle types) is what `go/mesh_rpc.go` documents against; | |
| # keep its rustdoc warning-free so the cross-language ABI | |
| # contract notes stay buildable. | |
| - name: Build net-rpc-ffi documentation | |
| run: cargo doc -p net-rpc-ffi --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings |