diff --git a/README.md b/README.md
index 922baa1..456511e 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ configurable matching rules. Available conditions:
* [Age](#age): label based on the age of a PR or Issue.
* [Author can merge](#author-can-merge): label based on whether the author can merge the PR
+* [Author is member of team](#author-in-team): label based on whether the author is an active member of the given team
* [Authors](#authors): label based on the PR/Issue authors
* [Base branch](#base-branch): label based on the PR's base branch name
* [Body](#body): label based on the PR/Issue body
@@ -339,6 +340,17 @@ This is implemented by checking if the author is an owner of the repo.
```yaml
author-can-merge: True
```
+
+
+### Author is member (PRs and Issues)
+
+This condition is satisfied when the author of the PR is an active
+member of the given team.
+
+```yaml
+author-is-member: CoreTeam
+```
+
### Authors (PRs and Issues)
This condition is satisfied when the author of the PR or Issue matches
diff --git a/cmd/action.go b/cmd/action.go
index 97a1c66..137be2d 100644
--- a/cmd/action.go
+++ b/cmd/action.go
@@ -244,6 +244,13 @@ func newLabeler(gh *github.Client, config *labeler.LabelerConfigV1) *labeler.Lab
owner, repo, &github.PullRequestListOptions{})
return prs, err
},
+ IsUserMemberOfTeam: func(user, team string) (bool, error) {
+ membership, _, err := gh.Organizations.GetOrgMembership(ctx, user, team)
+ if err != nil {
+ return false, err
+ }
+ return membership.GetState() == "active", nil
+ },
},
Client: labeler.NewDefaultHttpClient(),
}
diff --git a/pkg/condition_author_in_team.go b/pkg/condition_author_in_team.go
new file mode 100644
index 0000000..96c53d9
--- /dev/null
+++ b/pkg/condition_author_in_team.go
@@ -0,0 +1,23 @@
+package labeler
+
+import (
+ "fmt"
+)
+
+func AuthorInTeamCondition(l *Labeler) Condition {
+ return Condition{
+ GetName: func() string {
+ return "Author is member of team"
+ },
+ CanEvaluate: func(target *Target) bool {
+ return true
+ },
+ Evaluate: func(target *Target, matcher LabelMatcher) (bool, error) {
+ if len(matcher.AuthorInTeam) <= 0 {
+ return false, fmt.Errorf("author-in-team is not set in config")
+ }
+ // check if author is a member of team
+ return l.GitHubFacade.IsUserMemberOfTeam(target.Author, matcher.AuthorInTeam)
+ },
+ }
+}
diff --git a/pkg/labeler.go b/pkg/labeler.go
index 21250b5..1f61624 100644
--- a/pkg/labeler.go
+++ b/pkg/labeler.go
@@ -22,6 +22,7 @@ type LabelMatcher struct {
Age string
AuthorCanMerge string `yaml:"author-can-merge"`
Authors []string
+ AuthorInTeam string `yaml:"author-in-team"`
BaseBranch string `yaml:"base-branch"`
Body string
Branch string
@@ -65,9 +66,10 @@ type LabelUpdates struct {
// Just to make this mockable..
type GitHubFacade struct {
- GetRawDiff func(owner, repo string, prNumber int) (string, error)
- ListIssuesByRepo func(owner, repo string) ([]*gh.Issue, error)
- ListPRs func(owner, repo string) ([]*gh.PullRequest, error)
+ GetRawDiff func(owner, repo string, prNumber int) (string, error)
+ ListIssuesByRepo func(owner, repo string) ([]*gh.Issue, error)
+ ListPRs func(owner, repo string) ([]*gh.PullRequest, error)
+ IsUserMemberOfTeam func(user, team string) (bool, error)
}
type Labeler struct {
@@ -225,6 +227,7 @@ func (l *Labeler) findMatches(target *Target, config *LabelerConfigV1) (LabelUpd
AgeCondition(l),
AuthorCondition(),
AuthorCanMergeCondition(),
+ AuthorInTeamCondition(l),
BaseBranchCondition(),
BodyCondition(),
BranchCondition(),
diff --git a/pkg/labeler_test.go b/pkg/labeler_test.go
index 6a24c92..50316b6 100644
--- a/pkg/labeler_test.go
+++ b/pkg/labeler_test.go
@@ -983,6 +983,46 @@ func TestHandleEvent(t *testing.T) {
initialLabels: []string{"Meh"},
expectedLabels: []string{"Meh", "Test"},
},
+ {
+ event: "issues",
+ payloads: []string{"issue_open"},
+ name: "Add a label to issue when author is in team",
+ config: LabelerConfigV1{
+ Version: 1,
+ Labels: []LabelMatcher{
+ {
+ Label: "ShouldAppear",
+ AuthorInTeam: "team-with-srvaroa",
+ },
+ {
+ Label: "ShouldNotAppear",
+ AuthorInTeam: "team-with",
+ },
+ },
+ },
+ initialLabels: []string{"Meh"},
+ expectedLabels: []string{"Meh", "ShouldAppear"},
+ },
+ {
+ event: "pull_request",
+ payloads: []string{"create_pr"},
+ name: "Add a label to PR when author is in team",
+ config: LabelerConfigV1{
+ Version: 1,
+ Labels: []LabelMatcher{
+ {
+ Label: "ShouldAppear",
+ AuthorInTeam: "team-with-srvaroa",
+ },
+ {
+ Label: "ShouldNotAppear",
+ AuthorInTeam: "team-with",
+ },
+ },
+ },
+ initialLabels: []string{"Meh"},
+ expectedLabels: []string{"Meh", "ShouldAppear"},
+ },
}
for _, tc := range testCases {
@@ -1034,6 +1074,10 @@ func NewTestLabeler(t *testing.T, tc TestCase) Labeler {
data, err := ioutil.ReadAll(file)
return string(data), nil
},
+ // Will return true whenever team contains the given user name
+ IsUserMemberOfTeam: func(user, team string) (bool, error) {
+ return strings.Contains(team, user), nil
+ },
},
}
}