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
23 changes: 23 additions & 0 deletions .mise/config.coverage.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ coreutils rm -rf target/debug target/release
# `--sh` is the current flag (the old `--export-prefix` alias is deprecated). This sets the rustc wrapper +
# LLVM_PROFILE_FILE + profile dir so nextest and the regens instrument into one profile set that `report` merges.
eval "$(cargo llvm-cov show-env --sh)"
# nextest SIGKILLs the spawned et-ws-pyo3-runner (services/ws-pyo3-runner/tests/modules.rs) after each exchange.
# LLVM flushes a process's counters only at exit, so a SIGKILLed process contributes nothing: the runner's async
# run/drive/worker paths reported 0% while its in-process initialize() was covered. Continuous mode (%c) memory-maps
# the counter file so increments persist live and survive the kill. %c is incompatible with the merge-pool (%Nm)
# specifier show-env emits, so use a per-process (%p) continuous file in the same profile dir -- `cargo llvm-cov
# report` globs every *.profraw there regardless of name. On Linux continuous mode additionally needs relocatable
# counters (`-Cllvm-args=-runtime-counter-relocation`). The wrapper flags env is CARGO_ENCODED_RUSTFLAGS format
# (ASCII unit separator 0x1f between flags), not space-separated -- a space append glues the llvm-arg onto the
# last existing flag and rustc rejects `--cfg=coverage_nightly -Cllvm-args=...` as one invalid --cfg value.
cov_dir="$(coreutils dirname "$LLVM_PROFILE_FILE")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 HIGH RISK

Invoke the utilities directly (e.g., 'dirname', 'uname') instead of prefixing them with 'coreutils' to ensure compatibility across standard shell environments.

export LLVM_PROFILE_FILE="$cov_dir/core-cont-%p%c.profraw"
if [ "$(coreutils uname -s)" = "Linux" ]; then
reloc="-Cllvm-args=-runtime-counter-relocation"
flags="${__CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS:-}"
# Append the reloc flag with a TOML-injected unit separator (ASCII 31).
# Bash dollar-quote hex is not a valid TOML escape, so the separator has to be introduced by the
# TOML parser into the task body rather than written as a shell escape.
if [ -n "$flags" ]; then
export __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS="${flags}\u001f${reloc}"
else
export __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS="${reloc}"
fi
fi
# The --features flags compile each runner's coverage code, off by default so non-coverage builds omit it.
# et-ws-web-runner/coverage adds the browser-module capture (shims + the __et_capture_coverage PUT);
# et-ws-wasi-runner/coverage adds the guest `/cov` preopen. ET_TEST_COVERAGE (set by the coverage job) still
Expand Down
14 changes: 7 additions & 7 deletions config/otelcol-hostmetrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
# Scrapes host resource usage and ships it to the local OpenObserve (o2) over OTLP/HTTP -- the same OTLP-to-o2
# path the ws-server uses.
receivers:
# GPU (NVIDIA) is not collected here.
# Use the dedicated `o2-nvidia` / `o2-nvidia-native` mise tasks (native nvidia_gpu_exporter + prometheus
# scrape). DCGM remains available if you prefer in-collector GPU metrics: it needs `--gpus all` on the docker
# run and a DCGM-capable host; uncomment this receiver and add `dcgm` to the metrics pipeline receivers below
# to enable it.
# dcgm:
# collection_interval: 10s
hostmetrics:
# Read the host's /proc and /sys rather than the collector container's own.
# `/hostfs` is the host root the task bind-mounts read-only.
Expand All @@ -15,13 +22,6 @@ receivers:
filesystem: {}
network: {}
paging: {}
# GPU (NVIDIA) is not collected here.
# Use the dedicated `o2-nvidia` / `o2-nvidia-native` mise tasks (native nvidia_gpu_exporter + prometheus
# scrape). DCGM remains available if you prefer in-collector GPU metrics: it needs `--gpus all` on the docker
# run and a DCGM-capable host; uncomment this receiver and add `dcgm` to the metrics pipeline receivers below
# to enable it.
# dcgm:
# collection_interval: 10s

extensions:
# o2 ingests OTLP over HTTP with HTTP Basic auth; the credentials come from config/o2.env (passed via --env-file).
Expand Down
3 changes: 3 additions & 0 deletions config/ryl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
extends: default

rules:
# A misindented comment reads as attached to the wrong block, so treat it as an error, not a warning.
comments-indentation:
level: error
# dprint (the YAML formatter) writes one space before an inline `#`.
# yamllint defaults to two. Defer to dprint so the two can't fight.
comments:
Expand Down
13 changes: 12 additions & 1 deletion libs/path/tests/find.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
#![cfg(test)]

use et_path::find_project_root;
use et_path::{find_project_root, find_project_root_from_manifest};
use fs_err as fs;
use tempfile::tempdir;

#[test]
fn manifest_dir_resolves_to_an_existing_root() {
// cargo sets `CARGO_MANIFEST_DIR` in the test process env, so the helper reads this crate's
// directory and walks up to the workspace root (which carries project-root markers).
let root = find_project_root_from_manifest();
assert!(
root.is_dir(),
"resolved project root {root:?} should be an existing directory"
);
Comment on lines +11 to +15

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert that the resolved path is the project root, not merely a directory.

root.is_dir() does not verify the helper walked to the repository root; returning any existing manifest directory would still pass. Assert that root.join(".dprint.jsonc").is_file() (or compare against an independently determined expected root) to exercise the actual contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/path/tests/find.rs` around lines 11 - 15, Strengthen the assertion in
the find_project_root_from_manifest test to verify the resolved path is the
repository root, not merely an existing directory. Assert that
root.join(".dprint.jsonc").is_file() (or compare root with an independently
determined expected root), while retaining the existing directory validation if
useful.

}

#[test]
fn finds_marker_in_an_ancestor() {
let root = tempdir().unwrap();
Expand Down
8 changes: 8 additions & 0 deletions libs/web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ pub use self::error::{JsCastExt, JsFunctionExt, JsPromiseExt, JsResultExt};

pub const SENSOR_PERMISSION_GRANTED: &str = "granted";

/// Discard `value`, marking a `Result` (or other `#[must_use]`) as intentionally ignored.
///
/// The workspace denies `let_underscore*` and `unused_results`, and `DeepSource`'s RS-E1021 flags `drop()` on a
/// non-`Drop` type (e.g. `Result`), so neither `let _ = expr` nor `drop(expr)` is available for discarding one.
/// Passing the value here consumes it -- satisfying `must_use` / `unused_results` -- via neither. Intended for
/// best-effort JS DOM calls in `()`-returning closures and event handlers where the error is deliberately dropped.
pub fn ignore<T>(_value: T) {}

/// Return this module's raw minicov coverage buffer (a `.profraw`), or empty on failure.
///
/// Present only in the `coverage` build. `wasm-bindgen` collects this export into every dependent browser
Expand Down
10 changes: 5 additions & 5 deletions services/ws-modules/audio1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ thread_local! {

#[wasm_bindgen(start)]
pub fn init() {
drop(tracing_wasm::try_set_as_global_default());
et_web::ignore(tracing_wasm::try_set_as_global_default());
info!("audio-capture module initialized");
}

Expand Down Expand Up @@ -126,7 +126,7 @@ pub async fn run() -> Result<(), JsValue> {
let stop_callback = Closure::once_into_js(move || {
if is_running() {
log("workflow finished automatically after 5 seconds");
drop(stop());
et_web::ignore(stop());
}
});
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
Expand All @@ -139,7 +139,7 @@ pub async fn run() -> Result<(), JsValue> {

if let Err(error) = &outcome {
let message = describe_js_error(error);
drop(set_module_status(&format!("audio-capture: error\n{message}")));
et_web::ignore(set_module_status(&format!("audio-capture: error\n{message}")));
log(&format!("error: {message}"));
}

Expand Down Expand Up @@ -204,13 +204,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
et_web::ignore(reject.call1(&JsValue::NULL, &error));
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
8 changes: 4 additions & 4 deletions services/ws-modules/bluetooth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl BluetoothAccess {

#[wasm_bindgen(start)]
pub fn init() {
drop(tracing_wasm::try_set_as_global_default());
et_web::ignore(tracing_wasm::try_set_as_global_default());
info!("bluetooth module initialized");
}

Expand Down Expand Up @@ -146,7 +146,7 @@ pub async fn run() -> Result<(), JsValue> {

if let Err(error) = &outcome {
let message = describe_js_error(error);
drop(set_module_status(&format!("bluetooth: error\n{message}")));
et_web::ignore(set_module_status(&format!("bluetooth: error\n{message}")));
log(&format!("error: {message}"));
}

Expand Down Expand Up @@ -197,13 +197,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
et_web::ignore(reject.call1(&JsValue::NULL, &error));
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
10 changes: 5 additions & 5 deletions services/ws-modules/comm1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ fn handle_incoming_message(
"comm1: received {scope:?} message {message_id} from {from_agent_id} at {server_received_at}: {summary}"
);
web_sys::console::log_1(&JsValue::from_str(&line));
drop(set_module_status(&line));
let _status = set_module_status(&line);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 MEDIUM RISK

Suggestion: Use the newly introduced 'et_web::ignore' utility here instead of 'let _status'. This ensures consistency with other browser-based WASM modules updated in this PR and adheres to the project's workspace-wide linting strategy for 'must_use' results.

Suggested change
let _status = set_module_status(&line);
et_web::ignore(set_module_status(&line));

}
ServerMessage::MessageStatus {
message_id,
Expand All @@ -142,12 +142,12 @@ fn handle_incoming_message(
} => {
let line = format!("comm1: message status update {message_id:?} {status:?}: {detail}");
web_sys::console::log_1(&JsValue::from_str(&line));
drop(set_module_status(&line));
let _status = set_module_status(&line);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ LOW RISK

Suggestion: Use 'et_web::ignore' for consistency with other browser-based WASM modules in this PR to discard the result of 'set_module_status'.

}
ServerMessage::Invalid { message_id, detail } => {
let line = format!("comm1: invalid server response {message_id:?}: {detail}");
web_sys::console::warn_1(&JsValue::from_str(&line));
drop(set_module_status(&line));
let _status = set_module_status(&line);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ LOW RISK

Suggestion: Use 'et_web::ignore' for consistency with other browser-based WASM modules in this PR to discard the result of 'set_module_status'.

}
ServerMessage::ConnectAck { .. }
| ServerMessage::Response { .. }
Expand Down Expand Up @@ -192,13 +192,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
let _resolved = resolve.call0(&JsValue::NULL);
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
let _rejected = reject.call1(&JsValue::NULL, &error);
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
4 changes: 2 additions & 2 deletions services/ws-modules/data1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub async fn run() -> Result<(), JsValue> {
let Some(data) = value.as_string() else {
return;
};
drop(serde_json::from_str::<ServerMessage>(&data));
et_web::ignore(serde_json::from_str::<ServerMessage>(&data));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 MEDIUM RISK

The call to 'serde_json::from_str' currently has no effect as the result is discarded. Remove this call if validation is not needed, or update it to log a warning (e.g., using 'tracing::warn!') if parsing fails to avoid silent diagnostic gaps.

}) as Box<dyn FnMut(JsValue)>);

client.set_on_message(on_message.as_ref().clone());
Expand Down Expand Up @@ -134,7 +134,7 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, _reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});
let _id: Result<i32, JsValue> =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms);
Expand Down
16 changes: 8 additions & 8 deletions services/ws-modules/geolocation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,28 @@ impl GeolocationReading {
let promise = js_sys::Promise::new(&mut |resolve, reject| {
let reject_for_callback = reject.clone();
let success_box: Box<dyn FnOnce(JsValue)> = Box::new(move |position: JsValue| {
drop(resolve.call1(&JsValue::NULL, &position));
et_web::ignore(resolve.call1(&JsValue::NULL, &position));
});
let success = Closure::once(success_box);

let failure_box: Box<dyn FnOnce(JsValue)> = Box::new(move |error: JsValue| {
drop(reject_for_callback.call1(&JsValue::NULL, &error));
et_web::ignore(reject_for_callback.call1(&JsValue::NULL, &error));
});
let failure = Closure::once(failure_box);

match js_sys::Reflect::get(&geolocation, &JsValue::from_str("getCurrentPosition"))
.and_then(|value| value.into_function("navigator.geolocation.getCurrentPosition"))
{
Ok(get_current_position) => {
drop(get_current_position.call3(
et_web::ignore(get_current_position.call3(
&geolocation,
success.as_ref().unchecked_ref(),
failure.as_ref().unchecked_ref(),
&options,
));
}
Err(err) => {
drop(reject.call1(&JsValue::NULL, &err));
et_web::ignore(reject.call1(&JsValue::NULL, &err));
}
}

Expand Down Expand Up @@ -116,7 +116,7 @@ impl GeolocationReading {

#[wasm_bindgen(start)]
pub fn init() {
drop(tracing_wasm::try_set_as_global_default());
et_web::ignore(tracing_wasm::try_set_as_global_default());
info!("geolocation module initialized");
}

Expand Down Expand Up @@ -170,7 +170,7 @@ pub async fn run() -> Result<(), JsValue> {

if let Err(error) = &outcome {
let message = describe_js_error(error);
drop(set_module_status(&format!("geolocation: error\n{message}")));
et_web::ignore(set_module_status(&format!("geolocation: error\n{message}")));
log(&format!("error: {message}"));
}

Expand Down Expand Up @@ -221,13 +221,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
et_web::ignore(reject.call1(&JsValue::NULL, &error));
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
8 changes: 4 additions & 4 deletions services/ws-modules/graphics-info/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ fn string_or_unknown(value: String) -> String {

#[wasm_bindgen(start)]
pub fn init() {
drop(tracing_wasm::try_set_as_global_default());
et_web::ignore(tracing_wasm::try_set_as_global_default());
info!("graphics-info module initialized");
}

Expand Down Expand Up @@ -800,7 +800,7 @@ pub async fn run() -> Result<(), JsValue> {

if let Err(error) = &outcome {
let message = describe_js_error(error);
drop(set_module_status(&format!("graphics-info: error\n{message}")));
et_web::ignore(set_module_status(&format!("graphics-info: error\n{message}")));
log(&format!("error: {message}"));
}

Expand Down Expand Up @@ -851,13 +851,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
et_web::ignore(reject.call1(&JsValue::NULL, &error));
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
8 changes: 4 additions & 4 deletions services/ws-modules/har1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ impl DeviceSensors {

#[wasm_bindgen(start)]
pub fn init() {
drop(tracing_wasm::try_set_as_global_default());
et_web::ignore(tracing_wasm::try_set_as_global_default());
info!("har1 workflow module initialized");
}

Expand Down Expand Up @@ -371,7 +371,7 @@ pub async fn run() -> Result<(), JsValue> {

if let Err(error) = &outcome {
let message = describe_js_error(error);
drop(set_har_status(&format!("har1: error\n{message}")));
et_web::ignore(set_har_status(&format!("har1: error\n{message}")));
log(&format!("error: {message}"));
}

Expand Down Expand Up @@ -874,13 +874,13 @@ async fn sleep_ms(duration_ms: i32) -> Result<(), JsValue> {
let window = web_sys::window().ok_or_else(|| JsValue::from_str("No window available"))?;
let promise = Promise::new(&mut |resolve, reject| {
let callback = Closure::once_into_js(move || {
drop(resolve.call0(&JsValue::NULL));
et_web::ignore(resolve.call0(&JsValue::NULL));
});

if let Err(error) =
window.set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), duration_ms)
{
drop(reject.call1(&JsValue::NULL, &error));
et_web::ignore(reject.call1(&JsValue::NULL, &error));
}
});
JsFuture::from(promise).await.map(|_| ())
Expand Down
Loading
Loading