-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a58596c
commit ae8cbbb
Showing
4 changed files
with
285 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package assign | ||
|
||
import ( | ||
"context" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/golang/glog" | ||
"github.com/google/go-github/github" | ||
) | ||
|
||
const ( | ||
Assign = "/assign" | ||
Unassign = "/unassign" | ||
) | ||
|
||
// Handle event with assign | ||
func Handle(client *github.Client, event github.IssueCommentEvent) error { | ||
comment := *event.Comment.Body | ||
//regular expression to Assign or unassign the Assignees | ||
reg := regexp.MustCompile("(?mi)^/(un)?assign(( @?[-\\w]+?)*)\\s*$") | ||
|
||
if reg.MatchString(comment) { | ||
ctx := context.Background() | ||
//split the assignees and operation to be performed. | ||
substrings := strings.Split(comment, "@") | ||
//list of assignees to be assigned for issues/PR | ||
listOfAssignees := make([]string, 0) | ||
//range over the substring to get the list of assignees | ||
for i, assignees := range substrings { | ||
if i == 0 { | ||
//first index is the operation to be performed, rest will be the assignees | ||
continue | ||
} | ||
listOfAssignees = append(listOfAssignees, assignees) | ||
} | ||
//operation is the assign or unassign check | ||
operation := strings.Trim(substrings[0], " ") | ||
if operation == Assign { | ||
_, _, err := client.Issues.AddAssignees(ctx, *event.Repo.Owner.Login, *event.Repo.Name, *event.Issue.Number, listOfAssignees) | ||
if err != nil { | ||
glog.Fatalf("Unable to Add Assignees: %v err: %v", listOfAssignees, err) | ||
return err | ||
} else { | ||
glog.Infof("Assignee added successfully: %v", listOfAssignees) | ||
} | ||
} else if operation == Unassign { | ||
_, _, err := client.Issues.RemoveAssignees(ctx, *event.Repo.Owner.Login, *event.Repo.Name, *event.Issue.Number, listOfAssignees) | ||
if err != nil { | ||
glog.Fatalf("Cannot remove Assignees: %v err: %v", listOfAssignees, err) | ||
return err | ||
} | ||
glog.Infof("Removed assignee: %v", listOfAssignees) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
package handlers | ||
|
||
import ( | ||
|
||
"github.com/golang/glog" | ||
) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,40 @@ | ||
package handlers | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/golang/glog" | ||
"github.com/google/go-github/github" | ||
) | ||
|
||
const ( | ||
Assign = "/assign" | ||
Unassign = "/unassign" | ||
"github.com/Huawei-PaaS/ci-bot/handlers/assign" | ||
"github.com/Huawei-PaaS/ci-bot/handlers/label" | ||
) | ||
|
||
type GithubIssue github.Issue | ||
|
||
func (s *Server) handleIssueEvent(body []byte) { | ||
glog.Info("Received an Issue Event") | ||
|
||
} | ||
|
||
//function to handle issue comments | ||
func (s *Server) handleIssueCommentEvent(body []byte, client *github.Client) { | ||
var commentEvent github.IssueCommentEvent | ||
|
||
// Unmarshal | ||
err := json.Unmarshal(body, &commentEvent) | ||
if err != nil { | ||
glog.Errorf("fail to unmarshal: %v", err) | ||
} | ||
ctx := context.Background() | ||
comment := *commentEvent.Comment.Body | ||
//split the assignees and operation to be performed. | ||
substrings := strings.Split(comment, "@") | ||
//regular expression to Assign or unassign the Assignees | ||
reg := regexp.MustCompile("(?mi)^/(un)?assign(( @?[-\\w]+?)*)\\s*$") | ||
matchAssignOrUnassign := reg.MatchString(comment) | ||
//list of assignees to be assigned for issues/PR | ||
listOfAssignees := make([]string, 0) | ||
//range over the substring to get the list of assignees | ||
for i, assignees := range substrings { | ||
if i == 0 { | ||
//first index is the operation to be performed, rest will be the assignees | ||
continue | ||
} | ||
listOfAssignees = append(listOfAssignees, assignees) | ||
|
||
// assign | ||
err = assign.Handle(client, commentEvent) | ||
if err != nil { | ||
glog.Errorf("fail to handle: %v", err) | ||
} | ||
//operation is the assign or unassign check | ||
operation := strings.Trim(substrings[0], " ") | ||
|
||
if matchAssignOrUnassign == true { | ||
if operation == Assign { | ||
_, _, err := client.Issues.AddAssignees(ctx, *commentEvent.Repo.Owner.Login, *commentEvent.Repo.Name, *commentEvent.Issue.Number, listOfAssignees) | ||
if err != nil { | ||
glog.Fatalf("Unable to Add Assignees: %v err: %v", listOfAssignees, err) | ||
} else { | ||
glog.Infof("Assignee added successfully: %v", listOfAssignees) | ||
} | ||
} else if operation == Unassign { | ||
_, _, err := client.Issues.RemoveAssignees(ctx, *commentEvent.Repo.Owner.Login, *commentEvent.Repo.Name, *commentEvent.Issue.Number, listOfAssignees) | ||
if err != nil { | ||
glog.Fatalf("Cannot remove Assignees: %v err: %v", listOfAssignees, err) | ||
} | ||
glog.Infof("Removed assignee: %v", listOfAssignees) | ||
} | ||
// label | ||
err = label.Handle(client, commentEvent) | ||
if err != nil { | ||
glog.Errorf("fail to handle: %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
package label | ||
|
||
import ( | ||
"context" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/golang/glog" | ||
"github.com/google/go-github/github" | ||
) | ||
|
||
var ( | ||
// regular expression to add label | ||
regAddLabel = regexp.MustCompile(`(?mi)^/(kind|priority)\s*(.*)$`) | ||
// regular expression to remove label | ||
regRemoveLabel = regexp.MustCompile(`(?mi)^/remove-(kind|priority)\s*(.*)$`) | ||
) | ||
|
||
// Handle event with label | ||
func Handle(client *github.Client, event github.IssueCommentEvent) error { | ||
// get basic params | ||
comment := *event.Comment.Body | ||
glog.Infof("receive event with label. comment: %s", comment) | ||
|
||
// add labels | ||
if regAddLabel.MatchString(comment) { | ||
return add(client, event) | ||
} | ||
// remove labels | ||
if regRemoveLabel.MatchString(comment) { | ||
return remove(client, event) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// add labels | ||
func add(client *github.Client, event github.IssueCommentEvent) error { | ||
// get basic params | ||
ctx := context.Background() | ||
comment := *event.Comment.Body | ||
owner := *event.Repo.Owner.Login | ||
repo := *event.Repo.Name | ||
number := *event.Issue.Number | ||
glog.Infof("add label started. comment: %s owner: %s repo: %s number: %d", comment, owner, repo, number) | ||
|
||
// map of add labels | ||
mapOfAddLabels := getLabelsMap(comment) | ||
glog.Infof("map of add labels: %v", mapOfAddLabels) | ||
|
||
// list labels in current github repository | ||
listofRepoLabels, _, err := client.Issues.ListLabels(ctx, owner, repo, nil) | ||
if err != nil { | ||
glog.Fatalf("unable to list repository labels. err: %v", err) | ||
return err | ||
} | ||
glog.Infof("list of repository labels: %v", listofRepoLabels) | ||
|
||
// list labels in current issue | ||
listofIssueLabels, _, err := client.Issues.ListLabelsByIssue(ctx, owner, repo, number, nil) | ||
if err != nil { | ||
glog.Fatalf("unable to list issue labels. err: %v", err) | ||
return err | ||
} | ||
glog.Infof("list of issue labels: %v", listofIssueLabels) | ||
|
||
// list of add labels | ||
listOfAddLabels := getListOfAddLabels(mapOfAddLabels, listofRepoLabels, listofIssueLabels) | ||
glog.Infof("list of add labels: %v", listOfAddLabels) | ||
|
||
// invoke github api to add labels | ||
if len(listOfAddLabels) > 0 { | ||
_, _, err := client.Issues.AddLabelsToIssue(ctx, owner, repo, number, listOfAddLabels) | ||
if err != nil { | ||
glog.Fatalf("unable to add labels: %v err: %v", listOfAddLabels, err) | ||
return err | ||
} else { | ||
glog.Infof("add labels successfully: %v", listOfAddLabels) | ||
} | ||
} else { | ||
glog.Infof("No label to add for this event") | ||
} | ||
return nil | ||
} | ||
|
||
// remove labels | ||
func remove(client *github.Client, event github.IssueCommentEvent) error { | ||
// get basic params | ||
ctx := context.Background() | ||
comment := *event.Comment.Body | ||
owner := *event.Repo.Owner.Login | ||
repo := *event.Repo.Name | ||
number := *event.Issue.Number | ||
glog.Infof("remove label started. comment: %s owner: %s repo: %s number: %d", comment, owner, repo, number) | ||
|
||
// map of add labels | ||
mapOfRemoveLabels := getLabelsMap(comment) | ||
glog.Infof("map of remove labels: %v", mapOfRemoveLabels) | ||
|
||
// list labels in current issue | ||
listofIssueLabels, _, err := client.Issues.ListLabelsByIssue(ctx, owner, repo, number, nil) | ||
if err != nil { | ||
glog.Fatalf("unable to list issue labels. err: %v", err) | ||
return err | ||
} | ||
glog.Infof("list of issue labels: %v", listofIssueLabels) | ||
|
||
// list of remove labels | ||
listOfRemoveLabels := getListOfRemoveLabels(mapOfRemoveLabels, listofIssueLabels) | ||
glog.Infof("list of remove labels: %v", listOfRemoveLabels) | ||
|
||
// invoke github api to remove labels | ||
if len(listOfRemoveLabels) > 0 { | ||
for _, l := range listOfRemoveLabels { | ||
_, err := client.Issues.RemoveLabelForIssue(ctx, owner, repo, number, l) | ||
if err != nil { | ||
glog.Fatalf("unable to remove label: %v err: %v", l, err) | ||
} else { | ||
glog.Infof("remove label successfully: %v", l) | ||
} | ||
} | ||
} else { | ||
glog.Infof("No label to remove for this event") | ||
} | ||
return nil | ||
} | ||
|
||
// getListOfAddLabels return the exact list of add labels | ||
func getListOfAddLabels(mapOfAddLabels map[string]string, listofRepoLabels []*github.Label, listofIssueLabels []*github.Label) []string { | ||
// init | ||
listOfAddLabels := make([]string, 0) | ||
// range over the map to filter the list of labels | ||
for l := range mapOfAddLabels { | ||
// check if the label is existing in current github repository | ||
existingInRepo := false | ||
for _, repoLabel := range listofRepoLabels { | ||
if l == *repoLabel.Name { | ||
existingInRepo = true | ||
break | ||
} | ||
} | ||
// the label is not existing in current github repository so it can not add this label | ||
if !existingInRepo { | ||
glog.Infof("label %s is not existing in repository", l) | ||
continue | ||
} | ||
|
||
// check if the label is existing in current issue | ||
existingInIssue := false | ||
for _, issueLabel := range listofIssueLabels { | ||
if l == *issueLabel.Name { | ||
existingInIssue = true | ||
break | ||
} | ||
} | ||
// the label is already existing in current issue so it is no need to add this label | ||
if existingInIssue { | ||
glog.Infof("label %s is already existing in current issue", l) | ||
continue | ||
} | ||
|
||
// append | ||
listOfAddLabels = append(listOfAddLabels, l) | ||
} | ||
return listOfAddLabels | ||
} | ||
|
||
// getListOfRemoveLabels return the exact list of remove labels | ||
func getListOfRemoveLabels(mapOfRemoveLabels map[string]string, listofIssueLabels []*github.Label) []string { | ||
// init | ||
listOfRemoveLabels := make([]string, 0) | ||
// range over the map to filter the list of labels | ||
for l := range mapOfRemoveLabels { | ||
// check if the label is existing in current issue | ||
existingInIssue := false | ||
for _, issueLabel := range listofIssueLabels { | ||
if l == *issueLabel.Name { | ||
existingInIssue = true | ||
break | ||
} | ||
} | ||
// the label is not existing in current issue so it is no need to remove this label | ||
if !existingInIssue { | ||
glog.Infof("label %s is not existing in current issue", l) | ||
continue | ||
} | ||
|
||
// append | ||
listOfRemoveLabels = append(listOfRemoveLabels, l) | ||
} | ||
return listOfRemoveLabels | ||
} | ||
|
||
// getLabelsMap for add or remove labels | ||
func getLabelsMap(comment string) map[string]string { | ||
// init labels map | ||
mapOfLabels := map[string]string{} | ||
// split with blank space | ||
substrings := strings.Split(strings.TrimSpace(comment), " ") | ||
// init label group | ||
labelGroup := "" | ||
// range over the substrings to get the map of labels | ||
for i, l := range substrings { | ||
if i == 0 { | ||
// first index is the operation to be performed, rest will be the labels | ||
// the label group. e.g kind, priority | ||
labelGroup = strings.Replace(strings.Replace(l, "/", "", 1), "remove-", "", 1) | ||
} else { | ||
// the whole label = label group + / + label. e.g kind/feature | ||
wholeLabel := labelGroup + "/" + l | ||
// use map to avoid the reduplicate label | ||
mapOfLabels[wholeLabel] = wholeLabel | ||
} | ||
} | ||
return mapOfLabels | ||
} |