diff --git a/cmd/ghcs/delete.go b/cmd/ghcs/delete.go index 7800a13c0..a3971f491 100644 --- a/cmd/ghcs/delete.go +++ b/cmd/ghcs/delete.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "strings" + "sync" "github.com/github/ghcs/api" "github.com/github/ghcs/cmd/ghcs/output" @@ -116,28 +117,58 @@ func deleteByRepo(log *output.Logger, repo string) error { return fmt.Errorf("error getting codespaces: %v", err) } - var deleted bool - for _, c := range codespaces { - if !strings.EqualFold(c.RepositoryNWO, repo) { - continue - } - deleted = true - - token, err := apiClient.GetCodespaceToken(ctx, user.Login, c.Name) + delete := func(name string) error { + token, err := apiClient.GetCodespaceToken(ctx, user.Login, name) if err != nil { return fmt.Errorf("error getting codespace token: %v", err) } - if err := apiClient.DeleteCodespace(ctx, user, token, c.Name); err != nil { + if err := apiClient.DeleteCodespace(ctx, user, token, name); err != nil { return fmt.Errorf("error deleting codespace: %v", err) } - log.Printf("Codespace deleted: %s\n", c.Name) + return nil } - if !deleted { + // Perform deletions in parallel. + var ( + found bool + mu sync.Mutex // guards errs, logger + errs []error + wg sync.WaitGroup + ) + for _, c := range codespaces { + if !strings.EqualFold(c.RepositoryNWO, repo) { + continue + } + found = true + c := c + wg.Add(1) + go func() { + defer wg.Done() + err := delete(c.Name) + mu.Lock() + defer mu.Unlock() + if err != nil { + errs = append(errs, err) + } else { + log.Printf("Codespace deleted: %s\n", c.Name) + } + }() + } + if !found { return fmt.Errorf("No codespace was found for repository: %s", repo) } + wg.Wait() + + // Return first error, plus count of others. + if errs != nil { + err := errs[0] + if others := len(errs) - 1; others > 0 { + err = fmt.Errorf("%w (+%d more)", err, others) + } + return err + } return list(&listOptions{}) }