Repository navigation
fix: keep numeric/boolean owner and tag strings instead of crashing or dropping them - #2376
deepanshupal wants to merge 7 commits into
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
…lists Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
|
👋 @deepanshupal |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (3)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe JSON unpacking helpers now preserve parsed scalar tokens as single-item string lists. ChangesJSON list conversion
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to No actionable merge-blocking issue is identified. The reported retry-test timeout remains an unverified test result, not evidence of a regression in this change. Security Architecture ReviewSecurity architecture risk: ⚪ Minimal · up to The change preserves scalar metadata through existing processing paths without adding permissions or exposed interfaces. Comparison with the previous behavior found no material security risk introduced or worsened by this PR. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
EladBarkay
left a comment
There was a problem hiding this comment.
Thanks for the fix and the clear repro! Keeping bare numbers and booleans as strings is the right call. A few things before merging:
-
JSON-encoded strings keep their quotes.
json.loads('"@alice"')returns thestr@alice, which now goes down the new scalar branch. Both helpers then return the raw text with quotes (['"@alice"']), so it shows up quoted in alerts and doesn't dedup against@alice. The decoded string should be used instead. -
Numbers inside a JSON list.
"12345"now becomes["12345"], but"[12345]"still becomes[12345], an int. A mixed list like'[1, "a"]'then fails with aTypeErrorinprettify_and_dedup_list, because it sorts ints and strings together. This predates your PR but is the same bug in list form. One caution: the conversion to strings should happen only in the owners/tags path (unpack_and_flatten_and_dedup_list_of_strings), not inunpack_and_flatten_str_to_listitself.test_rows_samplegoes through that function too and relies on it returning a list of dicts unchanged. -
The two helpers disagree.
ExtendedBaseModel._load_var_to_list(report) andunpack_and_flatten_and_dedup_list_of_strings(alerts) parse the same owners and tags, but return different results for the same input:- Dicts:
'{"a": 1}'becomes[]in alerts (silently dropped) and['{"a": 1}']in the report. - Comma splitting:
"a, b"becomes["a", "b"]in alerts and["a, b"]in the report. - Whitespace:
" prod "becomes['prod']in alerts and[' prod ']in the report. This PR adds the same split for scalars (" 12345 "). - Dedup and order: alerts dedup through
set(), which loses order. The report keeps duplicates and order.
At a minimum, the cases this PR touches (scalars, quoted strings) should give the same result in both.
- Dicts:
Nit: consider merging the two parsers into one. This PR fixes the same bug separately in each helper, and #1 would need fixing twice as well. A single normalizer in json_utils, with _load_var_to_list calling it, would resolve #3 and stop the two from drifting further. Some callers depend on today's behavior, so a few things need deciding along the way:
_load_var_to_listalso parsesdepends_on_nodes(monitor/fetchers/models/schema.py). Comma splitting, stripping and dedup would start applying there too.unpack_and_flatten_str_to_listalso parsestest_rows_sample(alert_data.py), which expects a list of dicts. The shared logic can't convert list items to strings across the board.- The model, test and source-freshness schemas don't split on commas today. If the shared version does, tags like
"a, b"will start splitting in the report.
Please add tests for each case (quoted strings, lists with numbers, dicts, whitespace) covering both helpers.
| if isinstance(list_unpacked, dict): | ||
| return [] # edge case of a string of an empty dict or IDK | ||
| # A JSON scalar such as 12345 or true is just a plain token. | ||
| return [list_as_str.strip()] |
There was a problem hiding this comment.
A JSON string scalar hits this branch too. '"@alice"' parses to the str @alice, but we return the original text with its quotes. The decoded value should win when it's a string.
| @@ -33,7 +33,10 @@ def unpack_and_flatten_str_to_list(list_as_str: str) -> List[str]: | |||
|
|
|||
| if isinstance(list_unpacked, list): | |||
| return list_unpacked | |||
There was a problem hiding this comment.
The list branch has the same problem as the scalar case for owners and tags: "[12345]" returns an int, and mixed lists fail when prettify_and_dedup_list sorts them. Note that test_rows_sample also comes through here and needs its list of dicts returned as is, so the conversion to strings belongs in unpack_and_flatten_and_dedup_list_of_strings rather than here.
| return list_unpacked | ||
| return [] # edge case of a string of an empty dict or IDK | ||
| if isinstance(list_unpacked, dict): | ||
| return [] # edge case of a string of an empty dict or IDK |
There was a problem hiding this comment.
This drops a dict to [], while _load_var_to_list keeps it as [json.dumps(dict)]. That's one of the disagreements in point 3 of the summary.
| if isinstance(loaded_var, dict): | ||
| loaded_var = [json.dumps(loaded_var)] | ||
| if loaded_var is None: | ||
| if loaded_var is None or not isinstance(loaded_var, list): |
There was a problem hiding this comment.
This is the second copy of the same scalar fix. It has the same quoted-string issue ('"prod"' becomes ['"prod"']) and keeps whitespace where the alerts path strips it. See the nit in the summary about delegating to one shared helper. Also a small nit: is None is redundant, because None already fails isinstance(..., list).
|
Thanks for the detailed review. Updated the quoted-string and numeric-list paths and added regression coverage:
I kept comma splitting, dict handling, duplicate retention and ordering at their existing caller-specific boundaries rather than merging the full parsers. That avoids changing The initial reviewer-case tests produced nine failures before the repair. The updated parser/formatter tests pass (25), and the unit suite excluding |
An owner or tag set to a plain number or boolean, for example
owner: 12345in a dbt config, crashes the monitor. The same value in an alert's owners or tags is silently dropped.Repro on current master:
Cause: both helpers run the value through
json.loadsfirst.12345,1.5andtrueare valid JSON, so they come back as an int, float or bool.ExtendedBaseModel._load_var_to_listreturns that scalar as is, which fails theList[str]validation.unpack_and_flatten_str_to_listonly accepts a list and returns[]for anything else.Fix: a JSON scalar is kept as the plain string token. Lists, comma separated strings and the existing handling of dicts and
{}do not change. Source change is +6/-2 lines.Tests: new
tests/unit/utils/test_json_utils.py. 7 of the 9 cases fail on master and all pass with the change.tests/unitotherwise passes (486). The 4 failures intests/unit/clients/dbt_runner/test_retry_logic.pyalso fail on unmodified master (timeouts) and are unrelated.AI disclosure: this change was written with AI assistance (Claude), then reviewed and tested locally by the submitter.
Summary by CodeRabbit
nullare now preserved as single-item results instead of being discarded.