github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/search/issues/issues.go (about) 1 package issues 2 3 import ( 4 "fmt" 5 6 "github.com/MakeNowJust/heredoc" 7 "github.com/ungtb10d/cli/v2/pkg/cmd/search/shared" 8 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 9 "github.com/ungtb10d/cli/v2/pkg/search" 10 "github.com/spf13/cobra" 11 ) 12 13 func NewCmdIssues(f *cmdutil.Factory, runF func(*shared.IssuesOptions) error) *cobra.Command { 14 var locked, includePrs bool 15 var noAssignee, noLabel, noMilestone, noProject bool 16 var order, sort string 17 var appAuthor string 18 opts := &shared.IssuesOptions{ 19 Browser: f.Browser, 20 Entity: shared.Issues, 21 IO: f.IOStreams, 22 Query: search.Query{Kind: search.KindIssues, 23 Qualifiers: search.Qualifiers{Type: "issue"}}, 24 } 25 26 cmd := &cobra.Command{ 27 Use: "issues [<query>]", 28 Short: "Search for issues", 29 Long: heredoc.Doc(` 30 Search for issues on GitHub. 31 32 The command supports constructing queries using the GitHub search syntax, 33 using the parameter and qualifier flags, or a combination of the two. 34 35 GitHub search syntax is documented at: 36 <https://docs.github.com/search-github/searching-on-github/searching-issues-and-pull-requests> 37 `), 38 Example: heredoc.Doc(` 39 # search issues matching set of keywords "readme" and "typo" 40 $ gh search issues readme typo 41 42 # search issues matching phrase "broken feature" 43 $ gh search issues "broken feature" 44 45 # search issues and pull requests in cli organization 46 $ gh search issues --include-prs --owner=cli 47 48 # search open issues assigned to yourself 49 $ gh search issues --assignee=@me --state=open 50 51 # search issues with numerous comments 52 $ gh search issues --comments=">100" 53 54 # search issues without label "bug" 55 $ gh search issues -- -label:bug 56 `), 57 RunE: func(c *cobra.Command, args []string) error { 58 if len(args) == 0 && c.Flags().NFlag() == 0 { 59 return cmdutil.FlagErrorf("specify search keywords or flags") 60 } 61 if opts.Query.Limit < 1 || opts.Query.Limit > shared.SearchMaxResults { 62 return cmdutil.FlagErrorf("`--limit` must be between 1 and 1000") 63 } 64 if c.Flags().Changed("author") && c.Flags().Changed("app") { 65 return cmdutil.FlagErrorf("specify only `--author` or `--app`") 66 } 67 if c.Flags().Changed("app") { 68 opts.Query.Qualifiers.Author = fmt.Sprintf("app/%s", appAuthor) 69 } 70 if includePrs { 71 opts.Entity = shared.Both 72 opts.Query.Qualifiers.Type = "" 73 } 74 if c.Flags().Changed("order") { 75 opts.Query.Order = order 76 } 77 if c.Flags().Changed("sort") { 78 opts.Query.Sort = sort 79 } 80 if c.Flags().Changed("locked") { 81 if locked { 82 opts.Query.Qualifiers.Is = append(opts.Query.Qualifiers.Is, "locked") 83 } else { 84 opts.Query.Qualifiers.Is = append(opts.Query.Qualifiers.Is, "unlocked") 85 } 86 } 87 if c.Flags().Changed("no-assignee") && noAssignee { 88 opts.Query.Qualifiers.No = append(opts.Query.Qualifiers.No, "assignee") 89 } 90 if c.Flags().Changed("no-label") && noLabel { 91 opts.Query.Qualifiers.No = append(opts.Query.Qualifiers.No, "label") 92 } 93 if c.Flags().Changed("no-milestone") && noMilestone { 94 opts.Query.Qualifiers.No = append(opts.Query.Qualifiers.No, "milestone") 95 } 96 if c.Flags().Changed("no-project") && noProject { 97 opts.Query.Qualifiers.No = append(opts.Query.Qualifiers.No, "project") 98 } 99 opts.Query.Keywords = args 100 if runF != nil { 101 return runF(opts) 102 } 103 var err error 104 opts.Searcher, err = shared.Searcher(f) 105 if err != nil { 106 return err 107 } 108 return shared.SearchIssues(opts) 109 }, 110 } 111 112 // Output flags 113 cmdutil.AddJSONFlags(cmd, &opts.Exporter, search.IssueFields) 114 cmd.Flags().BoolVarP(&opts.WebMode, "web", "w", false, "Open the search query in the web browser") 115 116 // Query parameter flags 117 cmd.Flags().IntVarP(&opts.Query.Limit, "limit", "L", 30, "Maximum number of results to fetch") 118 cmdutil.StringEnumFlag(cmd, &order, "order", "", "desc", []string{"asc", "desc"}, "Order of results returned, ignored unless '--sort' flag is specified") 119 cmdutil.StringEnumFlag(cmd, &sort, "sort", "", "best-match", 120 []string{ 121 "comments", 122 "created", 123 "interactions", 124 "reactions", 125 "reactions-+1", 126 "reactions--1", 127 "reactions-heart", 128 "reactions-smile", 129 "reactions-tada", 130 "reactions-thinking_face", 131 "updated", 132 }, "Sort fetched results") 133 134 // Query qualifier flags 135 cmd.Flags().BoolVar(&includePrs, "include-prs", false, "Include pull requests in results") 136 cmd.Flags().StringVar(&appAuthor, "app", "", "Filter by GitHub App author") 137 cmdutil.NilBoolFlag(cmd, &opts.Query.Qualifiers.Archived, "archived", "", "Restrict search to archived repositories") 138 cmd.Flags().StringVar(&opts.Query.Qualifiers.Assignee, "assignee", "", "Filter by assignee") 139 cmd.Flags().StringVar(&opts.Query.Qualifiers.Author, "author", "", "Filter by author") 140 cmd.Flags().StringVar(&opts.Query.Qualifiers.Closed, "closed", "", "Filter on closed at `date`") 141 cmd.Flags().StringVar(&opts.Query.Qualifiers.Commenter, "commenter", "", "Filter based on comments by `user`") 142 cmd.Flags().StringVar(&opts.Query.Qualifiers.Comments, "comments", "", "Filter on `number` of comments") 143 cmd.Flags().StringVar(&opts.Query.Qualifiers.Created, "created", "", "Filter based on created at `date`") 144 cmdutil.StringSliceEnumFlag(cmd, &opts.Query.Qualifiers.In, "match", "", nil, []string{"title", "body", "comments"}, "Restrict search to specific field of issue") 145 cmd.Flags().StringVar(&opts.Query.Qualifiers.Interactions, "interactions", "", "Filter on `number` of reactions and comments") 146 cmd.Flags().StringVar(&opts.Query.Qualifiers.Involves, "involves", "", "Filter based on involvement of `user`") 147 cmdutil.StringSliceEnumFlag(cmd, &opts.Query.Qualifiers.Is, "visibility", "", nil, []string{"public", "private", "internal"}, "Filter based on repository visibility") 148 cmd.Flags().StringSliceVar(&opts.Query.Qualifiers.Label, "label", nil, "Filter on label") 149 cmd.Flags().StringVar(&opts.Query.Qualifiers.Language, "language", "", "Filter based on the coding language") 150 cmd.Flags().BoolVar(&locked, "locked", false, "Filter on locked conversation status") 151 cmd.Flags().StringVar(&opts.Query.Qualifiers.Mentions, "mentions", "", "Filter based on `user` mentions") 152 cmd.Flags().StringVar(&opts.Query.Qualifiers.Milestone, "milestone", "", "Filter by milestone `title`") 153 cmd.Flags().BoolVar(&noAssignee, "no-assignee", false, "Filter on missing assignee") 154 cmd.Flags().BoolVar(&noLabel, "no-label", false, "Filter on missing label") 155 cmd.Flags().BoolVar(&noMilestone, "no-milestone", false, "Filter on missing milestone") 156 cmd.Flags().BoolVar(&noProject, "no-project", false, "Filter on missing project") 157 cmd.Flags().StringVar(&opts.Query.Qualifiers.Project, "project", "", "Filter on project board `number`") 158 cmd.Flags().StringVar(&opts.Query.Qualifiers.Reactions, "reactions", "", "Filter on `number` of reactions") 159 cmd.Flags().StringSliceVar(&opts.Query.Qualifiers.Repo, "repo", nil, "Filter on repository") 160 cmdutil.StringEnumFlag(cmd, &opts.Query.Qualifiers.State, "state", "", "", []string{"open", "closed"}, "Filter based on state") 161 cmd.Flags().StringVar(&opts.Query.Qualifiers.Team, "team-mentions", "", "Filter based on team mentions") 162 cmd.Flags().StringVar(&opts.Query.Qualifiers.Updated, "updated", "", "Filter on last updated at `date`") 163 cmd.Flags().StringVar(&opts.Query.Qualifiers.User, "owner", "", "Filter on repository owner") 164 165 return cmd 166 }