Skip to content

fix(jtk): include custom fields in search/list JSON output#180

Merged
rianjs merged 5 commits intomainfrom
fix/jtk-search-custom-fields
Mar 14, 2026
Merged

fix(jtk): include custom fields in search/list JSON output#180
rianjs merged 5 commits intomainfrom
fix/jtk-search-custom-fields

Conversation

@rianjs
Copy link
Copy Markdown
Contributor

@rianjs rianjs commented Mar 14, 2026

Closes #179

Summary

  • JSON output from issues search and issues list now requests all fields (*all) from the Jira API instead of a hardcoded built-in list, so custom fields are no longer null
  • Adds --fields flag to both commands for explicit field selection (comma-separated, e.g. --fields summary,customfield_10005)
  • Trims whitespace in --fields values for ergonomic input

Field resolution priority:

  1. --fields specified → use those exact fields
  2. -o json → use *all (return everything)
  3. --full → use DefaultSearchFields
  4. default → use ListSearchFields

Table output is unaffected — columns are hardcoded regardless of which fields are fetched.

Test plan

  • Unit tests for resolveFields covering all branches + whitespace/trailing comma edge cases
  • Regression tests verifying outbound HTTP request body contains *all for JSON output
  • Tests verifying --fields overrides the JSON default
  • Tests verifying table output still uses ListSearchFields
  • All existing tests pass
  • Manual smoke test: jtk issues search --jql 'key = MON-4036' -o json | jq '.[0].fields.customfield_10005'

Copy link
Copy Markdown

@monit-reviewer monit-reviewer left a comment

Choose a reason for hiding this comment

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

Automated PR Review

Reviewed commit: 3db43ed

Summary

Reviewer Findings
security:code-auditor 3
security:code-auditor (3 findings)

⚠️ Should Fix - tools/jtk/internal/cmd/issues/search_fields.go:12

resolveFields returns api.DefaultSearchFields and api.ListSearchFields by reference (slices). A caller that appends to the returned slice could mutate the package-level variable. Consider returning a copy: append([]string(nil), api.DefaultSearchFields...) for the full and default cases.

💡 Suggestion - tools/jtk/internal/cmd/issues/search_fields.go:21

When --fields produces zero non-empty tokens (e.g. --fields ",, "), resolveFields returns an empty slice rather than falling through to the json/full/default logic. An empty fields list may cause the Jira API to return no fields or an error. Consider falling through when the parsed slice is empty, or returning an error.

💡 Suggestion - tools/jtk/internal/cmd/issues/search_fields_test.go:1

No test covers the edge case where fieldsFlag is non-empty but resolves to zero fields after trimming (e.g. --fields ",, "). The code returns an empty slice in this scenario, but the behaviour is not tested.


Completed in 47s | $0.18 | sonnet
Field Value
Model sonnet
Reviewers hybrid-synthesis, security:code-auditor
Reviewed by pr-review-daemon · monit-pr-reviewer
Duration 47s (Reviewers: 31s · Synthesis: 18s)
Cost $0.18
Tokens 79.3k in / 2.6k out
Turns 7

// resolveFields determines which fields to request from the Jira API based on
// the --fields flag, output format, and --full flag.
func resolveFields(fieldsFlag, outputFormat string, full bool) []string {
if fieldsFlag != "" {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium (security:code-auditor): resolveFields returns api.DefaultSearchFields and api.ListSearchFields by reference (slices). A caller that appends to the returned slice could mutate the package-level variable. Consider returning a copy: append([]string(nil), api.DefaultSearchFields...) for the full and default cases.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 803f690 — now returns copies via append([]string(nil), ...) for both DefaultSearchFields and ListSearchFields.

}
}
return fields
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low (security:code-auditor): When --fields produces zero non-empty tokens (e.g. --fields ",, "), resolveFields returns an empty slice rather than falling through to the json/full/default logic. An empty fields list may cause the Jira API to return no fields or an error. Consider falling through when the parsed slice is empty, or returning an error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 803f690 — empty token list now falls through to the json/full/default logic instead of returning an empty slice.

@@ -0,0 +1,277 @@
package issues
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low (security:code-auditor): No test covers the edge case where fieldsFlag is non-empty but resolves to zero fields after trimming (e.g. --fields ",, "). The code returns an empty slice in this scenario, but the behaviour is not tested.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added in 803f690 — two new test cases: all empty tokens falls through to json default and all empty tokens falls through to list default.

Copy link
Copy Markdown

@monit-reviewer monit-reviewer left a comment

Choose a reason for hiding this comment

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

Automated PR Review

Reviewed commit: 803f690

Approved with 3 non-blocking suggestions below. Address at your discretion.

Summary

Reviewer Findings
security:code-auditor 3
security:code-auditor (3 findings)

💡 Suggestion - tools/jtk/internal/cmd/issues/search_fields.go:23

When --fields contains only whitespace/empty tokens, the code silently falls through to defaults with no user feedback. A warning to stderr when fieldsFlag is non-empty but yields zero valid fields would help users catch typos like '--fields , ,'.

💡 Suggestion - tools/jtk/internal/cmd/issues/search_fields_test.go:113

newSearchServer only handles the happy path: it always returns HTTP 200 with a fixed body regardless of the HTTP method or path. Adding a method/path assertion (e.g. checking r.URL.Path contains 'search') would make test failures easier to diagnose.

💡 Suggestion - tools/jtk/internal/cmd/issues/search_fields_test.go:148

The integration-style tests (TestRunSearch_, TestRunList_) only assert on captured.Fields and not on response parsing or rendered output. If JSON marshalling of Fields in api.SearchRequest changes (e.g. omitempty added), these tests would still pass while the feature breaks. A complementary assertion on stdout output for at least one test case would increase confidence.


Completed in 48s | $0.15 | sonnet
Field Value
Model sonnet
Reviewers hybrid-synthesis, security:code-auditor
Reviewed by pr-review-daemon · monit-pr-reviewer
Duration 48s (Reviewers: 39s · Synthesis: 11s)
Cost $0.15
Tokens 79.8k in / 2.5k out
Turns 7

if len(fields) > 0 {
return fields
}
// Fall through to defaults if all tokens were empty/whitespace
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low (security:code-auditor): When --fields contains only whitespace/empty tokens, the code silently falls through to defaults with no user feedback. A warning to stderr when fieldsFlag is non-empty but yields zero valid fields would help users catch typos like '--fields , ,'.

testutil.Equal(t, tt.want[i], got[i])
}
})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low (security:code-auditor): newSearchServer only handles the happy path: it always returns HTTP 200 with a fixed body regardless of the HTTP method or path. Adding a method/path assertion (e.g. checking r.URL.Path contains 'search') would make test failures easier to diagnose.

_ = json.NewEncoder(w).Encode(result)
}))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low (security:code-auditor): The integration-style tests (TestRunSearch_, TestRunList_) only assert on captured.Fields and not on response parsing or rendered output. If JSON marshalling of Fields in api.SearchRequest changes (e.g. omitempty added), these tests would still pass while the feature breaks. A complementary assertion on stdout output for at least one test case would increase confidence.

rianjs added 4 commits March 14, 2026 08:26
jtk README: add dashboards and links command sections, add --type/
--assignee/--parent flags to issues create/update, add --full and
--next-page-token to issues list/search, fix --max default (50→25),
document escape sequence support in --description.

jtk CHANGELOG: add 9 missing Unreleased entries (dashboards, links,
bearer auth, pagination, assignee, parent, type change, escapes,
automation rule builder).

cfl CHANGELOG: add 3 missing Unreleased entries (bearer auth,
--storage flag, wiki-link syntax).

Top-level README: add dashboards, links, fields, space management,
and config examples to quick reference sections.
JSON output from `issues search` and `issues list` now requests all
fields (`*all`) from the Jira API instead of a hardcoded built-in list,
so custom fields are no longer null. Adds a `--fields` flag to both
commands for explicit field selection.
Adds httptest-based tests verifying the outbound request body contains
the correct fields parameter: *all for JSON output, explicit fields when
--fields is set, and ListSearchFields for table output. Also fixes
whitespace trimming in --fields parsing and adds edge case tests.
…llthrough

- Return copies of package-level field slices to prevent caller mutation
- Fall through to defaults when --fields contains only empty/whitespace tokens
- Add tests for all-empty-tokens edge case
@rianjs rianjs force-pushed the fix/jtk-search-custom-fields branch from 803f690 to 183c42e Compare March 14, 2026 12:26
@rianjs rianjs merged commit 29259c8 into main Mar 14, 2026
7 checks passed
@rianjs rianjs deleted the fix/jtk-search-custom-fields branch March 14, 2026 12:30
rianjs added a commit that referenced this pull request Mar 28, 2026
Catches up documentation for recent features and fixes:
- README: document --fields flag, auto-pagination, fields command group,
  users get subcommand, --assignee none, multi-value --field, and
  escape sequences in comment --body
- CHANGELOG: add entries for PRs #178, #180, #182, #186-189
- integration-tests: add test cases for auto-pagination, --fields,
  users get, --assignee none, multi-value --field, and escape sequences

Closes #183
rianjs added a commit that referenced this pull request Mar 28, 2026
#190)

Catches up documentation for recent features and fixes:
- README: document --fields flag, auto-pagination, fields command group,
  users get subcommand, --assignee none, multi-value --field, and
  escape sequences in comment --body
- CHANGELOG: add entries for PRs #178, #180, #182, #186-189
- integration-tests: add test cases for auto-pagination, --fields,
  users get, --assignee none, multi-value --field, and escape sequences

Closes #183
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.

fix(jtk): issues search -o json omits custom fields

2 participants