From 984ca2be0d8716eba91d1955acd1eea3feb50bd6 Mon Sep 17 00:00:00 2001 From: Austin DeNoble Date: Wed, 18 Mar 2026 13:48:07 -0400 Subject: [PATCH 1/2] fix organization and project delete operations ignoring the --json flag, update tests --- .claude/settings.local.json | 19 ++++++ .../pkg/cli/command/organization/delete.go | 29 ++++++++- .../cli/command/organization/delete_test.go | 59 +++++++++++++++++++ internal/pkg/cli/command/project/delete.go | 26 +++++++- .../pkg/cli/command/project/delete_test.go | 59 +++++++++++++++++++ 5 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 internal/pkg/cli/command/organization/delete_test.go create mode 100644 internal/pkg/cli/command/project/delete_test.go diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..436037a4 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,19 @@ +{ + "permissions": { + "allow": [ + "mcp__claude_ai_Linear__get_project", + "mcp__claude_ai_Linear__list_teams", + "mcp__claude_ai_Linear__list_issue_labels", + "mcp__claude_ai_Linear__create_issue_label", + "mcp__claude_ai_Linear__save_issue", + "mcp__claude_ai_Linear__list_issues", + "mcp__claude_ai_Linear__get_issue", + "mcp__claude_ai_Linear__list_issue_statuses", + "Bash(git checkout:*)", + "Bash(go build:*)", + "Bash(go test:*)", + "Bash(grep:*)", + "Bash(go doc:*)" + ] + } +} diff --git a/internal/pkg/cli/command/organization/delete.go b/internal/pkg/cli/command/organization/delete.go index da8e83ee..0487f27d 100644 --- a/internal/pkg/cli/command/organization/delete.go +++ b/internal/pkg/cli/command/organization/delete.go @@ -2,6 +2,7 @@ package organization import ( "bufio" + "context" "fmt" "os" "strings" @@ -13,6 +14,7 @@ import ( "github.com/pinecone-io/cli/internal/pkg/utils/pcio" "github.com/pinecone-io/cli/internal/pkg/utils/sdk" "github.com/pinecone-io/cli/internal/pkg/utils/style" + "github.com/pinecone-io/cli/internal/pkg/utils/text" "github.com/spf13/cobra" ) @@ -22,6 +24,10 @@ type deleteOrganizationCmdOptions struct { json bool } +type deleteOrganizationService interface { + Delete(ctx context.Context, id string) error +} + func NewDeleteOrganizationCmd() *cobra.Command { options := deleteOrganizationCmdOptions{} @@ -48,20 +54,19 @@ func NewDeleteOrganizationCmd() *cobra.Command { confirmDelete(org.Name, org.Id) } - err = ac.Organization.Delete(cmd.Context(), options.organizationID) + err = runDeleteOrganizationCmd(ctx, ac.Organization, options, org.Name, org.Id) if err != nil { msg.FailMsg("Failed to delete organization %s: %s\n", options.organizationID, err) exit.Errorf(err, "Failed to delete organization %s", style.Emphasis(options.organizationID)) } - // Clear target project if the deleted project is the target project + // Clear target org if the deleted org is the target org if state.TargetOrg.Get().Id == options.organizationID { state.TargetOrg.Set(state.TargetOrganization{ Id: "", Name: "", }) } - msg.SuccessMsg("Organization %s (ID: %s) deleted.\n", style.Emphasis(org.Name), style.Emphasis(options.organizationID)) }, } @@ -76,6 +81,24 @@ func NewDeleteOrganizationCmd() *cobra.Command { return cmd } +func runDeleteOrganizationCmd(ctx context.Context, svc deleteOrganizationService, opts deleteOrganizationCmdOptions, name, id string) error { + if err := svc.Delete(ctx, id); err != nil { + return err + } + + if opts.json { + fmt.Println(text.IndentJSON(struct { + Deleted bool `json:"deleted"` + Name string `json:"name"` + Id string `json:"id"` + }{Deleted: true, Name: name, Id: id})) + return nil + } + + msg.SuccessMsg("Organization %s (ID: %s) deleted.\n", style.Emphasis(name), style.Emphasis(id)) + return nil +} + func confirmDelete(organizationName string, organizationID string) { msg.WarnMsg("This will delete the organization %s (ID: %s).", style.Emphasis(organizationName), style.Emphasis(organizationID)) msg.WarnMsg("This action cannot be undone.") diff --git a/internal/pkg/cli/command/organization/delete_test.go b/internal/pkg/cli/command/organization/delete_test.go new file mode 100644 index 00000000..56ad78fc --- /dev/null +++ b/internal/pkg/cli/command/organization/delete_test.go @@ -0,0 +1,59 @@ +package organization + +import ( + "context" + "errors" + "os" + "testing" + + "github.com/pinecone-io/cli/internal/pkg/cli/testutils" + "github.com/stretchr/testify/assert" +) + +type mockDeleteOrganizationService struct { + lastDeleteId string + deleteErr error +} + +func (m *mockDeleteOrganizationService) Delete(ctx context.Context, id string) error { + m.lastDeleteId = id + return m.deleteErr +} + +func TestMain(m *testing.M) { + reset := testutils.SilenceOutput() + code := m.Run() + reset() + os.Exit(code) +} + +func Test_runDeleteOrganizationCmd_Succeeds(t *testing.T) { + svc := &mockDeleteOrganizationService{} + opts := deleteOrganizationCmdOptions{organizationID: "org-123"} + + err := runDeleteOrganizationCmd(context.Background(), svc, opts, "my-org", "org-123") + + assert.NoError(t, err) + assert.Equal(t, "org-123", svc.lastDeleteId) +} + +func Test_runDeleteOrganizationCmd_SucceedsJSON(t *testing.T) { + svc := &mockDeleteOrganizationService{} + opts := deleteOrganizationCmdOptions{organizationID: "org-123", json: true} + + out := testutils.CaptureStdout(t, func() { + err := runDeleteOrganizationCmd(context.Background(), svc, opts, "my-org", "org-123") + assert.NoError(t, err) + }) + + assert.JSONEq(t, `{"deleted":true,"name":"my-org","id":"org-123"}`, out) +} + +func Test_runDeleteOrganizationCmd_PropagatesError(t *testing.T) { + svc := &mockDeleteOrganizationService{deleteErr: errors.New("service error")} + opts := deleteOrganizationCmdOptions{organizationID: "org-123"} + + err := runDeleteOrganizationCmd(context.Background(), svc, opts, "my-org", "org-123") + + assert.Error(t, err) +} diff --git a/internal/pkg/cli/command/project/delete.go b/internal/pkg/cli/command/project/delete.go index 3d15c6e6..1380b7ba 100644 --- a/internal/pkg/cli/command/project/delete.go +++ b/internal/pkg/cli/command/project/delete.go @@ -14,6 +14,7 @@ import ( "github.com/pinecone-io/cli/internal/pkg/utils/pcio" "github.com/pinecone-io/cli/internal/pkg/utils/sdk" "github.com/pinecone-io/cli/internal/pkg/utils/style" + "github.com/pinecone-io/cli/internal/pkg/utils/text" "github.com/spf13/cobra" ) @@ -23,6 +24,10 @@ type deleteProjectCmdOptions struct { json bool } +type deleteProjectService interface { + Delete(ctx context.Context, id string) error +} + func NewDeleteProjectCmd() *cobra.Command { options := deleteProjectCmdOptions{} @@ -65,7 +70,7 @@ func NewDeleteProjectCmd() *cobra.Command { confirmDelete(projToDelete.Name) } - err = ac.Project.Delete(ctx, projToDelete.Id) + err = runDeleteProjectCmd(ctx, ac.Project, options, projToDelete.Name, projToDelete.Id) if err != nil { msg.FailMsg("Failed to delete project %s: %s\n", style.Emphasis(projToDelete.Name), err) exit.Errorf(err, "Failed to delete project %s", style.Emphasis(projToDelete.Name)) @@ -78,7 +83,6 @@ func NewDeleteProjectCmd() *cobra.Command { Name: "", }) } - msg.SuccessMsg("Project %s deleted.\n", style.Emphasis(projToDelete.Name)) }, } @@ -90,6 +94,24 @@ func NewDeleteProjectCmd() *cobra.Command { return cmd } +func runDeleteProjectCmd(ctx context.Context, svc deleteProjectService, opts deleteProjectCmdOptions, name, id string) error { + if err := svc.Delete(ctx, id); err != nil { + return err + } + + if opts.json { + fmt.Println(text.IndentJSON(struct { + Deleted bool `json:"deleted"` + Name string `json:"name"` + Id string `json:"id"` + }{Deleted: true, Name: name, Id: id})) + return nil + } + + msg.SuccessMsg("Project %s deleted.\n", style.Emphasis(name)) + return nil +} + func confirmDelete(projectName string) { msg.WarnMsg("This will delete the project %s in organization %s.", style.Emphasis(projectName), style.Emphasis(state.TargetOrg.Get().Name)) msg.WarnMsg("This action cannot be undone.") diff --git a/internal/pkg/cli/command/project/delete_test.go b/internal/pkg/cli/command/project/delete_test.go new file mode 100644 index 00000000..e707adb6 --- /dev/null +++ b/internal/pkg/cli/command/project/delete_test.go @@ -0,0 +1,59 @@ +package project + +import ( + "context" + "errors" + "os" + "testing" + + "github.com/pinecone-io/cli/internal/pkg/cli/testutils" + "github.com/stretchr/testify/assert" +) + +type mockDeleteProjectService struct { + lastDeleteId string + deleteErr error +} + +func (m *mockDeleteProjectService) Delete(ctx context.Context, id string) error { + m.lastDeleteId = id + return m.deleteErr +} + +func TestMain(m *testing.M) { + reset := testutils.SilenceOutput() + code := m.Run() + reset() + os.Exit(code) +} + +func Test_runDeleteProjectCmd_Succeeds(t *testing.T) { + svc := &mockDeleteProjectService{} + opts := deleteProjectCmdOptions{projectId: "proj-123"} + + err := runDeleteProjectCmd(context.Background(), svc, opts, "my-project", "proj-123") + + assert.NoError(t, err) + assert.Equal(t, "proj-123", svc.lastDeleteId) +} + +func Test_runDeleteProjectCmd_SucceedsJSON(t *testing.T) { + svc := &mockDeleteProjectService{} + opts := deleteProjectCmdOptions{projectId: "proj-123", json: true} + + out := testutils.CaptureStdout(t, func() { + err := runDeleteProjectCmd(context.Background(), svc, opts, "my-project", "proj-123") + assert.NoError(t, err) + }) + + assert.JSONEq(t, `{"deleted":true,"name":"my-project","id":"proj-123"}`, out) +} + +func Test_runDeleteProjectCmd_PropagatesError(t *testing.T) { + svc := &mockDeleteProjectService{deleteErr: errors.New("service error")} + opts := deleteProjectCmdOptions{projectId: "proj-123"} + + err := runDeleteProjectCmd(context.Background(), svc, opts, "my-project", "proj-123") + + assert.Error(t, err) +} From 933514561400f4929d35c0f53fb4fe67ea3a39d0 Mon Sep 17 00:00:00 2001 From: Austin DeNoble Date: Wed, 18 Mar 2026 16:23:28 -0400 Subject: [PATCH 2/2] local settings file --- .claude/settings.local.json | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 436037a4..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "permissions": { - "allow": [ - "mcp__claude_ai_Linear__get_project", - "mcp__claude_ai_Linear__list_teams", - "mcp__claude_ai_Linear__list_issue_labels", - "mcp__claude_ai_Linear__create_issue_label", - "mcp__claude_ai_Linear__save_issue", - "mcp__claude_ai_Linear__list_issues", - "mcp__claude_ai_Linear__get_issue", - "mcp__claude_ai_Linear__list_issue_statuses", - "Bash(git checkout:*)", - "Bash(go build:*)", - "Bash(go test:*)", - "Bash(grep:*)", - "Bash(go doc:*)" - ] - } -}