Skip to content

Commit 903da9d

Browse files
committed
feat(pullvet): -label-match and -milestone-match to match regexp patterns
1 parent f9720f1 commit 903da9d

File tree

3 files changed

+129
-10
lines changed

3 files changed

+129
-10
lines changed

cmd/pullvet/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,29 @@ Just give me a simple Golang program that reads GitHub Actions v2 event json fil
1313
## Usage
1414

1515
```
16-
Usage of bin/pullvet:
16+
$ bin/actions pullvet -help
17+
Usage of pullvet:
1718
-any-milestone
1819
If set, pullvet fails whenever the pull request misses a milestone
1920
-label value
2021
Required label. When provided multiple times, pullvet succeeds if one or more of required labels exist
22+
-label-match value
23+
Regexp pattern to match label name against. If set, pullvet tries to find the label matches any of patterns and fail if none matched.
2124
-milestone string
2225
If set, pullvet fails whenever the pull request misses a milestone
26+
-milestone-match value
27+
Regexp pattern to match milestone title against. If set, pullvet tries to find the milestone matches any of patterns and fail if none matched.
2328
-note
2429
Require a note with the specified title. pullvet fails whenever the pr misses the note in the pr description. A note can be written in Markdown as: **<title>**:
2530
`
2631
<body>
2732
```
28-
-note-regex
29-
Regexp pattern of each note(including the title and the body). Default: [\*]*([^\*:]+)[\*]*:\s`
30-
([^`]+)
31-
``` (default "[\\*]*([^\\*:]+)[\\*]*:\\s```\n([^`]+)\n```")
33+
-note-regex string
34+
Regexp pattern of each note(including the title and the body) (default "[\\*]*([^\\*\r\n:]+)[\\*]*:\\s```\n([^`]+)\n```")
3235
-require-all
33-
If set, pullvet fails whenever the pull request was unable to fullfill any of the requirements. Default: false
36+
If set, pullvet fails whenever the pull request was unable to fullfill any of the requirements
3437
-require-any
35-
If set, pullvet fails whenever the pull request was unable to fullfill all the requirements. Default: true (default true)
38+
If set, pullvet fails whenever the pull request was unable to fullfill all the requirements (default true)
3639
```
3740

3841
## Running locally

pkg/pullvet/pullvet.go

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ type Command struct {
2323
labels cmd.StringSlice
2424
noteTitles cmd.StringSlice
2525

26+
labelMatches cmd.StringSlice
27+
milestoneMatches cmd.StringSlice
28+
2629
noteRegex string
2730

2831
milestone string
@@ -45,13 +48,15 @@ func New() *Command {
4548
}
4649

4750
func (c *Command) AddFlags(fs *flag.FlagSet) {
48-
fs.BoolVar(&c.requireAny, "require-any", true, "If set, pullvet fails whenever the pull request was unable to fullfill all the requirements. Default: true")
49-
fs.BoolVar(&c.requireAll, "require-all", false, "If set, pullvet fails whenever the pull request was unable to fullfill any of the requirements. Default: false")
51+
fs.BoolVar(&c.requireAny, "require-any", true, "If set, pullvet fails whenever the pull request was unable to fullfill all the requirements")
52+
fs.BoolVar(&c.requireAll, "require-all", false, "If set, pullvet fails whenever the pull request was unable to fullfill any of the requirements")
5053
fs.Var(&c.labels, "label", "Required label. When provided multiple times, pullvet succeeds if one or more of required labels exist")
5154
fs.BoolVar(&c.anyMilestone, "any-milestone", false, "If set, pullvet fails whenever the pull request misses a milestone")
5255
fs.StringVar(&c.milestone, "milestone", "", "If set, pullvet fails whenever the pull request misses a milestone")
56+
fs.Var(&c.labelMatches, "label-match", "Regexp pattern to match label name against. If set, pullvet tries to find the label matches any of patterns and fail if none matched.")
57+
fs.Var(&c.milestoneMatches, "milestone-match", "Regexp pattern to match milestone title against. If set, pullvet tries to find the milestone matches any of patterns and fail if none matched.")
5358
fs.Var(&c.noteTitles, "note", "Require a note with the specified title. pullvet fails whenever the pr misses the note in the pr description. A note can be written in Markdown as: **<title>**:\n```\n<body>\n```")
54-
fs.StringVar(&c.noteRegex, "note-regex", defaultNoteRegex, "Regexp pattern of each note(including the title and the body). Default: "+defaultNoteRegex)
59+
fs.StringVar(&c.noteRegex, "note-regex", defaultNoteRegex, "Regexp pattern of each note(including the title and the body)")
5560
}
5661

5762
func (c *Command) Run() error {
@@ -88,6 +93,29 @@ func (c *Command) HandlePullRequest(owner, repo string, pullRequest *github.Pull
8893
}
8994
}
9095

96+
labelRegexs := []*regexp.Regexp{}
97+
for _, p := range c.labelMatches {
98+
labelRegexs = append(labelRegexs, regexp.MustCompile(p))
99+
}
100+
101+
for _, r := range labelRegexs {
102+
var matched bool
103+
104+
for _, lbl := range labels {
105+
if r.MatchString(lbl) {
106+
matched = true
107+
}
108+
}
109+
110+
if matched {
111+
any = true
112+
passed += 1
113+
} else {
114+
all = false
115+
failures = append(failures, fmt.Sprintf("no label matched %q", r.String()))
116+
}
117+
}
118+
91119
milestone := pullRequest.Milestone.GetTitle()
92120

93121
if c.milestone != "" {
@@ -100,6 +128,22 @@ func (c *Command) HandlePullRequest(owner, repo string, pullRequest *github.Pull
100128
}
101129
}
102130

131+
milestoneRegexs := []*regexp.Regexp{}
132+
for _, p := range c.milestoneMatches {
133+
milestoneRegexs = append(milestoneRegexs, regexp.MustCompile(p))
134+
}
135+
136+
for _, r := range milestoneRegexs {
137+
matched := r.MatchString(milestone)
138+
if matched {
139+
any = true
140+
passed += 1
141+
} else {
142+
all = false
143+
failures = append(failures, fmt.Sprintf("milestone did not match %q", r.String()))
144+
}
145+
}
146+
103147
if c.anyMilestone {
104148
if milestone != "" {
105149
any = true

pkg/pullvet/pullvet_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,78 @@ func TestRun(t *testing.T) {
154154
},
155155
expected: "1 check(s) failed:\n* missing label: v3",
156156
},
157+
//
158+
// -label-match
159+
//
160+
{
161+
cmd: &Command{requireAll: true, labelMatches: []string{"release-v.+"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
162+
input: &github.PullRequest{
163+
Labels: []*github.Label{
164+
&github.Label{Name: github.String("rel-v1")},
165+
},
166+
},
167+
expected: "1 check(s) failed:\n* no label matched \"release-v.+\"",
168+
},
169+
{
170+
cmd: &Command{requireAll: true, labelMatches: []string{"release-v.+", "releasenote/none"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
171+
input: &github.PullRequest{
172+
Labels: []*github.Label{
173+
&github.Label{Name: github.String("release-v1")},
174+
&github.Label{Name: github.String("releasenote/none")},
175+
},
176+
},
177+
expected: "",
178+
},
179+
{
180+
cmd: &Command{requireAll: true, labelMatches: []string{"release-v.+", "releasenote/none"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
181+
input: &github.PullRequest{
182+
Labels: []*github.Label{
183+
&github.Label{Name: github.String("rel-v1")},
184+
&github.Label{Name: github.String("releasenote/none")},
185+
},
186+
},
187+
expected: "1 check(s) failed:\n* no label matched \"release-v.+\"",
188+
},
189+
{
190+
cmd: &Command{requireAny: true, labelMatches: []string{"release-v.+", "releasenote/none"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
191+
input: &github.PullRequest{
192+
Labels: []*github.Label{
193+
&github.Label{Name: github.String("rel-v1")},
194+
&github.Label{Name: github.String("releasenote/none")},
195+
},
196+
},
197+
expected: "",
198+
},
199+
{
200+
cmd: &Command{requireAll: true, labelMatches: []string{"release-v.+"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
201+
input: &github.PullRequest{
202+
Labels: []*github.Label{
203+
&github.Label{Name: github.String("release-v1")},
204+
},
205+
},
206+
expected: "",
207+
},
208+
//
209+
// -milestone-match
210+
//
211+
{
212+
cmd: &Command{requireAny: true, milestoneMatches: []string{"release-v.+"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
213+
input: &github.PullRequest{
214+
Milestone: &github.Milestone{
215+
Title: github.String("rel-v1"),
216+
},
217+
},
218+
expected: "1 check(s) failed:\n* milestone did not match \"release-v.+\"",
219+
},
220+
{
221+
cmd: &Command{requireAny: true, milestoneMatches: []string{"release-v.+", "rel-v.+"}, noteRegex: defaultNoteRegex, getPullRequestBody: stubPRBody("")},
222+
input: &github.PullRequest{
223+
Milestone: &github.Milestone{
224+
Title: github.String("rel-v1"),
225+
},
226+
},
227+
expected: "",
228+
},
157229
}
158230

159231
for i := range testcases {

0 commit comments

Comments
 (0)