github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/pr/merge/http.go (about) 1 package merge 2 3 import ( 4 "net/http" 5 "strings" 6 7 "github.com/ungtb10d/cli/v2/api" 8 "github.com/ungtb10d/cli/v2/internal/ghrepo" 9 "github.com/shurcooL/githubv4" 10 ) 11 12 type PullRequestMergeMethod int 13 14 const ( 15 PullRequestMergeMethodMerge PullRequestMergeMethod = iota 16 PullRequestMergeMethodRebase 17 PullRequestMergeMethodSquash 18 ) 19 20 const ( 21 MergeStateStatusBehind = "BEHIND" 22 MergeStateStatusBlocked = "BLOCKED" 23 MergeStateStatusClean = "CLEAN" 24 MergeStateStatusDirty = "DIRTY" 25 MergeStateStatusHasHooks = "HAS_HOOKS" 26 MergeStateStatusMerged = "MERGED" 27 MergeStateStatusUnstable = "UNSTABLE" 28 ) 29 30 type mergePayload struct { 31 repo ghrepo.Interface 32 pullRequestID string 33 method PullRequestMergeMethod 34 auto bool 35 commitSubject string 36 commitBody string 37 setCommitBody bool 38 expectedHeadOid string 39 authorEmail string 40 } 41 42 // TODO: drop after githubv4 gets updated 43 type EnablePullRequestAutoMergeInput struct { 44 githubv4.MergePullRequestInput 45 } 46 47 func mergePullRequest(client *http.Client, payload mergePayload) error { 48 input := githubv4.MergePullRequestInput{ 49 PullRequestID: githubv4.ID(payload.pullRequestID), 50 } 51 52 switch payload.method { 53 case PullRequestMergeMethodMerge: 54 m := githubv4.PullRequestMergeMethodMerge 55 input.MergeMethod = &m 56 case PullRequestMergeMethodRebase: 57 m := githubv4.PullRequestMergeMethodRebase 58 input.MergeMethod = &m 59 case PullRequestMergeMethodSquash: 60 m := githubv4.PullRequestMergeMethodSquash 61 input.MergeMethod = &m 62 } 63 64 if payload.authorEmail != "" { 65 authorEmail := githubv4.String(payload.authorEmail) 66 input.AuthorEmail = &authorEmail 67 } 68 if payload.commitSubject != "" { 69 commitHeadline := githubv4.String(payload.commitSubject) 70 input.CommitHeadline = &commitHeadline 71 } 72 if payload.setCommitBody { 73 commitBody := githubv4.String(payload.commitBody) 74 input.CommitBody = &commitBody 75 } 76 77 if payload.expectedHeadOid != "" { 78 expectedHeadOid := githubv4.GitObjectID(payload.expectedHeadOid) 79 input.ExpectedHeadOid = &expectedHeadOid 80 } 81 82 variables := map[string]interface{}{ 83 "input": input, 84 } 85 86 gql := api.NewClientFromHTTP(client) 87 88 if payload.auto { 89 var mutation struct { 90 EnablePullRequestAutoMerge struct { 91 ClientMutationId string 92 } `graphql:"enablePullRequestAutoMerge(input: $input)"` 93 } 94 variables["input"] = EnablePullRequestAutoMergeInput{input} 95 return gql.Mutate(payload.repo.RepoHost(), "PullRequestAutoMerge", &mutation, variables) 96 } 97 98 var mutation struct { 99 MergePullRequest struct { 100 ClientMutationId string 101 } `graphql:"mergePullRequest(input: $input)"` 102 } 103 return gql.Mutate(payload.repo.RepoHost(), "PullRequestMerge", &mutation, variables) 104 } 105 106 func disableAutoMerge(client *http.Client, repo ghrepo.Interface, prID string) error { 107 var mutation struct { 108 DisablePullRequestAutoMerge struct { 109 ClientMutationId string 110 } `graphql:"disablePullRequestAutoMerge(input: {pullRequestId: $prID})"` 111 } 112 113 variables := map[string]interface{}{ 114 "prID": githubv4.ID(prID), 115 } 116 117 gql := api.NewClientFromHTTP(client) 118 return gql.Mutate(repo.RepoHost(), "PullRequestAutoMergeDisable", &mutation, variables) 119 } 120 121 func getMergeText(client *http.Client, repo ghrepo.Interface, prID string, mergeMethod PullRequestMergeMethod) (string, string, error) { 122 var method githubv4.PullRequestMergeMethod 123 switch mergeMethod { 124 case PullRequestMergeMethodMerge: 125 method = githubv4.PullRequestMergeMethodMerge 126 case PullRequestMergeMethodRebase: 127 method = githubv4.PullRequestMergeMethodRebase 128 case PullRequestMergeMethodSquash: 129 method = githubv4.PullRequestMergeMethodSquash 130 } 131 132 var query struct { 133 Node struct { 134 PullRequest struct { 135 ViewerMergeHeadlineText string `graphql:"viewerMergeHeadlineText(mergeType: $method)"` 136 ViewerMergeBodyText string `graphql:"viewerMergeBodyText(mergeType: $method)"` 137 } `graphql:"...on PullRequest"` 138 } `graphql:"node(id: $prID)"` 139 } 140 141 variables := map[string]interface{}{ 142 "prID": githubv4.ID(prID), 143 "method": method, 144 } 145 146 gql := api.NewClientFromHTTP(client) 147 err := gql.Query(repo.RepoHost(), "PullRequestMergeText", &query, variables) 148 if err != nil { 149 // Tolerate this API missing in older GitHub Enterprise 150 if strings.Contains(err.Error(), "Field 'viewerMergeHeadlineText' doesn't exist") || 151 strings.Contains(err.Error(), "Field 'viewerMergeBodyText' doesn't exist") { 152 return "", "", nil 153 } 154 return "", "", err 155 } 156 157 return query.Node.PullRequest.ViewerMergeHeadlineText, query.Node.PullRequest.ViewerMergeBodyText, nil 158 }