Skip to content

Commit e5619c5

Browse files
authored
feat: allow enable needs-retitle like a non external plugin (#3)
1 parent 78a7b31 commit e5619c5

File tree

7 files changed

+499
-50
lines changed

7 files changed

+499
-50
lines changed

README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- [Overview](#overview)
44
- [Configuration](#configuration)
5+
- [Enable only in some repositories of an organization](#enable-only-in-some-repositories-of-an-organization)
56
- [Build](#build)
67
- [Deploy](#deploy)
78

@@ -77,6 +78,74 @@ You'll need to add new things to your prow `plugins.yaml` file:
7778
- needs-retitle
7879
```
7980
81+
### Enable only in some repositories of an organization
82+
83+
To enable the plugin only in some repositories of the same organization you have two options:
84+
85+
* You can add to the `external_plugins` options all the repositories you want like:
86+
87+
```
88+
external_plugins:
89+
org-foo/repo-bar:
90+
- name: needs-retitle
91+
events:
92+
- pull_request
93+
org-foo/repo-bar-2:
94+
- name: needs-retitle
95+
events:
96+
- pull_request
97+
org-foo/repo-bar-3:
98+
- name: needs-retitle
99+
events:
100+
- pull_request
101+
...
102+
```
103+
104+
* You can use `require_enable_as_not_external`, this way you can enable the plugin for the whole organization at the `external_plugins` config level, and then just add the plugin to each repo like any other plugin, example:
105+
106+
* First we enable the `require_enable_as_not_external` setting for the plugin:
107+
108+
```
109+
needs_retitle:
110+
regexp: "^(fix:|feat:|major:).*$"
111+
require_enable_as_not_external: true
112+
error_message: |
113+
Invalid title for the PR, the title needs to be like:
114+
115+
fix: this is a fix commit
116+
feat: this is a feature commit
117+
major: this is a major commit
118+
```
119+
120+
* Then we enable the plugin for the whole organization in `external_plugins`:
121+
122+
```
123+
external_plugins:
124+
org-foo:
125+
- name: needs-retitle
126+
events:
127+
- pull_request
128+
```
129+
130+
* And now we enable it like any other plugin for the repositories:
131+
132+
```
133+
plugins:
134+
org-foo/test-infra:
135+
- approve
136+
- assign
137+
- config-updater
138+
- needs-retitle
139+
org-foo/my-repo:
140+
- approve
141+
- assign
142+
- lgtm
143+
- needs-retitle
144+
org-foo/another-repo:
145+
- trigger
146+
- needs-retitle
147+
```
148+
80149
## Build
81150
82151
* To make just the binary run: `make build`

cmd/needs-retitle/main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ func main() {
9999
log.WithError(err).Fatalf("Error loading plugin config from %q.", o.pluginConfig)
100100
}
101101

102-
pca := config.NewPluginConfigAgent()
102+
p := plugin.NewPlugin(pa)
103+
104+
pca := config.NewPluginConfigAgent(p)
103105
if err := pca.Start(o.pluginConfig); err != nil {
104106
log.WithError(err).Fatalf("Error loading %s config from %q.", plugin.PluginName, o.pluginConfig)
105107
}
@@ -116,7 +118,7 @@ func main() {
116118

117119
interrupts.TickLiteral(func() {
118120
start := time.Now()
119-
if err := pca.GetPlugin().HandleAll(log, githubClient, pa.Config()); err != nil {
121+
if err := pca.GetPlugin().HandleAll(log, githubClient); err != nil {
120122
log.WithError(err).Error("Error during periodic update of all PRs.")
121123
}
122124
log.WithField("duration", fmt.Sprintf("%v", time.Since(start))).Info("Periodic update complete.")

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ require (
2020
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a // indirect
2121
gopkg.in/yaml.v2 v2.3.0 // indirect
2222
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
23+
gotest.tools v2.2.0+incompatible
2324
honnef.co/go/tools v0.0.1-2020.1.4 // indirect
2425
k8s.io/test-infra v0.0.0-20200702033203-1e71b3526aef
2526
sigs.k8s.io/yaml v1.2.0

pkg/config/config.go

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
11
package config
22

33
import (
4-
"fmt"
54
"io/ioutil"
6-
"regexp"
75
"time"
86

97
"github.com/ouzi-dev/needs-retitle/pkg/plugin"
8+
"github.com/ouzi-dev/needs-retitle/pkg/types"
109
"github.com/sirupsen/logrus"
1110
"sigs.k8s.io/yaml"
1211
)
1312

1413
// ConfigAgent contains the agent mutex and the Agent configuration.
1514
type PluginConfigAgent struct {
16-
configuration *Configuration
17-
plugin *plugin.Plugin
15+
plugin *plugin.Plugin
1816
}
1917

20-
// Configuration is the top-level serialization target for plugin Configuration.
21-
type Configuration struct {
22-
NeedsRetitle NeedsRetitle `json:"needs_retitle"`
23-
}
24-
25-
type NeedsRetitle struct {
26-
Regexp string `json:"regexp"`
27-
ErrorMessage string `json:"error_message"`
28-
}
29-
30-
func NewPluginConfigAgent() *PluginConfigAgent {
18+
func NewPluginConfigAgent(p *plugin.Plugin) *PluginConfigAgent {
3119
return &PluginConfigAgent{
32-
plugin: &plugin.Plugin{},
20+
plugin: p,
3321
}
3422
}
3523

@@ -62,7 +50,7 @@ func (pca *PluginConfigAgent) Load(path string) error {
6250
if err != nil {
6351
return err
6452
}
65-
np := &Configuration{}
53+
np := &types.Configuration{}
6654
if err := yaml.Unmarshal(b, np); err != nil {
6755
return err
6856
}
@@ -76,22 +64,6 @@ func (pca *PluginConfigAgent) Load(path string) error {
7664
}
7765

7866
// Set sets the plugin agent configuration.
79-
func (pca *PluginConfigAgent) Set(pc *Configuration) {
80-
pca.configuration = pc
81-
r, _ := regexp.Compile(pca.configuration.NeedsRetitle.Regexp)
82-
pca.plugin.SetConfig(pc.NeedsRetitle.ErrorMessage, r)
83-
}
84-
85-
func (c *Configuration) Validate() error {
86-
if len(c.NeedsRetitle.Regexp) == 0 {
87-
return fmt.Errorf("needs_pr_rename.regexp can not be empty")
88-
}
89-
90-
_, err := regexp.Compile(c.NeedsRetitle.Regexp)
91-
92-
if err != nil {
93-
return fmt.Errorf("error compiling regular expression %s: %v", c.NeedsRetitle.Regexp, err)
94-
}
95-
96-
return nil
67+
func (pca *PluginConfigAgent) Set(pc *types.Configuration) {
68+
pca.plugin.SetConfig(pc)
9769
}

pkg/plugin/plugin.go

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"sync"
2626
"time"
2727

28+
"github.com/ouzi-dev/needs-retitle/pkg/types"
2829
githubql "github.com/shurcooL/githubv4"
2930
"github.com/sirupsen/logrus"
3031

@@ -57,11 +58,19 @@ type githubClient interface {
5758
type Plugin struct {
5859
mut sync.Mutex
5960
c *pluginConfig
61+
ca *plugins.ConfigAgent
6062
}
6163

6264
type pluginConfig struct {
6365
errorMessage string
6466
re *regexp.Regexp
67+
config *types.Configuration
68+
}
69+
70+
func NewPlugin(ca *plugins.ConfigAgent) *Plugin {
71+
return &Plugin{
72+
ca: ca,
73+
}
6574
}
6675

6776
// HelpProvider constructs the PluginHelp for this plugin that takes into account enabled repositories.
@@ -74,18 +83,21 @@ The plugin reacts to commit changes on PRs in addition to periodically scanning
7483
nil
7584
}
7685

77-
func (p *Plugin) SetConfig(m string, r *regexp.Regexp) {
86+
func (p *Plugin) SetConfig(c *types.Configuration) {
7887
p.mut.Lock()
7988
defer p.mut.Unlock()
8089

90+
r, _ := regexp.Compile(c.NeedsRetitle.Regexp)
91+
8192
errorMessage := fmt.Sprintf(defaultNeedsRetitleMessage, r.String())
82-
if len(m) > 0 {
83-
errorMessage = m
93+
if len(c.NeedsRetitle.ErrorMessage) > 0 {
94+
errorMessage = c.NeedsRetitle.ErrorMessage
8495
}
8596

8697
p.c = &pluginConfig{
8798
errorMessage: errorMessage,
8899
re: r,
100+
config: c,
89101
}
90102
}
91103

@@ -131,6 +143,20 @@ func (p *Plugin) handle(log *logrus.Entry, ghc githubClient, pr *github.PullRequ
131143

132144
org := pr.Base.Repo.Owner.Login
133145
repo := pr.Base.Repo.Name
146+
147+
pluginConfig := p.getConfig()
148+
149+
if pluginConfig.config.NeedsRetitle.RequireEnableAsNotExternal {
150+
config := p.ca.Config()
151+
if orgs, repos := config.EnabledReposForPlugin(PluginName); orgs != nil || repos != nil {
152+
orgRepo := fmt.Sprintf("%s/%s", org, repo)
153+
if !isInArray(org, orgs) && !isInArray(orgRepo, repos) {
154+
log.Warnf("Repo %s not enabled for the %s plugin", orgRepo, PluginName)
155+
return nil
156+
}
157+
}
158+
}
159+
134160
number := pr.Number
135161
title := pr.Title
136162

@@ -140,14 +166,36 @@ func (p *Plugin) handle(log *logrus.Entry, ghc githubClient, pr *github.PullRequ
140166
}
141167
hasLabel := github.HasLabel(needsRetitleLabel, issueLabels)
142168

143-
return p.takeAction(log, ghc, org, repo, number, pr.User.Login, hasLabel, title)
169+
return p.takeAction(log, ghc, org, repo, number, pr.User.Login, hasLabel, title, pluginConfig)
170+
}
171+
172+
func isInArray(s string, a []string) bool {
173+
for _, v := range a {
174+
if s == v {
175+
return true
176+
}
177+
}
178+
179+
return false
144180
}
145181

146182
// HandleAll checks all orgs and repos that enabled this plugin for open PRs to
147183
// determine if the "needs-retitle" label needs to be added or removed.
148-
func (p *Plugin) HandleAll(log *logrus.Entry, ghc githubClient, config *plugins.Configuration) error {
184+
func (p *Plugin) HandleAll(log *logrus.Entry, ghc githubClient) error {
149185
log.Info("Checking all PRs.")
150-
orgs, repos := config.EnabledReposForExternalPlugin(PluginName)
186+
187+
pluginConfig := p.getConfig()
188+
config := p.ca.Config()
189+
190+
var orgs []string
191+
var repos []string
192+
193+
if pluginConfig.config.NeedsRetitle.RequireEnableAsNotExternal {
194+
orgs, repos = config.EnabledReposForPlugin(PluginName)
195+
} else {
196+
orgs, repos = config.EnabledReposForExternalPlugin(PluginName)
197+
}
198+
151199
if len(orgs) == 0 && len(repos) == 0 {
152200
log.Warnf("No repos have been configured for the %s plugin", PluginName)
153201
return nil
@@ -192,6 +240,7 @@ func (p *Plugin) HandleAll(log *logrus.Entry, ghc githubClient, config *plugins.
192240
string(pr.Author.Login),
193241
hasLabel,
194242
title,
243+
pluginConfig,
195244
)
196245
if err != nil {
197246
l.WithError(err).Error("Error handling PR.")
@@ -203,8 +252,7 @@ func (p *Plugin) HandleAll(log *logrus.Entry, ghc githubClient, config *plugins.
203252
// takeAction adds or removes the "needs-rebase" label based on the current
204253
// state of the PR (hasLabel and mergeable). It also handles adding and
205254
// removing GitHub comments notifying the PR author that a rebase is needed.
206-
func (p *Plugin) takeAction(log *logrus.Entry, ghc githubClient, org, repo string, num int, author string, hasLabel bool, title string) error {
207-
c := p.getConfig()
255+
func (p *Plugin) takeAction(log *logrus.Entry, ghc githubClient, org, repo string, num int, author string, hasLabel bool, title string, c *pluginConfig) error {
208256
needsRetitleMessage := c.errorMessage
209257
titleOk := c.re.MatchString(title)
210258
if !titleOk && !hasLabel {

0 commit comments

Comments
 (0)