Skip to content

Do not output a json array for whoami command when --json is given#1905

Open
edwardrf wants to merge 1 commit intomainfrom
edw/whoami-output-json-not-array
Open

Do not output a json array for whoami command when --json is given#1905
edwardrf wants to merge 1 commit intomainfrom
edw/whoami-output-json-not-array

Conversation

@edwardrf
Copy link
Contributor

@edwardrf edwardrf commented Feb 4, 2026

Description

Also allow json table to correctly handle non-slice input

Linked Issues

Checklist

  • I have performed a self-review of my code
  • I have added appropriate tests
  • I have updated the Defang CLI docs and/or README to reflect my changes, if necessary

Summary by CodeRabbit

  • Refactor
    • Improved internal data handling for table output to support more flexible input formats.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

The term.Table API is refactored to accept individual data structures directly instead of requiring callers to wrap them in slices. The implementation now handles both single items and slices through internal reflect-based wrapping.

Changes

Cohort / File(s) Summary
Command layer
src/cmd/cli/command/whoami.go
Updated call to term.Table to pass a single ShowAccountData struct directly instead of wrapping it in a slice.
Term package API
src/pkg/term/table.go
Refactored Table and related methods to accept data any instead of slice any. Added internal logic to wrap single items into slices via reflect operations. Updated 4 method signatures: public Table function, Term.Table method, jsonTable method, and table method.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jordanstephens

Poem

🐰 A simpler way to show the data flow,
No slicing needed, just let it go,
Wrap it inside with reflect's keen eye,
One struct or many—the table flies high!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: the whoami command no longer outputs a JSON array when --json is given, which matches the primary purpose of the modifications in both files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch edw/whoami-output-json-not-array

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.5.0)

level=warning msg="[linters_context] running gomodguard failed: unable to read module file go.mod: current working directory must have a go.mod file: if you are not using go modules it is suggested to disable this linter"
level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/pkg/term/table.go`:
- Around line 28-34: The code in Term.table currently calls
reflect.ValueOf(data) and then uses val.Type(), which will panic if data is nil
(reflect.Value is invalid); add a nil/invalid check after val :=
reflect.ValueOf(data) and before using val.Type(): if data is nil (or
!val.IsValid()) construct a slice of the desired element type (e.g., []any or a
slice of the zero value type) or return an informative error, otherwise proceed
with the existing reflect.MakeSlice logic; update Term.table to handle the nil
case safely (check val.IsValid(), handle nil by creating a fallback slice or
returning an error) so val.Type() is never called on an invalid reflect.Value.

Comment on lines +28 to 34
func (t *Term) table(data any, attributes ...string) error {
// Ensure data is a slice
val := reflect.ValueOf(data)
if val.Kind() != reflect.Slice {
return errors.New("Table: input is not a slice")
val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
val.Index(0).Set(reflect.ValueOf(data))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential panic if nil is passed.

If data is nil, reflect.ValueOf(nil) returns a zero reflect.Value, and calling val.Type() on line 32 will panic. Consider adding a nil check if this is a realistic scenario.

🛡️ Optional defensive nil check
 func (t *Term) table(data any, attributes ...string) error {
 	// Ensure data is a slice
 	val := reflect.ValueOf(data)
+	if !val.IsValid() {
+		return nil // or return an error for nil input
+	}
 	if val.Kind() != reflect.Slice {
 		val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
 		val.Index(0).Set(reflect.ValueOf(data))
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (t *Term) table(data any, attributes ...string) error {
// Ensure data is a slice
val := reflect.ValueOf(data)
if val.Kind() != reflect.Slice {
return errors.New("Table: input is not a slice")
val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
val.Index(0).Set(reflect.ValueOf(data))
}
func (t *Term) table(data any, attributes ...string) error {
// Ensure data is a slice
val := reflect.ValueOf(data)
if !val.IsValid() {
return nil // or return an error for nil input
}
if val.Kind() != reflect.Slice {
val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
val.Index(0).Set(reflect.ValueOf(data))
}
🤖 Prompt for AI Agents
In `@src/pkg/term/table.go` around lines 28 - 34, The code in Term.table currently
calls reflect.ValueOf(data) and then uses val.Type(), which will panic if data
is nil (reflect.Value is invalid); add a nil/invalid check after val :=
reflect.ValueOf(data) and before using val.Type(): if data is nil (or
!val.IsValid()) construct a slice of the desired element type (e.g., []any or a
slice of the zero value type) or return an informative error, otherwise proceed
with the existing reflect.MakeSlice logic; update Term.table to handle the nil
case safely (check val.IsValid(), handle nil by creating a fallback slice or
returning an error) so val.Type() is never called on an invalid reflect.Value.

Comment on lines +32 to +33
val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
val.Index(0).Set(reflect.ValueOf(data))
Copy link
Member

Choose a reason for hiding this comment

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

What am I missing?

Suggested change
val = reflect.MakeSlice(reflect.SliceOf(val.Type()), 1, 1)
val.Index(0).Set(reflect.ValueOf(data))
val = reflect.ValueOf([]any{data})

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was my first instinct too, but this results in a slice of any, not slice of the type, which causes panic later when looping below. So maybe I should improve the code below to allow slice of interfaces to be passed in right now only slice of solid types can be used.

@lionello lionello enabled auto-merge (squash) February 4, 2026 22:46
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.

4 participants