Skip to content

Commit 4e37cb2

Browse files
efarrerejoffe
authored andcommitted
Delete remote branch after closing pull request.
Based on https://github.com/levibostian/spr/tree/delete-closed-branches but with a feature flag, separate unit tests and documentation update.
1 parent 12105b8 commit 4e37cb2

File tree

6 files changed

+84
-1
lines changed

6 files changed

+84
-1
lines changed

config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type UserConfig struct {
5151
CreateDraftPRs bool `default:"false" yaml:"createDraftPRs"`
5252
PreserveTitleAndBody bool `default:"false" yaml:"preserveTitleAndBody"`
5353
NoRebase bool `default:"false" yaml:"noRebase"`
54+
DeleteMergedBranches bool `default:"false" yaml:"deleteMergedBranches"`
5455
}
5556

5657
type InternalState struct {

git/helpers.go

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ func GetLocalTopCommit(cfg *config.Config, gitcmd GitInterface) *Commit {
4242
return &commits[len(commits)-1]
4343
}
4444

45+
func DeleteRemoteBranch(cfg *config.Config, gitcmd GitInterface, branchName string) {
46+
command := fmt.Sprintf("push origin --delete %s", branchName)
47+
err := gitcmd.Git(command, nil)
48+
check(err)
49+
}
50+
4551
// GetLocalCommitStack returns a list of unmerged commits
4652
//
4753
// the list is ordered with the bottom commit in the stack first

git/mockgit/mockgit.go

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ func (m *Mock) ExpectFetch() {
7474
m.expect("git rebase origin/master --autostash")
7575
}
7676

77+
func (m *Mock) ExpectDeleteBranch(branchName string) {
78+
m.expect(fmt.Sprintf("git push origin --delete %s", branchName))
79+
}
80+
7781
func (m *Mock) ExpectLogAndRespond(commits []*git.Commit) {
7882
m.expect("git log --format=medium --no-color origin/master..HEAD").commitRespond(commits)
7983
}

readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ User specific configuration is saved to .spr.yml in the user home directory.
187187
| createDraftPRs | bool | false | new pull requests are created as draft |
188188
| preserveTitleAndBody | bool | false | updating pull requests will not overwrite the pr title and body |
189189
| noRebase | bool | false | when true spr update will not rebase on top of origin |
190+
| deleteMergedBranches | bool | false | delete branches after prs are merged |
190191

191192
Happy Coding!
192193
-------------

spr/spr.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ func (sd *stackediff) MergePullRequests(ctx context.Context, count *uint) {
317317
mergeMethod, err := sd.config.MergeMethod()
318318
check(err)
319319
sd.github.MergePullRequest(ctx, prToMerge, mergeMethod)
320-
sd.profiletimer.Step("MergePullRequests::merge pr")
320+
if sd.config.User.DeleteMergedBranches {
321+
git.DeleteRemoteBranch(sd.config, sd.gitcmd, prToMerge.FromBranch)
322+
}
321323

322324
// Close all the pull requests in the stack below the merged pr
323325
// Before closing add a review comment with the pr that merged the commit.
@@ -328,6 +330,9 @@ func (sd *stackediff) MergePullRequests(ctx context.Context, count *uint) {
328330
prToMerge.Number, sd.config.Repo.GitHubHost, sd.config.Repo.GitHubRepoOwner, sd.config.Repo.GitHubRepoName, prToMerge.Number)
329331
sd.github.CommentPullRequest(ctx, pr, comment)
330332
sd.github.ClosePullRequest(ctx, pr)
333+
if sd.config.User.DeleteMergedBranches {
334+
git.DeleteRemoteBranch(sd.config, sd.gitcmd, pr.FromBranch)
335+
}
331336
}
332337
sd.profiletimer.Step("MergePullRequests::close prs")
333338

spr/spr_test.go

+66
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,72 @@ func TestSPRBasicFlowFourCommits(t *testing.T) {
343343
output.Reset()
344344
}
345345

346+
func TestSPRBasicFlowDeleteBranch(t *testing.T) {
347+
s, gitmock, githubmock, _, output := makeTestObjects(t)
348+
s.config.User.DeleteMergedBranches = true
349+
assert := require.New(t)
350+
ctx := context.Background()
351+
352+
c1 := git.Commit{
353+
CommitID: "00000001",
354+
CommitHash: "c100000000000000000000000000000000000000",
355+
Subject: "test commit 1",
356+
}
357+
c2 := git.Commit{
358+
CommitID: "00000002",
359+
CommitHash: "c200000000000000000000000000000000000000",
360+
Subject: "test commit 2",
361+
}
362+
363+
// 'git spr update' :: UpdatePullRequest :: commits=[c1]
364+
githubmock.ExpectGetInfo()
365+
gitmock.ExpectFetch()
366+
gitmock.ExpectLogAndRespond([]*git.Commit{&c1})
367+
gitmock.ExpectPushCommits([]*git.Commit{&c1})
368+
githubmock.ExpectCreatePullRequest(c1, nil)
369+
githubmock.ExpectGetAssignableUsers()
370+
githubmock.ExpectAddReviewers([]string{mockclient.NobodyUserID})
371+
githubmock.ExpectUpdatePullRequest(c1, nil)
372+
githubmock.ExpectGetInfo()
373+
s.UpdatePullRequests(ctx, []string{mockclient.NobodyLogin}, nil)
374+
fmt.Printf("OUT: %s\n", output.String())
375+
assert.Equal("[vvvv] 1 : test commit 1\n", output.String())
376+
output.Reset()
377+
378+
// 'git spr update' :: UpdatePullRequest :: commits=[c1, c2]
379+
githubmock.ExpectGetInfo()
380+
gitmock.ExpectFetch()
381+
gitmock.ExpectLogAndRespond([]*git.Commit{&c2, &c1})
382+
gitmock.ExpectPushCommits([]*git.Commit{&c2})
383+
githubmock.ExpectCreatePullRequest(c2, &c1)
384+
githubmock.ExpectGetAssignableUsers()
385+
githubmock.ExpectAddReviewers([]string{mockclient.NobodyUserID})
386+
githubmock.ExpectUpdatePullRequest(c1, nil)
387+
githubmock.ExpectUpdatePullRequest(c2, &c1)
388+
githubmock.ExpectGetInfo()
389+
s.UpdatePullRequests(ctx, []string{mockclient.NobodyLogin}, nil)
390+
lines := strings.Split(output.String(), "\n")
391+
fmt.Printf("OUT: %s\n", output.String())
392+
assert.Equal("warning: not updating reviewers for PR #1", lines[0])
393+
assert.Equal("[vvvv] 1 : test commit 2", lines[1])
394+
assert.Equal("[vvvv] 1 : test commit 1", lines[2])
395+
output.Reset()
396+
397+
// 'git spr merge' :: MergePullRequest :: commits=[a1, a2]
398+
githubmock.ExpectGetInfo()
399+
githubmock.ExpectUpdatePullRequest(c2, nil)
400+
githubmock.ExpectMergePullRequest(c2, genclient.PullRequestMergeMethod_REBASE)
401+
gitmock.ExpectDeleteBranch("from_branch") // <--- This is the key expectation of this test.
402+
githubmock.ExpectCommentPullRequest(c1)
403+
githubmock.ExpectClosePullRequest(c1)
404+
gitmock.ExpectDeleteBranch("from_branch") // <--- This is the key expectation of this test.
405+
s.MergePullRequests(ctx, nil)
406+
lines = strings.Split(output.String(), "\n")
407+
assert.Equal("MERGED 1 : test commit 1", lines[0])
408+
fmt.Printf("OUT: %s\n", output.String())
409+
output.Reset()
410+
}
411+
346412
func TestSPRMergeCount(t *testing.T) {
347413
s, gitmock, githubmock, _, output := makeTestObjects(t)
348414
assert := require.New(t)

0 commit comments

Comments
 (0)