forked from paulfantom/periodic-labeler
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
121 lines (106 loc) · 2.74 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
112
113
114
115
116
117
118
119
120
121
package main
import (
"context"
"os"
"path"
"strings"
"github.com/golang/glog"
"golang.org/x/oauth2"
"github.com/google/go-github/v28/github"
"gopkg.in/yaml.v2"
)
func contains(slice []string, item string) bool {
set := make(map[string]struct{}, len(slice))
for _, s := range slice {
set[s] = struct{}{}
}
_, ok := set[item]
return ok
}
func getCurrentLabels(pr *github.PullRequest) []string {
var labelSet []string
for _, l := range pr.Labels {
labelSet = append(labelSet, *l.Name)
}
return labelSet
}
func containsLabels(expected []string, current []string) bool {
for _, e := range expected {
if !contains(current, e) {
return false
}
}
return true
}
// Get files and labels matchers, output labels
func matchFiles(labelsMatch map[string][]string, files []*github.CommitFile) []string {
var labelSet []string
set := make(map[string]bool)
for _, file := range files {
for label, matchers := range labelsMatch {
for _, pattern := range matchers {
match, _ := path.Match(pattern, *file.Filename)
if match && !set[label] {
set[label] = true
labelSet = append(labelSet, label)
break
}
}
}
}
return labelSet
}
func main() {
var owner, repo, token, configpath string
repoSlug, _ := os.LookupEnv("GITHUB_REPOSITORY")
token, _ = os.LookupEnv("GITHUB_TOKEN")
configpath, exists := os.LookupEnv("LABEL_MAPPINGS_FILE")
if !exists {
configpath = ".github/labeler.yml"
}
s := strings.Split(repoSlug, "/")
owner = s[0]
repo = s[1]
ctx := context.Background()
ts := oauth2.StaticTokenSource(
//TODO: access token should be passed as CLI parameter
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
content, _, _, err := client.Repositories.GetContents(context.Background(), owner, repo, configpath, nil)
if err != nil {
glog.Fatal(err)
}
yamlFile, err := content.GetContent()
if err != nil {
glog.Fatal(err)
}
var labelMatchers map[string][]string
err = yaml.Unmarshal([]byte(yamlFile), &labelMatchers)
if err != nil {
glog.Fatal(err)
}
opt := &github.PullRequestListOptions{State: "open", Sort: "updated"}
// get all pages of results
for {
pulls, resp, err := client.PullRequests.List(context.Background(), owner, repo, opt)
if err != nil {
glog.Fatal(err)
}
for _, pull := range pulls {
files, _, err := client.PullRequests.ListFiles(context.Background(), owner, repo, *pull.Number, nil)
if err != nil {
glog.Error(err)
}
expectedLabels := matchFiles(labelMatchers, files)
if !containsLabels(expectedLabels, getCurrentLabels(pull)) {
client.Issues.AddLabelsToIssue(context.Background(), owner, repo, *pull.Number, expectedLabels)
}
}
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
}