feat: warn on unexpected team field shape in verbose mode (#195)#242
Merged
feat: warn on unexpected team field shape in verbose mode (#195)#242
Conversation
IssueFields::team_id previously returned None silently when the team
field was present but not a JSON string — typically an object like
{"id": "..."} delivered by a misconfigured team_field_id pointing at a
non-Teams custom field (user picker, select list, etc.). The Team row
on "jr issue view" silently disappeared with no signal to the user.
Add a verbose: bool parameter. On the "present but not a string, not
null" path, emit a once-per-process [verbose] hint to stderr naming
the field and the actual value kind. Null and missing remain silent
(those are well-formed "no team set" states, not config errors).
Matches the existing observability pattern from src/observability.rs:
inline static AtomicBool gate + eprintln!("[verbose] ..."). The gate
ordering (verbose check before swap) is the same invariant pinned by
observability::tests::verbose_false_leaves_flag_untouched.
Adds unit coverage for object and array value shapes; updates existing
tests to pass verbose=false.
Closes #195
There was a problem hiding this comment.
Pull request overview
Adds a verbose-only diagnostic when a Jira “team” custom field is present but has an unexpected JSON shape (e.g., object/array) so jr issue view doesn’t silently omit the Team row with no hint.
Changes:
- Extend
IssueFields::team_idto acceptverbose: booland emit a once-per-process[verbose]warning on unexpected non-null, non-string values. - Add a small
value_kind()helper to describe the observed JSON value kind in the warning. - Update the
issue viewcall site to passclient.verbose()and expand unit tests for additional non-string shapes.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/types/jira/issue.rs |
Implements verbose-gated, once-per-process warning for unexpected team field shapes; adds helper and updates tests. |
src/cli/issue/list.rs |
Passes client.verbose() into team_id() so the hint is controlled by --verbose. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
IssueFields::team_idpreviously returnedNonesilently when the team field was present but not a JSON string — typically an object like{"id": "..."}delivered by a misconfiguredteam_field_idpointing at a non-Teams custom field. The Team row onjr issue viewsilently disappeared with no diagnostic.This change adds a
verbose: boolparameter. On the "present but not a string, not null" path, we emit a once-per-process[verbose]hint to stderr naming the field and the actual value kind (object,array,number,bool). Null and missing remain silent — those are well-formed "no team set" states, not configuration errors.Design
Follows the existing pattern from
src/observability.rs::log_parse_failure_once: inlinestatic AtomicBoolgate +eprintln!("[verbose] ..."). The gate ordering (verbose check beforeswap(true)) preserves the same invariant pinned inobservability::tests::verbose_false_leaves_flag_untouched— a non-verbose run doesn't burn the flag.I considered refactoring
log_parse_failure_onceinto a shared helper, but kept inline duplication: the existing helper encodes a fixed message template ("{site} timestamp failed to parse: {iso}") and generalizing it for a second caller would widen its responsibility and add public API surface for a two-caller pattern. YAGNI.Changes
src/types/jira/issue.rs—team_id(&self, field_id, verbose)signature +value_kind()helpersrc/cli/issue/list.rs:934— call site passesclient.verbose()Scope notes
handle_viewin list.rs). The signature change is narrow.--verboseper the project's existing verbose-logging convention (no tracing crate).Test plan
cargo fmt --all -- --checkcleancargo clippy --all-targets -- -D warningscleancargo test— 805 passed, 0 failed (baseline 803 + 2 new)team_id_*unit tests all passCloses #195