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  }