Skip to content

refactor(cli): disable jsonschema resolving external resources#4

Open
tomerqodo wants to merge 6 commits into
coderabbit_full_base_refactorcli_disable_jsonschema_resolving_external_resources_pr4from
coderabbit_full_head_refactorcli_disable_jsonschema_resolving_external_resources_pr4
Open

refactor(cli): disable jsonschema resolving external resources#4
tomerqodo wants to merge 6 commits into
coderabbit_full_base_refactorcli_disable_jsonschema_resolving_external_resources_pr4from
coderabbit_full_head_refactorcli_disable_jsonschema_resolving_external_resources_pr4

Conversation

@tomerqodo

@tomerqodo tomerqodo commented Jan 30, 2026

Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#4

Summary by CodeRabbit

  • Chores

    • Refined dependency configuration to optimize CLI build.
  • Refactor

    • Improved schema validation performance through caching mechanisms.
    • Streamlined error handling and reporting logic throughout CLI utilities.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The changes optimize the jsonschema dependency by disabling default features, introduce a cached JSON schema validator for configuration validation using OnceLock, refactor config merging logic to use metadata extensions, and improve error handling efficiency by reducing unnecessary string allocations.

Changes

Cohort / File(s) Summary
Dependency Configuration
crates/tauri-cli/Cargo.toml
Updated jsonschema dependency to disable default features, changing from version constraint to feature-controlled variant.
Config Validation & Processing
crates/tauri-cli/src/helpers/config.rs
Introduced cached schema validator via OnceLock for bundled config.schema.json; refactored validation calls to use config_schema_validator().iter_errors(); modified config merging to store merged extensions in metadata; improved error message formatting with interpolation placeholders.
Error Handling Efficiency
crates/tauri-cli/src/interface/rust.rs
Optimized error logging to use Display implementation directly instead of converting to String, eliminating unnecessary allocation in watch folder error handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

A rabbit hops through schemas cached so neat,
With OnceLock and merges sweet,
Default features stripped away with care,
Error logging floats light as air,
Optimization makes the build run fleet! 🐰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: disabling jsonschema's external resource resolution in the CLI. This is directly reflected in the Cargo.toml dependency modification (default-features = false) and the corresponding validation logic updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch coderabbit_full_head_refactorcli_disable_jsonschema_resolving_external_resources_pr4

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@crates/tauri-cli/src/helpers/config.rs`:
- Around line 201-204: The extension check on config_path is impossible because
it uses && (both "json" and "json5" at once), so schema validation never runs;
update the condition in the block that calls
config_schema_validator().iter_errors(&config) to check for either extension
instead (replace the && with ||) — i.e., use config_path.extension() ==
Some(OsStr::new("json")) || config_path.extension() == Some(OsStr::new("json5"))
(or collapse to a single map/contains check) so .json and .json5 files properly
trigger validation in the config loading logic.
- Around line 175-179: original_identifier is always None because the code calls
.as_str() on the "bundle" value (an object) instead of drilling into that
object; change the extraction to get the "bundle" object first and then read its
identifier field (e.g., replace the chain on config to .and_then(|config|
config.get("bundle")).and_then(|b| b.as_object()).and_then(|b|
b.get("identifier").and_then(|id| id.as_str())).map(ToString::to_string) so
original_identifier actually captures the inner string.
- Around line 286-291: The merged JSON `value` is never written back to the
actual config; after calling merge(&mut value, &merge_config) you must
deserialize the merged `value` and assign it to `config_metadata.inner` so the
in-memory config reflects the merge. Locate the block around
serde_json::to_value(config_metadata.inner.clone()) and, after merge(&mut value,
&merge_config), perform serde_json::from_value(value) (with appropriate error
context) and set config_metadata.inner = deserialized_result before inserting
the MERGE_CONFIG_EXTENSION_NAME extension and returning handle.

Comment on lines 175 to 179
let original_identifier = config
.as_object()
.and_then(|config| config.get("identifier"))
.and_then(|config| config.get("bundle"))
.and_then(|id| id.as_str())
.map(ToString::to_string);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Bug: original_identifier extraction will always return None.

The code retrieves "bundle" (which is an object) and then calls .as_str() on it. Since bundle is an object containing the identifier, not a string, this will always return None.

To properly extract the bundle identifier from the config JSON, you need to navigate into the bundle object:

🐛 Proposed fix
   let original_identifier = config
     .as_object()
-    .and_then(|config| config.get("bundle"))
-    .and_then(|id| id.as_str())
+    .and_then(|config| config.get("bundle"))
+    .and_then(|bundle| bundle.get("identifier"))
+    .and_then(|id| id.as_str())
     .map(ToString::to_string);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let original_identifier = config
.as_object()
.and_then(|config| config.get("identifier"))
.and_then(|config| config.get("bundle"))
.and_then(|id| id.as_str())
.map(ToString::to_string);
let original_identifier = config
.as_object()
.and_then(|config| config.get("bundle"))
.and_then(|bundle| bundle.get("identifier"))
.and_then(|id| id.as_str())
.map(ToString::to_string);
🤖 Prompt for AI Agents
In `@crates/tauri-cli/src/helpers/config.rs` around lines 175 - 179,
original_identifier is always None because the code calls .as_str() on the
"bundle" value (an object) instead of drilling into that object; change the
extraction to get the "bundle" object first and then read its identifier field
(e.g., replace the chain on config to .and_then(|config|
config.get("bundle")).and_then(|b| b.as_object()).and_then(|b|
b.get("identifier").and_then(|id| id.as_str())).map(ToString::to_string) so
original_identifier actually captures the inner string.

Comment on lines 201 to +204
if config_path.extension() == Some(OsStr::new("json"))
|| config_path.extension() == Some(OsStr::new("json5"))
&& config_path.extension() == Some(OsStr::new("json5"))
{
let schema: JsonValue = serde_json::from_str(include_str!("../../config.schema.json"))
.context("failed to parse config schema")?;
let validator = jsonschema::validator_for(&schema).expect("Invalid schema");
let mut errors = validator.iter_errors(&config).peekable();
let mut errors = config_schema_validator().iter_errors(&config).peekable();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical bug: Schema validation is completely disabled due to impossible condition.

The condition checks if the extension equals both "json" AND "json5" simultaneously, which is logically impossible. This means schema validation will never execute.

If the intent was to validate only .json files (not .json5), it should be:

if config_path.extension() == Some(OsStr::new("json"))

If the intent was to validate both formats, the original || was correct:

if config_path.extension() == Some(OsStr::new("json"))
    || config_path.extension() == Some(OsStr::new("json5"))
🐛 Proposed fix (assuming intent is to validate .json only)
-  if config_path.extension() == Some(OsStr::new("json"))
-    && config_path.extension() == Some(OsStr::new("json5"))
+  if config_path.extension() == Some(OsStr::new("json"))
   {
🤖 Prompt for AI Agents
In `@crates/tauri-cli/src/helpers/config.rs` around lines 201 - 204, The extension
check on config_path is impossible because it uses && (both "json" and "json5"
at once), so schema validation never runs; update the condition in the block
that calls config_schema_validator().iter_errors(&config) to check for either
extension instead (replace the && with ||) — i.e., use config_path.extension()
== Some(OsStr::new("json")) || config_path.extension() ==
Some(OsStr::new("json5")) (or collapse to a single map/contains check) so .json
and .json5 files properly trigger validation in the config loading logic.

Comment on lines 286 to 291
let mut value =
serde_json::to_value(config_metadata.inner.clone()).context("failed to serialize config")?;
merge(&mut value, &merge_config);
config_metadata.inner = serde_json::from_value(value).context("failed to parse config")?;
config_metadata.extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);

Ok(handle)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n crates/tauri-cli/src/helpers/config.rs | sed -n '270,310p'

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1663


🏁 Script executed:

git log -p --all -S 'merge_with' -- 'crates/tauri-cli/src/helpers/config.rs' | head -300

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 77


🏁 Script executed:

rg -B5 -A5 "^fn merge" crates/tauri-cli/src/helpers/config.rs

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 413


🏁 Script executed:

rg "merge_with" crates/tauri-cli/src/ -A3 -B1

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1302


🏁 Script executed:

rg "merge_with" crates/tauri-cli/tests/ -A5 -B1 2>/dev/null || echo "No tests found in expected location"

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 130


🏁 Script executed:

rg "use.*merge|fn merge|from_value.*value" crates/tauri-cli/src/helpers/config.rs | head -20

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 304


🏁 Script executed:

rg "MERGE_CONFIG_EXTENSION_NAME" crates/tauri-cli/src/ -B2 -A2

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1205


🏁 Script executed:

cat -n crates/tauri-cli/src/helpers/config.rs | sed -n '190,210p'

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1074


🏁 Script executed:

cat -n crates/tauri-cli/src/helpers/config.rs | sed -n '1,50p'

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1765


🏁 Script executed:

cat -n crates/tauri-cli/src/helpers/config.rs | sed -n '160,200p'

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1786


🏁 Script executed:

cat -n crates/tauri-cli/src/helpers/config.rs | sed -n '270,295p'

Repository: agentic-review-benchmarks/tauri-combined-coderabbit

Length of output: 1127


Merged config value is computed but never applied to the inner config.

The code merges merge_config into value (line 288), but value is never assigned back to config_metadata.inner. This is inconsistent with the load() function (line 197), which applies merge results to the actual config. Only the extension is being stored, leaving the inner config unchanged and the merge operation ineffective.

🐛 Fix: Apply merged result to inner config
     let mut value =
       serde_json::to_value(config_metadata.inner.clone()).context("failed to serialize config")?;
     merge(&mut value, &merge_config);
+    config_metadata.inner = serde_json::from_value(value).context("failed to deserialize merged config")?;
     config_metadata.extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);
 
     Ok(handle)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let mut value =
serde_json::to_value(config_metadata.inner.clone()).context("failed to serialize config")?;
merge(&mut value, &merge_config);
config_metadata.inner = serde_json::from_value(value).context("failed to parse config")?;
config_metadata.extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);
Ok(handle)
let mut value =
serde_json::to_value(config_metadata.inner.clone()).context("failed to serialize config")?;
merge(&mut value, &merge_config);
config_metadata.inner = serde_json::from_value(value).context("failed to deserialize merged config")?;
config_metadata.extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);
Ok(handle)
🤖 Prompt for AI Agents
In `@crates/tauri-cli/src/helpers/config.rs` around lines 286 - 291, The merged
JSON `value` is never written back to the actual config; after calling
merge(&mut value, &merge_config) you must deserialize the merged `value` and
assign it to `config_metadata.inner` so the in-memory config reflects the merge.
Locate the block around serde_json::to_value(config_metadata.inner.clone()) and,
after merge(&mut value, &merge_config), perform serde_json::from_value(value)
(with appropriate error context) and set config_metadata.inner =
deserialized_result before inserting the MERGE_CONFIG_EXTENSION_NAME extension
and returning handle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants