Skip to content

Commit 354a7f0

Browse files
authored
Merge pull request #1 from better/PLAT-1242/keep_branches_open_prs
PLAT-1242 | Do not delete branches that may have a second open PR
2 parents 4da2a71 + 8d32441 commit 354a7f0

File tree

3 files changed

+92
-14
lines changed

3 files changed

+92
-14
lines changed

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ clean:
3434
.PHONY: build
3535
build: clean build-darwin build-linux
3636

37-
build-%:
38-
GOOS=$* GOARCH=386 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-$*
37+
build-linux:
38+
GOOS=linux GOARCH=386 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-linux
39+
40+
build-darwin:
41+
GOOS=darwin GOARCH=amd64 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-darwin
3942

4043
.PHONY: docker
4144
docker:

main.go

+65-12
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func (ex *Executor) makeRequest(method string, url string) (res *http.Response,
7575
if err != nil {
7676
return nil, err
7777
}
78+
7879
req.Header.Add("Authorization", "token "+ex.token)
7980
res, _ = ex.client.Do(req)
8081
if res.StatusCode >= 400 {
@@ -92,7 +93,7 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) (
9293
res, err := ex.makeRequest("GET", "repos/"+user+"/"+repo+"/pulls?state=closed&sort=updated&direction=desc&per_page=100&page="+strconv.Itoa(page))
9394

9495
if err != nil {
95-
return pullRequests, errors.New("failed to get pull requests (" + err.Error() + ")")
96+
return pullRequests, errors.New("failed to get closed pull requests (" + err.Error() + ")")
9697
}
9798

9899
d := json.NewDecoder(res.Body)
@@ -102,7 +103,7 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) (
102103
err = d.Decode(&prs.PullRequests)
103104

104105
if err != nil {
105-
return pullRequests, errors.New("failed to parse pull requests (" + err.Error() + ")")
106+
return pullRequests, errors.New("failed to parse closed pull requests (" + err.Error() + ")")
106107
}
107108

108109
for _, pr := range prs.PullRequests {
@@ -122,6 +123,36 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) (
122123
return pullRequests, nil
123124
}
124125

126+
func (ex *Executor) listOpenPullRequests(user string, repo string) ([]pullRequest, error) {
127+
pullRequests := make([]pullRequest, 0, 1)
128+
129+
for page, keepGoing := 1, true; keepGoing; page++ {
130+
res, err := ex.makeRequest("GET", "repos/"+user+"/"+repo+"/pulls?state=open&sort=updated&direction=desc&per_page=100&page="+strconv.Itoa(page))
131+
132+
if err != nil {
133+
return pullRequests, errors.New("failed to get open pull requests (" + err.Error() + ")")
134+
}
135+
136+
d := json.NewDecoder(res.Body)
137+
var prs struct {
138+
PullRequests []pullRequest
139+
}
140+
err = d.Decode(&prs.PullRequests)
141+
142+
if err != nil {
143+
return pullRequests, errors.New("failed to parse open pull requests (" + err.Error() + ")")
144+
}
145+
146+
pullRequests = append(pullRequests, prs.PullRequests...)
147+
148+
if len(prs.PullRequests) == 0 || len(prs.PullRequests) < 100 {
149+
break
150+
}
151+
}
152+
153+
return pullRequests, nil
154+
}
155+
125156
func (ex *Executor) listUnprotectedBranches(user string, repo string) ([]branch, error) {
126157
branches := make([]branch, 0, 1)
127158

@@ -174,18 +205,33 @@ func (ex *Executor) deleteBranches(user string, repo string, branches []string)
174205
return deletedBranches, nil
175206
}
176207

177-
func getStaleBranches(branches []branch, pullRequests []pullRequest) []string {
178-
branchesByName := make(map[string]branch)
179-
staleBranches := make([]string, 0, 1)
208+
func getStaleBranches(closedBranches []branch, closedPullRequests []pullRequest, openPullRequests []pullRequest) []string {
209+
branchShaMap := make(map[string]string) // Map[branch_name]branch_SHA
210+
staleBranchMap := make(map[string]bool) // Map[branch_name]is_stale
211+
212+
for _, b := range closedBranches {
213+
branchShaMap[b.Name] = b.Commit.SHA
214+
}
215+
216+
for _, pr := range closedPullRequests {
217+
staleBranchSHA, branchExists := branchShaMap[pr.Head.Ref]
218+
if branchExists && staleBranchSHA == pr.Head.SHA {
219+
staleBranchMap[pr.Head.Ref] = true
220+
}
221+
}
180222

181-
for _, b := range branches {
182-
branchesByName[b.Name] = b
223+
// If we've marked this branch as stale, but there is another open PR tied to the branch, unmark as stale
224+
for _, pr := range openPullRequests {
225+
_, branchExists := staleBranchMap[pr.Head.Ref]
226+
if branchExists {
227+
staleBranchMap[pr.Head.Ref] = false
228+
}
183229
}
184230

185-
for _, pr := range pullRequests {
186-
staleBranch, branchExists := branchesByName[pr.Head.Ref]
187-
if branchExists && staleBranch.Commit.SHA == pr.Head.SHA {
188-
staleBranches = append(staleBranches, pr.Head.Ref)
231+
staleBranches := make([]string, 0, 1)
232+
for branch, isStale := range staleBranchMap {
233+
if isStale {
234+
staleBranches = append(staleBranches, branch)
189235
}
190236
}
191237

@@ -269,11 +315,18 @@ func Run(user string, repo string, days int, ex Executor) error {
269315
if err != nil {
270316
return err
271317
}
318+
319+
openPullRequests, err := ex.listOpenPullRequests(user, repo)
320+
if err != nil {
321+
return err
322+
}
323+
272324
unprotectedBranches, err := ex.listUnprotectedBranches(user, repo)
273325
if err != nil {
274326
return err
275327
}
276-
staleBranches := getStaleBranches(unprotectedBranches, closedPullRequests)
328+
329+
staleBranches := getStaleBranches(unprotectedBranches, closedPullRequests, openPullRequests)
277330
db, err := ex.deleteBranches(user, repo, staleBranches)
278331
if err != nil {
279332
return err

main_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,28 @@ func TestRun(t *testing.T) {
208208
"ref": "stalebranch",
209209
"sha": "1761e021e70d29619ca270046b23bd243f652b98"
210210
}
211+
},
212+
{
213+
"number": 2,
214+
"updated_at": "` + now.Format(time.RFC3339) + `",
215+
"head": {
216+
"ref": "notstalebranch",
217+
"sha": "867530990210abcdefg867530990210abcdefg"
218+
}
219+
}
220+
]`,
221+
},
222+
mockHTTPResponse{
223+
method: "GET",
224+
URL: "/repos/user/repo/pulls?state=open&sort=updated&direction=desc&per_page=100&page=1",
225+
body: `[
226+
{
227+
"number": 2,
228+
"updated_at": "` + now.Format(time.RFC3339) + `",
229+
"head": {
230+
"ref": "notstalebranch",
231+
"sha": "867530990210abcdefg867530990210abcdefg"
232+
}
211233
}
212234
]`,
213235
},

0 commit comments

Comments
 (0)