New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
prow/plugin: Extends label plugin to use Unique Prefixes #26383
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -104,6 +104,35 @@ func TestValidateExternalPlugins(t *testing.T) { | |||||||
} | ||||||||
} | ||||||||
|
||||||||
func TestValidateUniquePrefixes(t *testing.T) { | ||||||||
testCases := []struct { | ||||||||
name string | ||||||||
uniquePrefixes []string | ||||||||
isErrorNil bool | ||||||||
}{ | ||||||||
{ | ||||||||
name: "non-zero length prefixes", | ||||||||
uniquePrefixes: []string{"prefix1/", "prefix2"}, | ||||||||
isErrorNil: true, | ||||||||
}, | ||||||||
{ | ||||||||
name: "zero length prefixes", | ||||||||
uniquePrefixes: []string{"", "prefix2"}, | ||||||||
isErrorNil: false, | ||||||||
}, | ||||||||
} | ||||||||
for _, tC := range testCases { | ||||||||
t.Run(tC.name, func(t *testing.T) { | ||||||||
err := validateUniquePrefixes(tC.uniquePrefixes) | ||||||||
if tC.isErrorNil && err != nil { | ||||||||
t.Errorf("expected nil error got %s", err) | ||||||||
} else if !tC.isErrorNil && err == nil { | ||||||||
t.Errorf("expected non nil error, got nil") | ||||||||
} | ||||||||
Comment on lines
+127
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we test for full error like the test above? test-infra/prow/plugins/config_test.go Lines 101 to 103 in 37b977f
|
||||||||
}) | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
func TestSetDefault_Maps(t *testing.T) { | ||||||||
cases := []struct { | ||||||||
name string | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,20 @@ func init() { | |
plugins.RegisterPullRequestHandler(PluginName, handlePullRequest, helpProvider) | ||
} | ||
|
||
// getExistingUniquePrefixLabels returns a list of labels for every label prefix that can only exist once per issue | ||
func getExistingUniquePrefixLabels(config plugins.Label, labels []github.Label) map[string][]string { | ||
labelsMap := make(map[string][]string) | ||
prefixList := config.UniquePrefixes | ||
for _, prefix := range prefixList { | ||
for _, label := range labels { | ||
if matched := strings.HasPrefix(label.Name, prefix); matched { | ||
labelsMap[prefix] = append(labelsMap[prefix], label.Name) | ||
} | ||
} | ||
} | ||
return labelsMap | ||
} | ||
|
||
func configString(labels []string) string { | ||
var formattedLabels []string | ||
for _, label := range labels { | ||
|
@@ -168,7 +182,6 @@ func handleComment(gc githubClient, log *logrus.Entry, config plugins.Label, e * | |
if err != nil { | ||
return err | ||
} | ||
|
||
RepoLabelsExisting := sets.String{} | ||
for _, l := range repoLabels { | ||
RepoLabelsExisting.Insert(strings.ToLower(l.Name)) | ||
|
@@ -180,6 +193,7 @@ func handleComment(gc githubClient, log *logrus.Entry, config plugins.Label, e * | |
labelsToAdd []string | ||
labelsToRemove []string | ||
nonMemberTriageAccepted bool | ||
labelPrefix string | ||
) | ||
|
||
additionalLabelSet := sets.String{} | ||
|
@@ -228,12 +242,29 @@ func handleComment(gc githubClient, log *logrus.Entry, config plugins.Label, e * | |
gc.CreateComment(org, repo, e.Number, plugins.FormatResponseRaw(bodyWithoutComments, e.HTMLURL, e.User.Login, canNotSetLabelReason)) | ||
continue | ||
} | ||
|
||
uniqueLabelsMap := getExistingUniquePrefixLabels(config, labels) | ||
var labelsWithPrefixExist = false | ||
for prefix := range uniqueLabelsMap { | ||
if matched := strings.HasPrefix(labelToAdd, prefix); matched { | ||
labelPrefix = prefix | ||
labelsWithPrefixExist = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need an additional variable, we can just reset |
||
} | ||
} | ||
// if the labelToAdd matches a unique prefix, remove all pre existing | ||
// labels that match this unique prefix, and then add the new label | ||
if labelsWithPrefixExist { | ||
for _, label := range uniqueLabelsMap[labelPrefix] { | ||
if label != labelToAdd && github.HasLabel(label, labels) { | ||
if err := gc.RemoveLabel(org, repo, e.Number, label); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ability to remote a labelj can be behind a permission (see L279), so we need to test whether the user is able to remove the label (and handle that situation well, as ignoring that condition would lead to a duplicate label on the issue/pr) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @petr-muller thanks for reviewing this! L235 already has the check which checks user permissions (which when fails, does not enter the de-duplication logic that I have added, and you have pointed to). I'm not sure how this can lead to duplicate labels? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. L235 checks for the permission to add the new label, but your L258 removes a different label, which the user may not have a permission to remove. Imagine this:
Your code would remove the |
||
log.WithError(err).Errorf("GitHub failed to remove the following label: %s", label) | ||
} | ||
} | ||
} | ||
} | ||
if err := gc.AddLabel(org, repo, e.Number, labelToAdd); err != nil { | ||
log.WithError(err).WithField("label", labelToAdd).Error("GitHub failed to add the label") | ||
} | ||
} | ||
|
||
// Remove labels | ||
for _, labelToRemove := range labelsToRemove { | ||
if !github.HasLabel(labelToRemove, labels) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also look for duplicates, and perhaps also for one prefix being a prefix of another (
foo
andfoobar
eg) to avoid interaction between different prefixes