-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
111 lines (89 loc) · 3.02 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import (
"time"
"github.com/hako/durafmt"
"vincent.click/pkg/octostats/commons"
"vincent.click/pkg/octostats/github"
)
const (
repositoryPattern = "[A-Za-z0-9-_]+/[A-Za-z0-9-_]+"
)
func main() {
auth := getAuth()
repo := getRepo()
mergedAfter := getStartTime()
log.Info("inspecting %s", repo)
client := github.NewOctoClient(auth)
if user, err := client.GetAuthenticatedUser(); err != nil {
log.Error("failed to get authenticated user: %s", err)
} else {
log.Info("authenticated as %s", user)
}
page := 1
count := 0 // number of merged pull requests
countByLabel := make(map[github.Label]int) // number of prs by label
reviewsCount := 0 // total number of pr reviews
timeToMergeInNanoSeconds := int64(0) // total time to merge in nanoseconds
query := buildQuery(repo, auth, mergedAfter)
for {
results := runQuery(client, repo, query, page)
if len(results.Items) < 1 {
break
}
page++
for _, item := range results.Items {
stats, err := getStats(client, repo, item)
if err != nil {
log.Warn(err.Error())
continue
}
stats.log()
// aggregate stats
timeToMergeInNanoSeconds += stats.timeToMerge.Nanoseconds()
reviewsCount += stats.reviews
for _, label := range stats.labels {
countByLabel[label]++
}
count++
}
}
avgTimeToMerge := time.Duration(timeToMergeInNanoSeconds / int64(count))
avgReviews := reviewsCount / count
summarize(repo, count, avgTimeToMerge, avgReviews, countByLabel)
}
// buildQuery builds a query for pull requests by repo, author, and merge time
func buildQuery(repo string, auth github.Credentials, mergedAfter time.Time) *github.QueryBuilder {
q := github.Query("").WithRepo(repo).WithAuthor(auth.User).IsMerged()
if !mergedAfter.IsZero() {
log.Info("looking at pull requests merged after %s", mergedAfter.Format(commons.DateLayout))
q.IsMergedAfter(mergedAfter)
} else {
log.Info("looking at pull requests by %s in %s", auth.User, repo)
}
return q
}
// runQuery searches for pull requests using a prepared query
func runQuery(client github.Client, repo string, query *github.QueryBuilder, page int) github.SearchResponse {
log.Debug("getting page %d of pull requests", page)
results, err := client.SearchPulls(repo, page, query)
if err != nil {
log.Fatal("failed to get pull requests: %s", err)
}
if results.IsIncomplete {
log.Warn("search results are incomplete due to timeout")
}
return results
}
// summarize prints a summary of the collected stats
func summarize(repo string, count int, avgTimeToMerge time.Duration, avgReviews int, countByLabel map[github.Label]int) {
log.Info("found %d merged pull requests for %s", count, repo)
if count < 1 {
return
}
avgTimeToMergeFriendly := durafmt.Parse(avgTimeToMerge)
log.Info("average time to merge: %0.4f hours (%s)", avgTimeToMerge.Hours(), avgTimeToMergeFriendly)
log.Info("average reviewers count: %d", avgReviews)
for label, count := range countByLabel {
log.Info("with label '%s': %d", label, count)
}
}