|
| 1 | +package command |
| 2 | + |
| 3 | +import ( |
| 4 | + "errors" |
| 5 | + "fmt" |
| 6 | + "strconv" |
| 7 | + "strings" |
| 8 | + |
| 9 | + "github.com/cli/cli/api" |
| 10 | + "github.com/spf13/cobra" |
| 11 | +) |
| 12 | + |
| 13 | +func init() { |
| 14 | + prCmd.AddCommand(prReviewCmd) |
| 15 | + |
| 16 | + prReviewCmd.Flags().BoolP("approve", "a", false, "Approve pull request") |
| 17 | + prReviewCmd.Flags().BoolP("request-changes", "r", false, "Request changes on a pull request") |
| 18 | + prReviewCmd.Flags().BoolP("comment", "c", false, "Comment on a pull request") |
| 19 | + prReviewCmd.Flags().StringP("body", "b", "", "Specify the body of a review") |
| 20 | +} |
| 21 | + |
| 22 | +var prReviewCmd = &cobra.Command{ |
| 23 | + Use: "review [{<number> | <url> | <branch>]", |
| 24 | + Short: "Add a review to a pull request.", |
| 25 | + Args: cobra.MaximumNArgs(1), |
| 26 | + Long: `Add a review to either a specified pull request or the pull request associated with the current branch. |
| 27 | +
|
| 28 | +Examples: |
| 29 | +
|
| 30 | + gh pr review -a # mark the current branch's pull request as approved |
| 31 | + gh pr review -c -b "interesting" # comment on the current branch's pull request |
| 32 | + gh pr review 123 -r -b "needs more ascii art" # request changes on pull request 123 |
| 33 | + `, |
| 34 | + RunE: prReview, |
| 35 | +} |
| 36 | + |
| 37 | +func processReviewOpt(cmd *cobra.Command) (*api.PullRequestReviewInput, error) { |
| 38 | + found := 0 |
| 39 | + flag := "" |
| 40 | + var state api.PullRequestReviewState |
| 41 | + |
| 42 | + if cmd.Flags().Changed("approve") { |
| 43 | + found++ |
| 44 | + flag = "approve" |
| 45 | + state = api.ReviewApprove |
| 46 | + } |
| 47 | + if cmd.Flags().Changed("request-changes") { |
| 48 | + found++ |
| 49 | + flag = "request-changes" |
| 50 | + state = api.ReviewRequestChanges |
| 51 | + } |
| 52 | + if cmd.Flags().Changed("comment") { |
| 53 | + found++ |
| 54 | + flag = "comment" |
| 55 | + state = api.ReviewComment |
| 56 | + } |
| 57 | + |
| 58 | + if found != 1 { |
| 59 | + return nil, errors.New("need exactly one of --approve, --request-changes, or --comment") |
| 60 | + } |
| 61 | + |
| 62 | + body, err := cmd.Flags().GetString("body") |
| 63 | + if err != nil { |
| 64 | + return nil, err |
| 65 | + } |
| 66 | + |
| 67 | + if (flag == "request-changes" || flag == "comment") && body == "" { |
| 68 | + return nil, fmt.Errorf("body cannot be blank for %s review", flag) |
| 69 | + } |
| 70 | + |
| 71 | + return &api.PullRequestReviewInput{ |
| 72 | + Body: body, |
| 73 | + State: state, |
| 74 | + }, nil |
| 75 | +} |
| 76 | + |
| 77 | +func prReview(cmd *cobra.Command, args []string) error { |
| 78 | + ctx := contextForCommand(cmd) |
| 79 | + baseRepo, err := determineBaseRepo(cmd, ctx) |
| 80 | + if err != nil { |
| 81 | + return fmt.Errorf("could not determine base repo: %w", err) |
| 82 | + } |
| 83 | + |
| 84 | + apiClient, err := apiClientForContext(ctx) |
| 85 | + if err != nil { |
| 86 | + return err |
| 87 | + } |
| 88 | + |
| 89 | + var prNum int |
| 90 | + branchWithOwner := "" |
| 91 | + |
| 92 | + if len(args) == 0 { |
| 93 | + prNum, branchWithOwner, err = prSelectorForCurrentBranch(ctx, baseRepo) |
| 94 | + if err != nil { |
| 95 | + return fmt.Errorf("could not query for pull request for current branch: %w", err) |
| 96 | + } |
| 97 | + } else { |
| 98 | + prArg, repo := prFromURL(args[0]) |
| 99 | + if repo != nil { |
| 100 | + baseRepo = repo |
| 101 | + } else { |
| 102 | + prArg = strings.TrimPrefix(args[0], "#") |
| 103 | + } |
| 104 | + prNum, err = strconv.Atoi(prArg) |
| 105 | + if err != nil { |
| 106 | + return errors.New("could not parse pull request argument") |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + input, err := processReviewOpt(cmd) |
| 111 | + if err != nil { |
| 112 | + return fmt.Errorf("did not understand desired review action: %w", err) |
| 113 | + } |
| 114 | + |
| 115 | + var pr *api.PullRequest |
| 116 | + if prNum > 0 { |
| 117 | + pr, err = api.PullRequestByNumber(apiClient, baseRepo, prNum) |
| 118 | + if err != nil { |
| 119 | + return fmt.Errorf("could not find pull request: %w", err) |
| 120 | + } |
| 121 | + } else { |
| 122 | + pr, err = api.PullRequestForBranch(apiClient, baseRepo, "", branchWithOwner) |
| 123 | + if err != nil { |
| 124 | + return fmt.Errorf("could not find pull request: %w", err) |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + err = api.AddReview(apiClient, pr, input) |
| 129 | + if err != nil { |
| 130 | + return fmt.Errorf("failed to create review: %w", err) |
| 131 | + } |
| 132 | + |
| 133 | + return nil |
| 134 | +} |
0 commit comments