Fetch codespace by name directly if name argument given
This commit is contained in:
parent
e8212a80a9
commit
75c1dfdf49
4 changed files with 174 additions and 33 deletions
|
|
@ -28,14 +28,16 @@ type deleteOptions struct {
|
|||
prompter prompter
|
||||
}
|
||||
|
||||
//go:generate moq -fmt goimports -rm -out mock_prompter.go . prompter
|
||||
//go:generate moq -fmt goimports -rm -skip-ensure -out mock_prompter.go . prompter
|
||||
type prompter interface {
|
||||
Confirm(message string) (bool, error)
|
||||
}
|
||||
|
||||
//go:generate moq -fmt goimports -rm -out mock_api.go . apiClient
|
||||
//go:generate moq -fmt goimports -rm -skip-ensure -out mock_api.go . apiClient
|
||||
type apiClient interface {
|
||||
GetUser(ctx context.Context) (*api.User, error)
|
||||
GetCodespaceToken(ctx context.Context, user, name string) (string, error)
|
||||
GetCodespace(ctx context.Context, token, user, name string) (*api.Codespace, error)
|
||||
ListCodespaces(ctx context.Context, user string) ([]*api.Codespace, error)
|
||||
DeleteCodespace(ctx context.Context, user, name string) error
|
||||
}
|
||||
|
|
@ -80,18 +82,34 @@ func delete(ctx context.Context, log logger, opts deleteOptions) error {
|
|||
return fmt.Errorf("error getting user: %w", err)
|
||||
}
|
||||
|
||||
codespaces, err := opts.apiClient.ListCodespaces(ctx, user.Login)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting codespaces: %w", err)
|
||||
}
|
||||
|
||||
var codespaces []*api.Codespace
|
||||
nameFilter := opts.codespaceName
|
||||
if nameFilter == "" && !opts.deleteAll && opts.repoFilter == "" {
|
||||
c, err := chooseCodespaceFromList(ctx, codespaces)
|
||||
if nameFilter == "" {
|
||||
codespaces, err = opts.apiClient.ListCodespaces(ctx, user.Login)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error choosing codespace: %w", err)
|
||||
return fmt.Errorf("error getting codespaces: %w", err)
|
||||
}
|
||||
nameFilter = c.Name
|
||||
|
||||
if !opts.deleteAll && opts.repoFilter == "" {
|
||||
c, err := chooseCodespaceFromList(ctx, codespaces)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error choosing codespace: %w", err)
|
||||
}
|
||||
nameFilter = c.Name
|
||||
}
|
||||
} else {
|
||||
// TODO: this token is discarded and then re-requested later in DeleteCodespace
|
||||
token, err := opts.apiClient.GetCodespaceToken(ctx, user.Login, nameFilter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting codespace token: %w", err)
|
||||
}
|
||||
|
||||
codespace, err := opts.apiClient.GetCodespace(ctx, token, user.Login, nameFilter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching codespace information: %w", err)
|
||||
}
|
||||
|
||||
codespaces = []*api.Codespace{codespace}
|
||||
}
|
||||
|
||||
codespacesToDelete := make([]*api.Codespace, 0, len(codespaces))
|
||||
|
|
@ -112,7 +130,7 @@ func delete(ctx context.Context, log logger, opts deleteOptions) error {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if nameFilter == "" || !opts.skipConfirm {
|
||||
if !opts.skipConfirm {
|
||||
confirmed, err := confirmDeletion(opts.prompter, c, opts.isInteractive)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to confirm: %w", err)
|
||||
|
|
@ -133,7 +151,7 @@ func delete(ctx context.Context, log logger, opts deleteOptions) error {
|
|||
codespaceName := c.Name
|
||||
g.Go(func() error {
|
||||
if err := opts.apiClient.DeleteCodespace(ctx, user.Login, codespaceName); err != nil {
|
||||
log.Errorf("error deleting codespace %q: %v", codespaceName, err)
|
||||
_, _ = log.Errorf("error deleting codespace %q: %v", codespaceName, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -31,9 +31,6 @@ func TestDelete(t *testing.T) {
|
|||
codespaceName: "hubot-robawt-abc",
|
||||
},
|
||||
codespaces: []*api.Codespace{
|
||||
{
|
||||
Name: "monalisa-spoonknife-123",
|
||||
},
|
||||
{
|
||||
Name: "hubot-robawt-abc",
|
||||
},
|
||||
|
|
@ -130,12 +127,6 @@ func TestDelete(t *testing.T) {
|
|||
GetUserFunc: func(_ context.Context) (*api.User, error) {
|
||||
return user, nil
|
||||
},
|
||||
ListCodespacesFunc: func(_ context.Context, userLogin string) ([]*api.Codespace, error) {
|
||||
if userLogin != user.Login {
|
||||
return nil, fmt.Errorf("unexpected user %q", userLogin)
|
||||
}
|
||||
return tt.codespaces, nil
|
||||
},
|
||||
DeleteCodespaceFunc: func(_ context.Context, userLogin, name string) error {
|
||||
if userLogin != user.Login {
|
||||
return fmt.Errorf("unexpected user %q", userLogin)
|
||||
|
|
@ -143,6 +134,30 @@ func TestDelete(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
}
|
||||
if tt.opts.codespaceName == "" {
|
||||
apiMock.ListCodespacesFunc = func(_ context.Context, userLogin string) ([]*api.Codespace, error) {
|
||||
if userLogin != user.Login {
|
||||
return nil, fmt.Errorf("unexpected user %q", userLogin)
|
||||
}
|
||||
return tt.codespaces, nil
|
||||
}
|
||||
} else {
|
||||
apiMock.GetCodespaceTokenFunc = func(_ context.Context, userLogin, name string) (string, error) {
|
||||
if userLogin != user.Login {
|
||||
return "", fmt.Errorf("unexpected user %q", userLogin)
|
||||
}
|
||||
return "CS_TOKEN", nil
|
||||
}
|
||||
apiMock.GetCodespaceFunc = func(_ context.Context, token, userLogin, name string) (*api.Codespace, error) {
|
||||
if userLogin != user.Login {
|
||||
return nil, fmt.Errorf("unexpected user %q", userLogin)
|
||||
}
|
||||
if token != "CS_TOKEN" {
|
||||
return nil, fmt.Errorf("unexpected token %q", token)
|
||||
}
|
||||
return tt.codespaces[0], nil
|
||||
}
|
||||
}
|
||||
opts := tt.opts
|
||||
opts.apiClient = apiMock
|
||||
opts.now = func() time.Time { return now }
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@ import (
|
|||
"github.com/github/ghcs/internal/api"
|
||||
)
|
||||
|
||||
// Ensure, that apiClientMock does implement apiClient.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ apiClient = &apiClientMock{}
|
||||
|
||||
// apiClientMock is a mock implementation of apiClient.
|
||||
//
|
||||
// func TestSomethingThatUsesapiClient(t *testing.T) {
|
||||
|
|
@ -23,6 +19,12 @@ var _ apiClient = &apiClientMock{}
|
|||
// DeleteCodespaceFunc: func(ctx context.Context, user string, name string) error {
|
||||
// panic("mock out the DeleteCodespace method")
|
||||
// },
|
||||
// GetCodespaceFunc: func(ctx context.Context, token string, user string, name string) (*api.Codespace, error) {
|
||||
// panic("mock out the GetCodespace method")
|
||||
// },
|
||||
// GetCodespaceTokenFunc: func(ctx context.Context, user string, name string) (string, error) {
|
||||
// panic("mock out the GetCodespaceToken method")
|
||||
// },
|
||||
// GetUserFunc: func(ctx context.Context) (*api.User, error) {
|
||||
// panic("mock out the GetUser method")
|
||||
// },
|
||||
|
|
@ -39,6 +41,12 @@ type apiClientMock struct {
|
|||
// DeleteCodespaceFunc mocks the DeleteCodespace method.
|
||||
DeleteCodespaceFunc func(ctx context.Context, user string, name string) error
|
||||
|
||||
// GetCodespaceFunc mocks the GetCodespace method.
|
||||
GetCodespaceFunc func(ctx context.Context, token string, user string, name string) (*api.Codespace, error)
|
||||
|
||||
// GetCodespaceTokenFunc mocks the GetCodespaceToken method.
|
||||
GetCodespaceTokenFunc func(ctx context.Context, user string, name string) (string, error)
|
||||
|
||||
// GetUserFunc mocks the GetUser method.
|
||||
GetUserFunc func(ctx context.Context) (*api.User, error)
|
||||
|
||||
|
|
@ -56,6 +64,26 @@ type apiClientMock struct {
|
|||
// Name is the name argument value.
|
||||
Name string
|
||||
}
|
||||
// GetCodespace holds details about calls to the GetCodespace method.
|
||||
GetCodespace []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Token is the token argument value.
|
||||
Token string
|
||||
// User is the user argument value.
|
||||
User string
|
||||
// Name is the name argument value.
|
||||
Name string
|
||||
}
|
||||
// GetCodespaceToken holds details about calls to the GetCodespaceToken method.
|
||||
GetCodespaceToken []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// User is the user argument value.
|
||||
User string
|
||||
// Name is the name argument value.
|
||||
Name string
|
||||
}
|
||||
// GetUser holds details about calls to the GetUser method.
|
||||
GetUser []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -69,9 +97,11 @@ type apiClientMock struct {
|
|||
User string
|
||||
}
|
||||
}
|
||||
lockDeleteCodespace sync.RWMutex
|
||||
lockGetUser sync.RWMutex
|
||||
lockListCodespaces sync.RWMutex
|
||||
lockDeleteCodespace sync.RWMutex
|
||||
lockGetCodespace sync.RWMutex
|
||||
lockGetCodespaceToken sync.RWMutex
|
||||
lockGetUser sync.RWMutex
|
||||
lockListCodespaces sync.RWMutex
|
||||
}
|
||||
|
||||
// DeleteCodespace calls DeleteCodespaceFunc.
|
||||
|
|
@ -113,6 +143,88 @@ func (mock *apiClientMock) DeleteCodespaceCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// GetCodespace calls GetCodespaceFunc.
|
||||
func (mock *apiClientMock) GetCodespace(ctx context.Context, token string, user string, name string) (*api.Codespace, error) {
|
||||
if mock.GetCodespaceFunc == nil {
|
||||
panic("apiClientMock.GetCodespaceFunc: method is nil but apiClient.GetCodespace was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
User string
|
||||
Name string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Token: token,
|
||||
User: user,
|
||||
Name: name,
|
||||
}
|
||||
mock.lockGetCodespace.Lock()
|
||||
mock.calls.GetCodespace = append(mock.calls.GetCodespace, callInfo)
|
||||
mock.lockGetCodespace.Unlock()
|
||||
return mock.GetCodespaceFunc(ctx, token, user, name)
|
||||
}
|
||||
|
||||
// GetCodespaceCalls gets all the calls that were made to GetCodespace.
|
||||
// Check the length with:
|
||||
// len(mockedapiClient.GetCodespaceCalls())
|
||||
func (mock *apiClientMock) GetCodespaceCalls() []struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
User string
|
||||
Name string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Token string
|
||||
User string
|
||||
Name string
|
||||
}
|
||||
mock.lockGetCodespace.RLock()
|
||||
calls = mock.calls.GetCodespace
|
||||
mock.lockGetCodespace.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// GetCodespaceToken calls GetCodespaceTokenFunc.
|
||||
func (mock *apiClientMock) GetCodespaceToken(ctx context.Context, user string, name string) (string, error) {
|
||||
if mock.GetCodespaceTokenFunc == nil {
|
||||
panic("apiClientMock.GetCodespaceTokenFunc: method is nil but apiClient.GetCodespaceToken was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
User string
|
||||
Name string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
User: user,
|
||||
Name: name,
|
||||
}
|
||||
mock.lockGetCodespaceToken.Lock()
|
||||
mock.calls.GetCodespaceToken = append(mock.calls.GetCodespaceToken, callInfo)
|
||||
mock.lockGetCodespaceToken.Unlock()
|
||||
return mock.GetCodespaceTokenFunc(ctx, user, name)
|
||||
}
|
||||
|
||||
// GetCodespaceTokenCalls gets all the calls that were made to GetCodespaceToken.
|
||||
// Check the length with:
|
||||
// len(mockedapiClient.GetCodespaceTokenCalls())
|
||||
func (mock *apiClientMock) GetCodespaceTokenCalls() []struct {
|
||||
Ctx context.Context
|
||||
User string
|
||||
Name string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
User string
|
||||
Name string
|
||||
}
|
||||
mock.lockGetCodespaceToken.RLock()
|
||||
calls = mock.calls.GetCodespaceToken
|
||||
mock.lockGetCodespaceToken.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// GetUser calls GetUserFunc.
|
||||
func (mock *apiClientMock) GetUser(ctx context.Context) (*api.User, error) {
|
||||
if mock.GetUserFunc == nil {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that prompterMock does implement prompter.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ prompter = &prompterMock{}
|
||||
|
||||
// prompterMock is a mock implementation of prompter.
|
||||
//
|
||||
// func TestSomethingThatUsesprompter(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue