fix(cli)!: coder groups list -o json returns empty values (#22923)

The groupsToRows function was not setting the Group field on
groupTableRow, causing JSON output to contain zero-value structs. Table
output was unaffected since it uses separate fields.

BREAKING CHANGE: The JSON output structure changes from `{"Group":
{"id": ...}}` to `{"id": ...}` (flat). This is technically a breaking
change, but JSON output never contained real data (all fields were
zero-valued), so no working consumer could exist. We're taking the
opportunity to flatten the structure to match other list commands like
`coder list -o json`.
This commit is contained in:
Zach
2026-03-11 09:45:00 -06:00
committed by GitHub
parent 40114b8eea
commit a46336c3ec
2 changed files with 60 additions and 1 deletions
+2 -1
View File
@@ -67,7 +67,7 @@ func (r *RootCmd) groupList() *serpent.Command {
type groupTableRow struct {
// For json output:
Group codersdk.Group `table:"-"`
codersdk.Group `table:"-"`
// For table output:
Name string `json:"-" table:"name,default_sort"`
@@ -85,6 +85,7 @@ func groupsToRows(groups ...codersdk.Group) []groupTableRow {
members = append(members, member.Email)
}
rows = append(rows, groupTableRow{
Group: group,
Name: group.Name,
DisplayName: group.DisplayName,
OrganizationID: group.OrganizationID,
+58
View File
@@ -1,8 +1,11 @@
package cli_test
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest"
@@ -86,4 +89,59 @@ func TestGroupList(t *testing.T) {
pty.ExpectMatch(match)
}
})
t.Run("JSON", func(t *testing.T) {
t.Parallel()
client, admin := coderdenttest.New(t, &coderdenttest.Options{LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureTemplateRBAC: 1,
},
}})
anotherClient, _ := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID, rbac.RoleUserAdmin())
_, user1 := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
group := coderdtest.CreateGroup(t, client, admin.OrganizationID, "alpha", user1)
inv, conf := newCLI(t, "groups", "list", "-o", "json")
clitest.SetupConfig(t, anotherClient, conf)
buf := new(bytes.Buffer)
inv.Stdout = buf
err := inv.Run()
require.NoError(t, err)
var rows []codersdk.Group
err = json.Unmarshal(buf.Bytes(), &rows)
require.NoError(t, err, "unmarshal JSON output")
require.Len(t, rows, 2, "expected Everyone group and alpha group")
groupsByName := make(map[string]codersdk.Group)
for _, g := range rows {
groupsByName[g.Name] = g
}
// Verify the "Everyone" group.
everyone, ok := groupsByName["Everyone"]
require.True(t, ok, "expected Everyone group in JSON output")
assert.Equal(t, admin.OrganizationID, everyone.ID, "Everyone group ID matches org ID")
assert.Equal(t, admin.OrganizationID, everyone.OrganizationID)
// Verify the created group.
alpha, ok := groupsByName["alpha"]
require.True(t, ok, "expected alpha group in JSON output")
assert.Equal(t, group.ID, alpha.ID)
assert.Equal(t, group.Name, alpha.Name)
assert.Equal(t, group.DisplayName, alpha.DisplayName)
assert.Equal(t, group.OrganizationID, alpha.OrganizationID)
assert.Equal(t, group.AvatarURL, alpha.AvatarURL)
assert.Equal(t, group.QuotaAllowance, alpha.QuotaAllowance)
assert.Equal(t, group.Source, alpha.Source)
require.Len(t, alpha.Members, 1)
assert.Equal(t, user1.ID, alpha.Members[0].ID)
assert.Equal(t, user1.Email, alpha.Members[0].Email)
})
}