Created
May 10, 2016 16:50
-
-
Save donatj/29876b0dc19dd11ebc2f09a632fe0b1b to your computer and use it in GitHub Desktop.
Find issues between two release branches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"log" | |
"regexp" | |
"sort" | |
"strconv" | |
"strings" | |
"github.com/google/go-github/github" | |
"github.com/mcuadros/go-version" | |
) | |
type branchSort []github.Branch | |
func (a branchSort) Len() int { return len(a) } | |
func (a branchSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | |
func (a branchSort) Less(i, j int) bool { | |
left := (*a[i].Name)[8:] | |
right := (*a[j].Name)[8:] | |
return version.Compare(left, right, "<") | |
} | |
var ( | |
username = flag.String("user", "", "Username to authenticate with") | |
password = flag.String("pass", "", "password or token to authenticate with") | |
owner = flag.String("owner", "capdig", "repo owner") | |
repo = flag.String("repo", "myon", "repo") | |
) | |
type issuePrAssoc struct { | |
Issue *github.Issue | |
PullRequests map[int]*github.PullRequest | |
} | |
type issueMap map[int]issuePrAssoc | |
func init() { | |
flag.Parse() | |
} | |
func main() { | |
tp := github.BasicAuthTransport{ | |
Username: *username, | |
Password: *password, | |
} | |
client := github.NewClient(tp.Client()) | |
bq, err := getReleaseBranches(client, *owner, *repo) | |
if err != nil { | |
log.Fatal(err) | |
} | |
start := bq[len(bq)-2] | |
end := bq[len(bq)-1] | |
mergeCommits, err := getMergeCommitsBetween( | |
client, *owner, *repo, | |
end.Commit, | |
start.Commit) | |
if err != nil { | |
log.Fatal(err) | |
} | |
issues, err := getIssueMap( | |
client, *owner, *repo, | |
mergeCommits) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// output | |
fmt.Printf("%s…%s\n", *start.Name, *end.Name) | |
if v, ok := issues[-1]; ok { | |
fmt.Printf("No Issue:\n") | |
for _, pr := range v.PullRequests { | |
fmt.Printf("\t#%d: %s\n", *pr.Number, *pr.Title) | |
} | |
} | |
for issueNumber, prNumbers := range issues { | |
if issueNumber == -1 { | |
continue | |
} else { | |
fmt.Printf("Issue: #%d: %s\n", issueNumber, *prNumbers.Issue.Title) | |
} | |
for _, pr := range prNumbers.PullRequests { | |
fmt.Printf("\t#%d: %s\n", *pr.Number, *pr.Title) | |
} | |
} | |
} | |
func getIssueMap(client *github.Client, owner, repo string, commits []github.RepositoryCommit) (issueMap, error) { | |
issues := make(issueMap) | |
for _, mc := range commits { | |
m := *mc.Commit.Message | |
r := regexp.MustCompile(`Merge pull request #(\d+)`) | |
matches := r.FindAllStringSubmatch(m, -1) | |
prNumber, err := strconv.Atoi(matches[0][1]) | |
if err != nil { | |
return nil, err | |
} | |
pullreq, _, err := client.PullRequests.Get(owner, repo, prNumber) | |
if err != nil { | |
return nil, err | |
} | |
r2 := regexp.MustCompile(`connects? \\?#(\d+)`) | |
matches = r2.FindAllStringSubmatch(*pullreq.Body, -1) | |
for _, match := range matches { | |
issueNum, err := strconv.Atoi(match[1]) | |
if err != nil { | |
return nil, err | |
} | |
if _, ok := issues[issueNum]; !ok { | |
issue, _, err := client.Issues.Get(owner, repo, issueNum) | |
if err != nil { | |
return nil, err | |
} | |
issues[issueNum] = issuePrAssoc{ | |
Issue: issue, | |
PullRequests: make(map[int]*github.PullRequest), | |
} | |
} | |
issues[issueNum].PullRequests[prNumber] = pullreq | |
} | |
if len(matches) == 0 { | |
if _, ok := issues[-1]; !ok { | |
issues[-1] = issuePrAssoc{ | |
PullRequests: make(map[int]*github.PullRequest), | |
} | |
} | |
issues[-1].PullRequests[prNumber] = pullreq | |
} | |
} | |
return issues, nil | |
} | |
func getMergeCommitsBetween(client *github.Client, owner, repo string, startc, endc *github.Commit) ([]github.RepositoryCommit, error) { | |
end := *endc.SHA | |
start := *startc.SHA | |
mergeCommits := []github.RepositoryCommit{} | |
page := 1 | |
outer: | |
for { | |
commits, resp, err := client.Repositories.ListCommits(owner, repo, &github.CommitsListOptions{ | |
SHA: start, | |
ListOptions: github.ListOptions{ | |
PerPage: 100, | |
Page: page, | |
}, | |
}) | |
if err != nil { | |
return nil, err | |
} | |
for _, cc := range commits { | |
if cc.Commit != nil && cc.Commit.Message != nil && strings.Contains(*cc.Commit.Message, "Merge pull request #") { | |
mergeCommits = append(mergeCommits, cc) | |
} | |
if *cc.SHA == end { | |
break outer | |
} | |
} | |
if resp.NextPage == 0 { | |
break | |
} | |
page = resp.NextPage | |
} | |
return mergeCommits, nil | |
} | |
func getReleaseBranches(client *github.Client, owner, repo string) (branchSort, error) { | |
brs := []github.Branch{} | |
page := 1 | |
for { | |
branch, resp, err := client.Repositories.ListBranches(owner, repo, &github.ListOptions{PerPage: 100, Page: page}) | |
if err != nil { | |
return nil, err | |
} | |
brs = append(brs, branch...) | |
if resp.NextPage == 0 { | |
break | |
} | |
page = resp.NextPage | |
} | |
bq := branchSort{} | |
for _, br := range brs { | |
if strings.HasPrefix(*br.Name, "release/") { | |
bq = append(bq, br) | |
} | |
} | |
sort.Sort(bq) | |
return bq, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment