From 5ea65bccdace5da173ee621d6ac791b5c9fc406e Mon Sep 17 00:00:00 2001 From: Tim Duffy Date: Mon, 5 Oct 2020 11:17:43 -0400 Subject: [PATCH 1/3] PLAT-1242 | Do not delete branches that may have a second open PR --- main.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index f07c896..7bb7a79 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ func (ex *Executor) makeRequest(method string, url string) (res *http.Response, if err != nil { return nil, err } + req.Header.Add("Accept", "application/vnd.github.v3+json") req.Header.Add("Authorization", "token "+ex.token) res, _ = ex.client.Do(req) if res.StatusCode >= 400 { @@ -122,6 +123,36 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) ( return pullRequests, nil } +func (ex *Executor) listOpenPullRequests(user string, repo string) ([]pullRequest, error) { + pullRequests := make([]pullRequest, 0, 1) + + for page, keepGoing := 1, true; keepGoing; page++ { + res, err := ex.makeRequest("GET", "repos/"+user+"/"+repo+"/pulls?state=open&sort=updated&direction=desc&per_page=100&page="+strconv.Itoa(page)) + + if err != nil { + return pullRequests, errors.New("failed to get pull requests (" + err.Error() + ")") + } + + d := json.NewDecoder(res.Body) + var prs struct { + PullRequests []pullRequest + } + err = d.Decode(&prs.PullRequests) + + if err != nil { + return pullRequests, errors.New("failed to parse pull requests (" + err.Error() + ")") + } + + pullRequests = append(pullRequests, prs.PullRequests...) + + if len(prs.PullRequests) == 0 || len(prs.PullRequests) < 100 { + break + } + } + + return pullRequests, nil +} + func (ex *Executor) listUnprotectedBranches(user string, repo string) ([]branch, error) { branches := make([]branch, 0, 1) @@ -174,18 +205,33 @@ func (ex *Executor) deleteBranches(user string, repo string, branches []string) return deletedBranches, nil } -func getStaleBranches(branches []branch, pullRequests []pullRequest) []string { - branchesByName := make(map[string]branch) - staleBranches := make([]string, 0, 1) +func getStaleBranches(closedBranches []branch, closedPullRequests []pullRequest, openPullRequests []pullRequest) []string { + branchShaMap := make(map[string]string) // Map[branch_name]branch_SHA + staleBranchMap := make(map[string]bool) // Map[branch_name]is_stale + + for _, b := range closedBranches { + branchShaMap[b.Name] = b.Commit.SHA + } + + for _, pr := range closedPullRequests { + staleBranchSHA, branchExists := branchShaMap[pr.Head.Ref] + if branchExists && staleBranchSHA == pr.Head.SHA { + staleBranchMap[pr.Head.Ref] = true + } + } - for _, b := range branches { - branchesByName[b.Name] = b + // If we've marked this branch as stale, but there is another open PR tied to the branch, unmark as stale + for _, pr := range openPullRequests { + _, branchExists := staleBranchMap[pr.Head.Ref] + if branchExists { + staleBranchMap[pr.Head.Ref] = false + } } - for _, pr := range pullRequests { - staleBranch, branchExists := branchesByName[pr.Head.Ref] - if branchExists && staleBranch.Commit.SHA == pr.Head.SHA { - staleBranches = append(staleBranches, pr.Head.Ref) + staleBranches := make([]string, 0, 1) + for branch, isStale := range staleBranchMap { + if isStale { + staleBranches = append(staleBranches, branch) } } @@ -269,11 +315,18 @@ func Run(user string, repo string, days int, ex Executor) error { if err != nil { return err } + + openPullRequests, err := ex.listOpenPullRequests(user, repo) + if err != nil { + return err + } + unprotectedBranches, err := ex.listUnprotectedBranches(user, repo) if err != nil { return err } - staleBranches := getStaleBranches(unprotectedBranches, closedPullRequests) + + staleBranches := getStaleBranches(unprotectedBranches, closedPullRequests, openPullRequests) db, err := ex.deleteBranches(user, repo, staleBranches) if err != nil { return err From af01bd4a1bf96d36b8a09ea23e4bdccacefd0773 Mon Sep 17 00:00:00 2001 From: Tim Duffy Date: Mon, 5 Oct 2020 11:34:26 -0400 Subject: [PATCH 2/3] Add mock API call for open PRs --- main_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/main_test.go b/main_test.go index d0cdcfc..56632e0 100644 --- a/main_test.go +++ b/main_test.go @@ -208,6 +208,28 @@ func TestRun(t *testing.T) { "ref": "stalebranch", "sha": "1761e021e70d29619ca270046b23bd243f652b98" } + }, + { + "number": 2, + "updated_at": "` + now.Format(time.RFC3339) + `", + "head": { + "ref": "notstalebranch", + "sha": "867530990210abcdefg867530990210abcdefg" + } + } + ]`, + }, + mockHTTPResponse{ + method: "GET", + URL: "/repos/user/repo/pulls?state=open&sort=updated&direction=desc&per_page=100&page=1", + body: `[ + { + "number": 2, + "updated_at": "` + now.Format(time.RFC3339) + `", + "head": { + "ref": "notstalebranch", + "sha": "867530990210abcdefg867530990210abcdefg" + } } ]`, }, From 8d3244187b7e522aabfc1cf60a9549fbe916f73b Mon Sep 17 00:00:00 2001 From: Tim Duffy Date: Mon, 5 Oct 2020 11:51:39 -0400 Subject: [PATCH 3/3] Remove accept header; change goarch for darwin --- Makefile | 7 +++++-- main.go | 10 +++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 078ffc2..c558f34 100644 --- a/Makefile +++ b/Makefile @@ -34,8 +34,11 @@ clean: .PHONY: build build: clean build-darwin build-linux -build-%: - GOOS=$* GOARCH=386 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-$* +build-linux: + GOOS=linux GOARCH=386 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-linux + +build-darwin: + GOOS=darwin GOARCH=amd64 go build -ldflags '${LDFLAGS}' -o ${PREFIX}${NAME}-darwin .PHONY: docker docker: diff --git a/main.go b/main.go index 7bb7a79..1293934 100644 --- a/main.go +++ b/main.go @@ -75,7 +75,7 @@ func (ex *Executor) makeRequest(method string, url string) (res *http.Response, if err != nil { return nil, err } - req.Header.Add("Accept", "application/vnd.github.v3+json") + req.Header.Add("Authorization", "token "+ex.token) res, _ = ex.client.Do(req) if res.StatusCode >= 400 { @@ -93,7 +93,7 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) ( res, err := ex.makeRequest("GET", "repos/"+user+"/"+repo+"/pulls?state=closed&sort=updated&direction=desc&per_page=100&page="+strconv.Itoa(page)) if err != nil { - return pullRequests, errors.New("failed to get pull requests (" + err.Error() + ")") + return pullRequests, errors.New("failed to get closed pull requests (" + err.Error() + ")") } d := json.NewDecoder(res.Body) @@ -103,7 +103,7 @@ func (ex *Executor) listClosedPullRequests(user string, repo string, days int) ( err = d.Decode(&prs.PullRequests) if err != nil { - return pullRequests, errors.New("failed to parse pull requests (" + err.Error() + ")") + return pullRequests, errors.New("failed to parse closed pull requests (" + err.Error() + ")") } for _, pr := range prs.PullRequests { @@ -130,7 +130,7 @@ func (ex *Executor) listOpenPullRequests(user string, repo string) ([]pullReques res, err := ex.makeRequest("GET", "repos/"+user+"/"+repo+"/pulls?state=open&sort=updated&direction=desc&per_page=100&page="+strconv.Itoa(page)) if err != nil { - return pullRequests, errors.New("failed to get pull requests (" + err.Error() + ")") + return pullRequests, errors.New("failed to get open pull requests (" + err.Error() + ")") } d := json.NewDecoder(res.Body) @@ -140,7 +140,7 @@ func (ex *Executor) listOpenPullRequests(user string, repo string) ([]pullReques err = d.Decode(&prs.PullRequests) if err != nil { - return pullRequests, errors.New("failed to parse pull requests (" + err.Error() + ")") + return pullRequests, errors.New("failed to parse open pull requests (" + err.Error() + ")") } pullRequests = append(pullRequests, prs.PullRequests...)