feat(validate): add --path option to target sub-schema via JSON Pointer#696
feat(validate): add --path option to target sub-schema via JSON Pointer#696Vaibhav701161 wants to merge 6 commits intosourcemeta:mainfrom
Conversation
|
Hi @jviotti, could you take a look when you have time? Would love your thoughts, especially if there are any edge cases I missed. |
There was a problem hiding this comment.
Pull request overview
Adds a --path option to the validate CLI command so users can target and validate a sub-schema inside a larger JSON/YAML document via JSON Pointer (e.g., OpenAPI documents).
Changes:
- Adds
--path <pointer>to thevalidatecommand and documents it in CLI help. - Extracts the pointed sub-schema before running the existing validation pipeline and blocks
--path+--templatetogether. - Adds new
validateCLI tests for success and failure cases involving--path.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/command_validate.cc |
Implements --path extraction logic and adds --path/--template conflict handling. |
src/main.cc |
Registers the new validate option and updates CLI help text. |
test/CMakeLists.txt |
Adds the new validate --path shell tests to the test suite. |
test/validate/pass_path_openapi.sh |
Validates extracting a schema embedded in an OpenAPI-like document. |
test/validate/fail_path_not_found.sh |
Asserts failure when the pointer doesn’t resolve. |
test/validate/fail_path_not_schema.sh |
Asserts failure when the pointed value isn’t a schema. |
test/validate/fail_path_with_template.sh |
Asserts CLI argument conflict handling for --path with --template. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
🤖 Augment PR SummarySummary: This PR adds a Changes:
Technical Notes: The implementation copies the pointed-to sub-schema before reassigning to avoid aliasing/use-after-free when the pointer references the same underlying JSON storage. 🤖 Was this summary useful? React with 👍 or 👎 |
There was a problem hiding this comment.
1 issue found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="test/CMakeLists.txt">
<violation number="1" location="test/CMakeLists.txt:232">
P2: New `--path` failure tests are registered without JSON-error assertions for two failure modes, leaving structured error output untested.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="test/validate/fail_path_ref_outside_subtree.sh">
<violation number="1" location="test/validate/fail_path_ref_outside_subtree.sh:32">
P2: New failure test lacks a companion `--json` assertion, so structured error output for this scenario is not covered.</violation>
<violation number="2" location="test/validate/fail_path_ref_outside_subtree.sh:36">
P2: Failure test is too broad: it suppresses output and only checks for any non-zero exit code, so unrelated errors can falsely pass.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
src/command_validate.cc
Outdated
| // Invalid pointer syntax is handled by to_pointer(), consistent with | ||
| // --entrypoint behavior. | ||
| const auto path_string{std::string{options.at("path").front()}}; | ||
| const auto pointer{sourcemeta::core::to_pointer(path_string)}; |
There was a problem hiding this comment.
Consider handling invalid JSON Pointer syntax from to_pointer(...) explicitly (e.g., wrap into a handled FileError similar to how resolve_entrypoint maps pointer errors); otherwise this will fall through to the generic handler and surface as an unexpected error instead of a schema input error.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
src/command_validate.cc
Outdated
|
|
||
| const auto schema{schema_from_stdin | ||
| ? read_from_stdin().document | ||
| sourcemeta::core::JSON schema{ |
src/command_validate.cc
Outdated
| : sourcemeta::core::read_yaml_or_json(schema_path)}; | ||
|
|
||
| if (options.contains("path") && !options.at("path").empty()) { | ||
| // Invalid pointer syntax is handled by to_pointer(), consistent with |
There was a problem hiding this comment.
I think this comment can go away. If any, cover it with a test
src/command_validate.cc
Outdated
| if (options.contains("path") && !options.at("path").empty()) { | ||
| // Invalid pointer syntax is handled by to_pointer(), consistent with | ||
| // --entrypoint behavior. | ||
| const auto path_string{std::string{options.at("path").front()}}; |
There was a problem hiding this comment.
Can we pass this directly to to_pointer?
src/command_validate.cc
Outdated
| if (!result) { | ||
| throw NotSchemaError{schema_resolution_base}; | ||
| } | ||
| // Note: extracting a sub-schema may break $ref references outside the |
There was a problem hiding this comment.
I think this comment can go away too. We can assert on this behaviour in the tests and instead explain in the docs.
Which reminds be that you didn't update the docs!
There was a problem hiding this comment.
BTW, we probably want something like this for the compile command too
src/main.cc
Outdated
| non-sense results. | ||
|
|
||
| Use --path to extract a sub-schema from the input document using | ||
| a JSON Pointer before validation. This is useful for validating |
There was a problem hiding this comment.
I would omit the second sentence about where this is useful. We can keep this help message more concise and explain more in the actual markdown docs?
src/main.cc
Outdated
| app.option("template", {"m"}); | ||
| app.option("loop", {"l"}); | ||
| app.option("entrypoint", {"p"}); | ||
| app.option("path", {}); |
There was a problem hiding this comment.
Can we add a short version to it too?
| # Schema input error | ||
| test "$EXIT_CODE" = "4" | ||
|
|
||
| cat << EOF > "$TMP/expected.txt" |
There was a problem hiding this comment.
For every error, please also run it with --json like the other test files
test/validate/fail_path_not_found.sh
Outdated
| test "$EXIT_CODE" = "4" | ||
|
|
||
| cat << EOF > "$TMP/expected.txt" | ||
| error: The schema file you provided does not represent a valid JSON Schema |
There was a problem hiding this comment.
Hmmm I think the error message makes no sense. Can we create a more meaningful exception class in src/error.h and throw that instead? You can do the try_get, and if not there, throw that new error?
test/validate/fail_path_not_found.sh
Outdated
| "$1" validate "$TMP/document.json" "$TMP/instance.json" \ | ||
| --path "/components/schemas/NonExistent" 2> "$TMP/stderr.txt" \ | ||
| && EXIT_CODE="$?" || EXIT_CODE="$?" | ||
| # Schema input error |
There was a problem hiding this comment.
Also this is not a schema input error for a general input error. Can you check the exit code constants? Is this indeed the most appropriate one?
There was a problem hiding this comment.
Yeah, seems like it should be 5?
| # Schema input error | ||
| test "$EXIT_CODE" = "4" | ||
|
|
||
| cat << EOF > "$TMP/expected.txt" |
There was a problem hiding this comment.
Same here. If testing errors, always also run it with --json. See other failure tests
|
|
||
| cat << EOF > "$TMP/expected.txt" | ||
| error: The schema file you provided does not represent a valid JSON Schema | ||
| at file path $(realpath "$TMP")/document.json |
There was a problem hiding this comment.
I think the error here is not that bad, but we should be printing the pointer too, with at pointer / at location or whatever we do with similar ones. So maybe worth subclassing this exception class in src/error.h?
| error: Could not resolve schema reference | ||
| at identifier file://$(realpath "$TMP")/document.json#/components/schemas/Address | ||
| at file path $(realpath "$TMP")/document.json | ||
| at location "/\$ref" |
There was a problem hiding this comment.
I think we also need to subclass this exception class to add the actual pointer from --path. Maybe what we do is always append that as from path <pointer>?
| EOF | ||
|
|
||
| diff "$TMP/stdout.txt" "$TMP/expected.txt" | ||
|
|
| { "name": "John", "age": 30 } | ||
| EOF | ||
|
|
||
| "$1" validate "$TMP/openapi.json" "$TMP/instance.json" \ |
There was a problem hiding this comment.
Can you run this with --verbose and then assert on the output? That will help us indeed assert on the result. And maybe do one with --json too
e6bc54c to
9942324
Compare
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
…ests, and behavior documentation) Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
9942324 to
de9cd5e
Compare
Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
- Change PathResolutionError exit code from 6 to 5 (EXIT_INVALID_CLI_ARGUMENTS) - Add pointer field to NotSchemaError, print when --path is used - Create PathSchemaReferenceError for errors with --path context - Guard empty pointer strings in print_exception - Remove unnecessary use-after-free comment - Move is_schema check inside --path block for correct pointer propagation - Update all test expectations Signed-off-by: Vaibhav mittal <vaibhavmittal929@gmail.com>
|
@jviotti , any comments ? |
Description
This PR adds support for a
--pathoption to thevalidatecommand. It allows validating a specific sub-schema inside a larger JSON document using a JSON Pointer.Reference #218
Motivation
In practice, most schemas are not standalone. They are often embedded inside larger documents such as OpenAPI specs. Right now, validating those requires manually extracting the schema first, which is inconvenient.
This change makes that workflow much simpler. You can directly point to the part of the document you want to validate.
Example:
This also fits with the direction discussed in #80, where the goal is to make it easier to work with embedded schemas without needing full OpenAPI parsing.
What this does
--path <pointer>option tovalidateto_pointer,try_get) to resolve the JSON Pointer--pathtogether with--templateError handling
--entrypointNo new error types are introduced. Existing ones are reused to stay consistent with current CLI behavior.
Tests
Added a small set of tests following existing patterns:
pass_path_openapichecks validating a schema inside an OpenAPI documentfail_path_not_foundchecks when the pointer does not resolvefail_path_not_schemachecks when the resolved value is not a schemafail_path_with_templatechecks the CLI option conflictTests focus on exit codes and stable output to avoid fragile assertions.
Notes
This change is intentionally scoped to
validateas a first step. It keeps the implementation simple and consistent with existing patterns.It also provides a practical way to work with embedded schemas today, while leaving room for broader OpenAPI support in the future.