github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/issue/delete/delete.go (about) 1 package delete 2 3 import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 8 "github.com/AlecAivazis/survey/v2" 9 "github.com/ungtb10d/cli/v2/api" 10 "github.com/ungtb10d/cli/v2/internal/config" 11 "github.com/ungtb10d/cli/v2/internal/ghrepo" 12 "github.com/ungtb10d/cli/v2/pkg/cmd/issue/shared" 13 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 14 "github.com/ungtb10d/cli/v2/pkg/iostreams" 15 "github.com/ungtb10d/cli/v2/pkg/prompt" 16 "github.com/shurcooL/githubv4" 17 "github.com/spf13/cobra" 18 ) 19 20 type DeleteOptions struct { 21 HttpClient func() (*http.Client, error) 22 Config func() (config.Config, error) 23 IO *iostreams.IOStreams 24 BaseRepo func() (ghrepo.Interface, error) 25 26 SelectorArg string 27 Confirmed bool 28 } 29 30 func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Command { 31 opts := &DeleteOptions{ 32 IO: f.IOStreams, 33 HttpClient: f.HttpClient, 34 Config: f.Config, 35 } 36 37 cmd := &cobra.Command{ 38 Use: "delete {<number> | <url>}", 39 Short: "Delete issue", 40 Args: cobra.ExactArgs(1), 41 RunE: func(cmd *cobra.Command, args []string) error { 42 // support `-R, --repo` override 43 opts.BaseRepo = f.BaseRepo 44 45 if len(args) > 0 { 46 opts.SelectorArg = args[0] 47 } 48 49 if runF != nil { 50 return runF(opts) 51 } 52 return deleteRun(opts) 53 }, 54 } 55 56 cmd.Flags().BoolVar(&opts.Confirmed, "confirm", false, "confirm deletion without prompting") 57 return cmd 58 } 59 60 func deleteRun(opts *DeleteOptions) error { 61 cs := opts.IO.ColorScheme() 62 63 httpClient, err := opts.HttpClient() 64 if err != nil { 65 return err 66 } 67 68 issue, baseRepo, err := shared.IssueFromArgWithFields(httpClient, opts.BaseRepo, opts.SelectorArg, []string{"id", "number", "title"}) 69 if err != nil { 70 return err 71 } 72 if issue.IsPullRequest() { 73 return fmt.Errorf("issue #%d is a pull request and cannot be deleted", issue.Number) 74 } 75 76 // When executed in an interactive shell, require confirmation, unless 77 // already provided. Otherwise skip confirmation. 78 if opts.IO.CanPrompt() && !opts.Confirmed { 79 answer := "" 80 //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter 81 err = prompt.SurveyAskOne( 82 &survey.Input{ 83 Message: fmt.Sprintf("You're going to delete issue #%d. This action cannot be reversed. To confirm, type the issue number:", issue.Number), 84 }, 85 &answer, 86 ) 87 if err != nil { 88 return err 89 } 90 answerInt, err := strconv.Atoi(answer) 91 if err != nil || answerInt != issue.Number { 92 fmt.Fprintf(opts.IO.Out, "Issue #%d was not deleted.\n", issue.Number) 93 return nil 94 } 95 } 96 97 if err := apiDelete(httpClient, baseRepo, issue.ID); err != nil { 98 return err 99 } 100 101 if opts.IO.IsStdoutTTY() { 102 fmt.Fprintf(opts.IO.ErrOut, "%s Deleted issue #%d (%s).\n", cs.Red("✔"), issue.Number, issue.Title) 103 } 104 105 return nil 106 } 107 108 func apiDelete(httpClient *http.Client, repo ghrepo.Interface, issueID string) error { 109 var mutation struct { 110 DeleteIssue struct { 111 Repository struct { 112 ID githubv4.ID 113 } 114 } `graphql:"deleteIssue(input: $input)"` 115 } 116 117 variables := map[string]interface{}{ 118 "input": githubv4.DeleteIssueInput{ 119 IssueID: issueID, 120 }, 121 } 122 123 gql := api.NewClientFromHTTP(httpClient) 124 return gql.Mutate(repo.RepoHost(), "IssueDelete", &mutation, variables) 125 }