Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .deepsource.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
version = 1

# Trees that are generated or vendored rather than hand-written source.
# Built module artifacts under any `pkg/`, the int-gen outputs under `generated/`, and the scenario `verification/`
# fixtures.
exclude_patterns = ["**/pkg/**", "generated/**", "verification/**"]
# `pkg/` is deliberately NOT excluded from DeepSource analysis.
# It holds hand-written module loaders (e.g. the Pyodide shim et_ws_pydata1.js) alongside build output. Only the
# int-gen outputs under `generated/` and the scenario `verification/` fixtures are excluded, since those are fully
# generated; if genuinely-generated glue under `pkg/` turns up as a finding, add a narrow per-file exclude then.
exclude_patterns = ["generated/**", "verification/**"]

# Repo convention: tests live in a `tests/` directory or in source files prefixed `test_`.
test_patterns = ["**/test_*.py", "**/tests/**"]
Expand Down
12 changes: 11 additions & 1 deletion .mise/config.coverage.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,17 @@ for profraw in "$covdir"/*.profraw; do
"$bin/llvm-profdata" merge -sparse -o "$pd" "$profraw"
"$bin/llvm-cov" export --format=lcov --instr-profile "$pd" "$obj" >> "$covdir/wasi.lcov"
done
coreutils cat "$covdir/wasi.lcov" >> lcov.info
# The wasm covmap records reference every source each module linked.
# Dependency crates under ~/.cargo/registry and toolchain std under ~/.rustup are not in VCS -- DeepSource
# flags them and they skew the aggregate metric -- so keep only workspace records (dropping .cargo/.rustup/rustc
# blocks) before merging the wasm lcov into lcov.info.
keep="$covdir/keep.awk"
coreutils cat > "$keep" <<'AWK'
{ buf = buf $0 ORS }
/^SF:/ { p = substr($0, 4); drop = (index(p, "/.cargo/") || index(p, "/.rustup/") || index(p, "/rustc/")) }
/^end_of_record$/ { if (!drop) printf "%s", buf; buf = ""; drop = 0 }
AWK
goawk -f "$keep" "$covdir/wasi.lcov" >> lcov.info
"""
shell = "bash -euo pipefail -c"

Expand Down
5 changes: 4 additions & 1 deletion .mise/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,10 @@ run = "typos --config config/typos.toml --write-changes"
# URLs from .rs comments and string literals too.
[tasks.link-check]
description = "Check that URLs in .md and .rs files are reachable (network)"
run = "lychee --config config/lychee.toml '**/*.md' '**/*.rs'"
# The .rs glob is scoped to the source dirs, not a bare `**/*.rs`.
# A recursive `**/*.rs` walks target/'s churning rustc temp files, and lychee expands globs before applying
# `exclude_path`, so it aborts with a GlobError when one of those temps vanishes mid-iteration.
run = "lychee --config config/lychee.toml '**/*.md' 'libs/**/*.rs' 'services/**/*.rs' 'utilities/**/*.rs'"

[tasks.ryl-check]
description = "Lint YAML with ryl (a yamllint-compatible Rust linter)"
Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,13 @@ opentelemetry-otlp = { version = "0.31", default-features = false, features = [
"http-json",
"http-proto",
"logs",
"metrics",
"reqwest-blocking-client",
"trace",
] }
opentelemetry-proto = { version = "0.31", default-features = false, features = [
"gen-tonic-messages",
"metrics",
"trace",
"with-serde",
] }
Expand Down
14 changes: 14 additions & 0 deletions config/ast-grep/rules/no-mod-in-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
id: no-mod-in-tests
language: Rust
severity: error
message: |
`mod` is forbidden inside test files (`tests/**/*.rs` and `src/test_*.rs`). Keep shared test helpers in a
test-support library crate -- `et-test-helpers` for low-dependency helpers, or a dedicated crate such as
`et-ws-test-server` / `int-otlp-mock` -- and `use` them, rather than a `tests/common/mod.rs` include or an
inline `mod { ... }`. A library gives each helper one compiled home (so coverage and lints see it once) instead
of recompiling it per test binary, and it keeps integration-test files flat: one file per test binary.
rule:
kind: mod_item
files:
- "**/tests/**/*.rs"
- "**/test_*.rs"
20 changes: 20 additions & 0 deletions config/clippy.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
allow-dbg-in-tests = true
allow-indexing-slicing-in-tests = true
allow-large-stack-frames-in-tests = true
allow-panic-in-tests = true
allow-print-in-tests = true
allow-unwrap-in-tests = true
allow-useless-vec-in-tests = true

# Compile-time bans -- a second layer under the matching config/ast-grep/rules/*, which catch these at diff time.
# `.expect()` itself is NOT listed here. `disallowed_methods` has no test exemption and does not skip
# proc-macro-generated code, so it would flag the `.build().expect("Failed building the Runtime")` that the
# `#[tokio::test]` macro expands into -- breaking every async test, even though that `.expect()` isn't ours. The
# `clippy::expect_used` restriction lint (denied workspace-wide) is the right tool instead: it bans hand-written
# `.expect()` everywhere but skips macro-generated calls, so `#[tokio::test]` is unaffected. `disallowed-methods`
# covers `.expect_err()` (which `expect_used` misses -- use `.unwrap_err()`) and mirrors ast-grep's `no-current-dir`.
disallowed-methods = [
{ path = "std::env::current_dir", reason = "use get_project_root() / et_path::find_project_root()" },
{ path = "std::result::Result::expect_err", reason = "use .unwrap_err() -- no message string needed" },
]

allowed-idents-below-min-chars = [
# clippy defaults
"Eq",
Expand Down
7 changes: 6 additions & 1 deletion libs/edge-toolkit/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ where
/// Helper to find repository root.
///
/// This is the one sanctioned `current_dir()`.
#[expect(clippy::missing_panics_doc, clippy::unwrap_used)]
#[expect(
clippy::disallowed_methods,
clippy::missing_panics_doc,
clippy::unwrap_used,
reason = "the one sanctioned current_dir() -- this helper is what the disallowed-methods ban points callers to"
)]
#[must_use]
pub fn get_project_root() -> PathBuf {
et_path::find_project_root(&std::env::current_dir().unwrap())
Expand Down
12 changes: 6 additions & 6 deletions libs/edge-toolkit/src/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ use serde::{Deserialize, Serialize};
/// payload is described as "arbitrary JSON" without tripping the parser.
#[cfg(feature = "schema-export")]
#[expect(
clippy::expect_used,
reason = "static JSON literal -> Schema is infallible; surfacing it loudly if asyncapi-rust ever changes shape"
clippy::unwrap_used,
reason = "static JSON literal -> Schema conversion is infallible by construction"
)]
fn any_json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
serde_json::json!({
"description": "Arbitrary JSON value (opaque to the protocol)",
})
.try_into()
.expect("any_json_schema is a valid object schema")
.unwrap()
}

/// Schema for `Vec<u8>` byte-array fields. schemars 1.x's default `Vec<u8>`
Expand All @@ -24,8 +24,8 @@ fn any_json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
/// `list<u8>` representation.
#[cfg(feature = "schema-export")]
#[expect(
clippy::expect_used,
reason = "static JSON literal -> Schema is infallible; surfacing it loudly if asyncapi-rust ever changes shape"
clippy::unwrap_used,
reason = "static JSON literal -> Schema conversion is infallible by construction"
)]
fn byte_array_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
serde_json::json!({
Expand All @@ -34,7 +34,7 @@ fn byte_array_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
"description": "Byte array (uint8)",
})
.try_into()
.expect("byte_array_schema is a valid array schema")
.unwrap()
}

#[expect(
Expand Down
19 changes: 7 additions & 12 deletions libs/edge-toolkit/src/ws_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,26 +207,21 @@ impl<S: Clone + Send + 'static> AgentRegistry<S> {
summaries
}

/// # Panics
/// Panics if `to_agent_id` is not present in the registry -- the caller is
/// expected to have validated that the recipient exists before queueing.
/// Queue a direct message for `to_agent_id`, returning the stored message and the recipient's session.
///
/// Returns `None` when `to_agent_id` is not in the registry. The inner `Option<S>` is the recipient's live
/// session -- `Some` when connected, `None` when the message was queued for a disconnected agent.
#[must_use]
#[expect(
clippy::expect_used,
reason = "caller contract: to_agent_id must reference a known agent"
)]
pub fn queue_direct(
&self,
message_id: String,
from_agent_id: &str,
to_agent_id: &str,
server_received_at: String,
message: serde_json::Value,
) -> (PendingDirectMessage, Option<S>) {
) -> Option<(PendingDirectMessage, Option<S>)> {
let mut agents = lock_agents(&self.agents);
let recipient = agents
.get_mut(to_agent_id)
.expect("queue_direct called for unknown target agent");
let recipient = agents.get_mut(to_agent_id)?;

let pending = PendingDirectMessage {
message_id,
Expand All @@ -240,7 +235,7 @@ impl<S: Clone + Send + 'static> AgentRegistry<S> {
.insert(from_agent_id.to_string(), pending.clone());
drop(agents);

(pending, session)
Some((pending, session))
}

#[must_use]
Expand Down
5 changes: 2 additions & 3 deletions libs/edge-toolkit/tests/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//! visible: `deserialize_optional::<String>` and the `Duration` humantime
//! variant share one sentinel (`none` / `off` / `disabled`).
#![cfg(test)]
#![expect(clippy::expect_used, reason = "test code: expect panics surface the failure")]

use std::time::Duration;

Expand All @@ -15,12 +14,12 @@ use serde::de::value::{Error as ValueError, StrDeserializer};

fn optional_string(value: &str) -> Option<String> {
let deser: StrDeserializer<'_, ValueError> = value.into_deserializer();
deserialize_optional::<_, String>(deser).expect("deserialize Option<String>")
deserialize_optional::<_, String>(deser).unwrap()
}

fn optional_duration(value: &str) -> Option<Duration> {
let deser: StrDeserializer<'_, ValueError> = value.into_deserializer();
deserialize_optional_humantime(deser).expect("deserialize Option<Duration>")
deserialize_optional_humantime(deser).unwrap()
}

#[test]
Expand Down
5 changes: 0 additions & 5 deletions libs/edge-toolkit/tests/http_pyodide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
//! silently passing.

#![cfg(test)]
#![expect(
clippy::panic,
clippy::unwrap_used,
reason = "test code: missing install fails loudly with a hint"
)]

use std::collections::HashSet;
use std::path::PathBuf;
Expand Down
1 change: 0 additions & 1 deletion libs/edge-toolkit/tests/no_mise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//! warnings at startup.

#![cfg(test)]
#![expect(clippy::unwrap_used, reason = "test code: failed tempdir setup should fail the test")]

use std::path::PathBuf;

Expand Down
1 change: 0 additions & 1 deletion libs/edge-toolkit/tests/npm_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//! verifies the resolver picks the right `node_modules` directory.

#![cfg(test)]
#![expect(clippy::unwrap_used, reason = "test code: failed tempdir setup should fail the test")]

use edge_toolkit::config::find_npm_modules_path_in;
use fs_err as fs;
Expand Down
1 change: 0 additions & 1 deletion libs/edge-toolkit/tests/pipx_site_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//! (`<install>/<pkg>/Lib/site-packages`, no Python-version subdir).

#![cfg(test)]
#![expect(clippy::unwrap_used, reason = "test code: failed tempdir setup should fail the test")]

use edge_toolkit::config::find_site_packages_in;
use fs_err as fs;
Expand Down
Loading
Loading