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