-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
construct.go
185 lines (159 loc) · 4.49 KB
/
construct.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package labeler
import (
"context"
"errors"
"os"
"strings"
"github.com/google/go-github/v50/github"
"golang.org/x/oauth2"
)
// Opt is a group of options for constructing a new Labeler
type Opt struct {
token string
ctx context.Context
client *github.Client
owner string
repo string
event string
id int
data string
configPath string
}
type OptFn func(o *Opt)
// WithToken allows configuration of the github token required for accessing the GitHub API for a given org/repo.
//
//goland:noinspection GoUnusedExportedFunction
func WithToken(value string) OptFn {
return func(o *Opt) {
o.token = value
}
}
// WithContext allows configuration of the context used as a parent context for all GitHub API calls
func WithContext(ctx context.Context) OptFn {
return func(o *Opt) {
o.ctx = ctx
}
}
// WithClient allows for configuration of the github client
//
//goland:noinspection GoUnusedExportedFunction
func WithClient(client *github.Client) OptFn {
return func(o *Opt) {
o.client = client
}
}
// WithOwner allows for configuring the user or organization owning the target repo
func WithOwner(value string) OptFn {
return func(o *Opt) {
o.owner = value
}
}
// WithRepo allows for configuring the name of the repo under a given owner; use in conjunction with WithOwner
func WithRepo(value string) OptFn {
return func(o *Opt) {
o.repo = value
}
}
// WithEvent allows for configuring the target event type
func WithEvent(value string) OptFn {
return func(o *Opt) {
o.event = value
}
}
// WithID allows for configuring the identifier of the issue or pull request we want to label
func WithID(value int) OptFn {
return func(o *Opt) {
o.id = value
}
}
// WithData allows for configuring the JSON event data to apply a label
func WithData(value string) OptFn {
return func(o *Opt) {
o.data = value
}
}
// WithConfigPath allows for configuring the labeler config path relative to the repository root (usually .github/labeler.yml)
func WithConfigPath(value string) OptFn {
return func(o *Opt) {
o.configPath = value
}
}
// NewWithOptions constructs a new Labeler with functional arguments of type OptFn
func NewWithOptions(opts ...OptFn) (*Labeler, error) {
l := Labeler{}
options := Opt{
token: os.Getenv("GITHUB_TOKEN"),
owner: os.Getenv("GITHUB_ACTOR"),
repo: os.Getenv("GITHUB_REPO"),
event: os.Getenv("GITHUB_EVENT_NAME"),
id: -1,
}
for _, opt := range opts {
opt(&options)
}
// validations
if options.owner == "" && options.repo == "" {
return nil, errors.New("both a github and owner are required")
}
if strings.Contains(options.repo, "/") {
return nil, errors.New("a repo must be just the repo name. Separate org/repo style into owner and repo options")
}
if options.owner == "" {
return nil, errors.New("a github owner (user or org) is required")
}
if options.repo == "" {
return nil, errors.New("a github repo is required")
}
if options.id < 0 {
return nil, errors.New("the integer id of the issue or pull request is required")
}
if options.ctx == nil {
options.ctx = context.Background()
}
if options.client == nil {
// only validate the token when constructing this default client. Otherwise, assume the caller has property constructed a client
if options.token == "" {
isTest := false
// hack: only apply this required token check if not in tests.
// this isn't a concern if we construct with an empty token because the client will error at invocation
for _, arg := range os.Args {
if strings.HasPrefix(arg, "-test.v") {
isTest = true
}
}
if !isTest {
return nil, errors.New("github token (e.g. GITHUB_TOKEN environment variable) is required")
}
}
options.client = github.NewClient(oauth2.NewClient(options.ctx, oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: options.token},
)))
}
// assignment
l.context = &options.ctx
l.client = options.client
l.Owner = &options.owner
l.Repo = &options.repo
l.Event = &options.event
l.ID = &options.id
if options.data != "" {
l.Data = &options.data
}
l.configPath = options.configPath
return &l, nil
}
// New creates a new instance of a Labeler
func New(owner string, repo string, event string, id int, data *string) (*Labeler, error) {
if data == nil {
return nil, errors.New("a JSON string of event data is required")
}
return NewWithOptions(
WithOwner(owner),
WithRepo(repo),
WithEvent(event),
WithID(id),
WithData(*data),
WithContext(context.Background()),
WithConfigPath(".github/labeler.yml"),
)
}