diff --git a/pkg/cmd/pr/merge/http.go b/pkg/cmd/pr/merge/http.go index 554d1bd39..6b705e6ef 100644 --- a/pkg/cmd/pr/merge/http.go +++ b/pkg/cmd/pr/merge/http.go @@ -36,6 +36,7 @@ type mergePayload struct { commitBody string setCommitBody bool expectedHeadOid string + authorEmail string } // TODO: drop after githubv4 gets updated @@ -60,6 +61,10 @@ func mergePullRequest(client *http.Client, payload mergePayload) error { input.MergeMethod = &m } + if payload.authorEmail != "" { + authorEmail := githubv4.String(payload.authorEmail) + input.AuthorEmail = &authorEmail + } if payload.commitSubject != "" { commitHeadline := githubv4.String(payload.commitSubject) input.CommitHeadline = &commitHeadline diff --git a/pkg/cmd/pr/merge/merge.go b/pkg/cmd/pr/merge/merge.go index 635945572..2972c09f9 100644 --- a/pkg/cmd/pr/merge/merge.go +++ b/pkg/cmd/pr/merge/merge.go @@ -39,6 +39,8 @@ type MergeOptions struct { AutoMergeEnable bool AutoMergeDisable bool + AuthorEmail string + Body string BodySet bool Subject string @@ -177,6 +179,7 @@ func NewCmdMerge(f *cmdutil.Factory, runF func(*MergeOptions) error) *cobra.Comm cmd.Flags().BoolVar(&opts.AutoMergeEnable, "auto", false, "Automatically merge only after necessary requirements are met") cmd.Flags().BoolVar(&opts.AutoMergeDisable, "disable-auto", false, "Disable auto-merge for this pull request") cmd.Flags().StringVar(&opts.MatchHeadCommit, "match-head-commit", "", "Commit `SHA` that the pull request head must match to allow merge") + cmd.Flags().StringVarP(&opts.AuthorEmail, "author-email", "A", "", "Email `text` for merge commit author") return cmd } @@ -280,6 +283,7 @@ func (m *mergeContext) merge() error { commitBody: m.opts.Body, setCommitBody: m.opts.BodySet, expectedHeadOid: m.opts.MatchHeadCommit, + authorEmail: m.opts.AuthorEmail, } if m.shouldAddToMergeQueue() { diff --git a/pkg/cmd/pr/merge/merge_test.go b/pkg/cmd/pr/merge/merge_test.go index 9428fd3e6..d1bb21d8c 100644 --- a/pkg/cmd/pr/merge/merge_test.go +++ b/pkg/cmd/pr/merge/merge_test.go @@ -55,6 +55,7 @@ func Test_NewCmdMerge(t *testing.T) { MergeStrategyEmpty: true, Body: "", BodySet: false, + AuthorEmail: "", }, }, { @@ -70,6 +71,7 @@ func Test_NewCmdMerge(t *testing.T) { MergeStrategyEmpty: true, Body: "", BodySet: false, + AuthorEmail: "", }, }, { @@ -85,6 +87,7 @@ func Test_NewCmdMerge(t *testing.T) { MergeStrategyEmpty: true, Body: "a body from file", BodySet: true, + AuthorEmail: "", }, }, { @@ -101,6 +104,7 @@ func Test_NewCmdMerge(t *testing.T) { MergeStrategyEmpty: true, Body: "this is on standard input", BodySet: true, + AuthorEmail: "", }, }, { @@ -116,6 +120,7 @@ func Test_NewCmdMerge(t *testing.T) { MergeStrategyEmpty: true, Body: "cool", BodySet: true, + AuthorEmail: "", }, }, { @@ -132,6 +137,23 @@ func Test_NewCmdMerge(t *testing.T) { Body: "", BodySet: false, MatchHeadCommit: "555", + AuthorEmail: "", + }, + }, + { + name: "author email", + args: "123 --author-email octocat@github.com", + isTTY: true, + want: MergeOptions{ + SelectorArg: "123", + DeleteBranch: false, + IsDeleteBranchIndicated: false, + CanDeleteLocalBranch: true, + MergeMethod: PullRequestMergeMethodMerge, + MergeStrategyEmpty: true, + Body: "", + BodySet: false, + AuthorEmail: "octocat@github.com", }, }, { @@ -205,6 +227,7 @@ func Test_NewCmdMerge(t *testing.T) { assert.Equal(t, tt.want.Body, opts.Body) assert.Equal(t, tt.want.BodySet, opts.BodySet) assert.Equal(t, tt.want.MatchHeadCommit, opts.MatchHeadCommit) + assert.Equal(t, tt.want.AuthorEmail, opts.AuthorEmail) }) } } @@ -537,6 +560,48 @@ func TestPrMerge_withMatchCommitHeadFlag(t *testing.T) { } } +func TestPrMerge_withAuthorFlag(t *testing.T) { + http := initFakeHTTP() + defer http.Verify(t) + + shared.RunCommandFinder( + "1", + &api.PullRequest{ + ID: "THE-ID", + Number: 1, + State: "OPEN", + Title: "The title of the PR", + MergeStateStatus: "CLEAN", + }, + baseRepo("OWNER", "REPO", "main"), + ) + + http.Register( + httpmock.GraphQL(`mutation PullRequestMerge\b`), + httpmock.GraphQLMutation(`{}`, func(input map[string]interface{}) { + assert.Equal(t, "THE-ID", input["pullRequestId"].(string)) + assert.Equal(t, "MERGE", input["mergeMethod"].(string)) + assert.Equal(t, "octocat@github.com", input["authorEmail"].(string)) + assert.NotContains(t, input, "commitHeadline") + }), + ) + + cs, cmdTeardown := run.Stub() + defer cmdTeardown(t) + cs.Register(`git rev-parse --verify refs/heads/`, 0, "") + + output, err := runCommand(http, "main", true, "pr merge 1 --merge --author-email octocat@github.com") + if err != nil { + t.Fatalf("error running command `pr merge`: %v", err) + } + + r := regexp.MustCompile(`Merged pull request #1 \(The title of the PR\)`) + + if !r.MatchString(output.Stderr()) { + t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) + } +} + func TestPrMerge_deleteBranch(t *testing.T) { http := initFakeHTTP() defer http.Verify(t)