Commit 4c3a293
authored
* feat(cli): add bq-agent-sdk binding-validate + ontology-build flags (#105 PR 2b)
Closes the user-facing surface of issue #105. Builds on PR 2a's
validate_binding_against_bigquery core (shipped in PR #109).
CLI changes (src/bigquery_agent_analytics/cli.py)
Standalone command:
bq-agent-sdk binding-validate
--project-id ...
--ontology X.yaml
--binding Y.yaml
[--location US]
[--strict]
[--format json|text|table]
Loads the ontology + binding via upstream loaders, builds a
google.cloud.bigquery.Client, calls
validate_binding_against_bigquery(...), prints a structured JSON
report on stdout. Warnings always print to stderr (one line each)
so CI logs surface advisory drift even when stdout is consumed by
a JSON-aware tool.
Exit codes: 0 ok, 1 failure(s), 2 unexpected error (load failure,
missing flags, etc).
ontology-build flags:
--validate-binding (default-mode pre-flight)
--validate-binding-strict (strict-mode pre-flight)
When set, run the validator before phase 2 (extraction). On any
failure, the build short-circuits BEFORE any AI.GENERATE call
fires, so authoring drift never costs tokens. Default-mode
warnings print to stderr but do not block.
The two flags are mutually exclusive; both are incompatible with
the deprecated --spec-path form because the validator needs the
unresolved Ontology + Binding pair, not a combined GraphSpec.
Helper _run_binding_preflight() centralizes the load + validate +
print + exit logic so it can be invoked from ontology-build
without duplicating the flow.
Also: --location flag added to ontology-build, threaded through
to build_ontology_graph() (which has supported it on the Python
side since PR #108 / commit 292320b). The CLI was previously
building without forwarding it.
Tests (tests/test_cli.py)
TestBindingValidate (6 tests):
- test_clean_validation_exits_zero
- test_failures_exit_one_with_payload
- test_warnings_print_to_stderr_but_do_not_flip_exit
- test_strict_flag_threaded_through
- test_missing_required_flags_exit_2
- test_load_failure_exits_two
TestOntologyBuildValidateBindingFlag (5 tests):
- test_validate_binding_short_circuits_on_failure_before_build
(asserts build_ontology_graph is NEVER called when validation
fails — extraction does not start)
- test_validate_binding_strict_short_circuits_on_nullable_keys
- test_validate_binding_clean_proceeds_to_build
- test_validate_binding_with_spec_path_rejected
- test_both_flags_rejected (mutual exclusion)
All tests use patched validators (no live BQ); the live
integration test for the full flow lives in PR 2a (#109).
253/253 tests pass across the touched test files.
Docs
New: docs/ontology/binding-validation.md
- When to run (binding authoring, CI gating, ontology-build).
- Standalone CLI examples (default + strict).
- ontology-build integration examples.
- Failure-code reference table covering all 7 default codes
plus the strict-only KEY_COLUMN_NULLABLE.
- CI usage pattern (GitHub Actions).
- Python API example.
- Cross-links to ontology-build.md, binding.md, and #76's
planned post-extraction validator.
Updated: docs/README.md
- Added binding-validation.md to the Ontology Reference table.
What's NOT in this PR
- Live integration test for the CLI surface (the validator
itself has live coverage from PR 2a's
TestBindingValidationLive). A literal subprocess-style CLI
smoke test could land as a follow-up if someone wants it, but
the unit tests cover wiring + exit codes + flag threading
comprehensively.
* fix+test+docs: lowercase JSON codes, changelog, location + warning-only paths (#105 PR 2b)
Four review findings folded in.
(1) Failure-code reference now shows lowercase JSON values
The CLI emits f.code.value (e.g. 'missing_table'), not the enum
attribute name ('MISSING_TABLE'). Docs previously listed the
uppercase form, so users copying the table into jq filters would
silently match nothing. The reference table now has both columns
(Python FailureCode + JSON value), with a sample jq filter using
the lowercase form.
(2) CHANGELOG entry under [Unreleased]
This PR adds a public CLI command (binding-validate), two public
ontology-build flags (--validate-binding[-strict]), --location on
ontology-build, and the validate_binding_against_bigquery Python
API. All four are now called out under [Unreleased] / Added.
(3) Test the warning-only path through ontology-build
The new test test_validate_binding_warnings_only_proceeds_to_build
patches the validator to return a BindingValidationReport with
only warnings (no failures), runs ontology-build --validate-binding,
and asserts:
- exit code 0
- build_ontology_graph IS called (warnings don't short-circuit)
- WARN: key_column_nullable appears in the CLI output
This covers _run_binding_preflight()'s default-mode advisory
branch, complementing the existing failure-short-circuit and
clean-success tests.
(4) --location now has tests and a doc note
Two new tests:
- TestBindingValidate::test_location_threaded_to_bigquery_client
confirms binding-validate --location=EU constructs a BQ client
with location='EU'.
- TestOntologyBuildValidateBindingFlag::
test_location_threaded_through_orchestrator confirms
ontology-build --location=EU forwards to build_ontology_graph
so the orchestrator's BQ client targets the EU multi-region.
docs/ontology/ontology-build.md: new 'BigQuery location' section
covering --location plus a 'Pre-flight binding validation' section
referencing binding-validation.md for the full --validate-binding
flag reference.
256/256 tests pass (test_binding_validation.py + test_cli.py +
test_ontology_orchestrator.py + test_ontology_materializer.py +
test_resolved_spec.py). Autoformat clean.
Optional nit (deferred, not blocking): _run_binding_preflight
loads ontology + binding once for validation, _load_spec_from_args
reloads them for resolve(). Worth a small helper that returns the
loaded objects once, but acceptable as-is for PR 2b scope.
* docs: avoid naming INFORMATION_SCHEMA as preflight mechanism (#105 PR 2b)
Two wording fixes; no behavior change.
The validator uses bq_client.get_table(...) metadata calls
(binding_validation.py:309), not direct INFORMATION_SCHEMA queries.
Two places said the latter:
(1) docs/ontology/ontology-build.md: 'pre-flight validator queries
INFORMATION_SCHEMA in the same region' -> 'uses the BigQuery client
with the requested location to fetch each bound table's metadata'.
(2) tests/test_cli.py docstring on
test_location_threaded_to_bigquery_client: same correction. The
test asserts the location threads through; the wording for *why*
location matters now matches the actual mechanism.
256/256 tests still pass. Autoformat clean.
1 parent 8f8a36f commit 4c3a293
6 files changed
Lines changed: 1008 additions & 1 deletion
File tree
- docs
- ontology
- src/bigquery_agent_analytics
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
10 | 38 | | |
11 | 39 | | |
12 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
57 | 83 | | |
58 | 84 | | |
59 | 85 | | |
| |||
0 commit comments