diff --git a/pr/db/dbutil.go b/pr/db/dbutil.go index f0fb10c..2a4b57c 100644 --- a/pr/db/dbutil.go +++ b/pr/db/dbutil.go @@ -54,9 +54,8 @@ func GetGitHubHandle(email string) (string, error) { return sid, nil } -// GetMaintainer returns the maintainers of a port, -// the primary maintainer is always the first in the slice. -func GetMaintainer(port string) (*PortMaintainer, error) { +// GetPortMaintainer returns the maintainers of a port +func GetPortMaintainer(port string) (*PortMaintainer, error) { rows, err := wwwDB.Query("SELECT maintainer, is_primary "+ "FROM public.maintainers "+ "WHERE portfile = $1", port) diff --git a/pr/githubapi/pull_request.go b/pr/githubapi/pull_request.go index 8253a32..ba5f49e 100644 --- a/pr/githubapi/pull_request.go +++ b/pr/githubapi/pull_request.go @@ -26,19 +26,19 @@ func NewClient(botSecret string) *Client { } } -func (client *Client) ListChangedPorts(number int) ([]string, error) { +func (client *Client) ListChangedPortsAndLines(number int) (ports []string, changes []int, err error) { files, _, err := client.PullRequests.ListFiles(context.Background(), "macports-staging", "macports-ports", number, nil) if err != nil { - return nil, err + return nil, nil, err } - ports := make([]string, 0, 1) portfileRegexp := regexp.MustCompile(`[^\._/][^/]*/([^/]+)/Portfile`) for _, file := range files { if match := portfileRegexp.FindStringSubmatch(*file.Filename); match != nil { ports = append(ports, match[1]) + changes = append(changes, *file.Changes) } } - return ports, nil + return } func (client *Client) CreateComment(owner, repo string, number int, body *string) error { diff --git a/pr/webhook/pull_request.go b/pr/webhook/pull_request.go index 97c937f..52a564f 100644 --- a/pr/webhook/pull_request.go +++ b/pr/webhook/pull_request.go @@ -26,32 +26,43 @@ func (receiver *Receiver) handlePullRequest(body []byte) { number := *event.Number owner := *event.Repo.Owner.Login repo := *event.Repo.Name - isOpenmaintainer := true - isNomaintainer := true - isMaintainer := false - ports, err := receiver.githubClient.ListChangedPorts(number) + + ports, changes, err := receiver.githubClient.ListChangedPortsAndLines(number) if err != nil { return } - handles := make([]string, 0, 1) - for _, port := range ports { - maintainer, err := db.GetMaintainer(port) + + handles := make(map[string][]string) + isOpenmaintainer := true + isNomaintainer := true + isMaintainer := true + isOneMaintainer := false + for i, port := range ports { + portMaintainer, err := db.GetPortMaintainer(port) if err != nil { continue } - isNomaintainer = isNomaintainer && maintainer.NoMaintainer - isOpenmaintainer = isOpenmaintainer && (maintainer.OpenMaintainer || maintainer.NoMaintainer) - if maintainer.NoMaintainer { + isNomaintainer = isNomaintainer && portMaintainer.NoMaintainer + isOpenmaintainer = isOpenmaintainer && (portMaintainer.OpenMaintainer || portMaintainer.NoMaintainer) + if portMaintainer.NoMaintainer { continue } - if maintainer.Primary.GithubHandle != "" { - handles = append(handles, maintainer.Primary.GithubHandle) - if maintainer.Primary.GithubHandle == *event.Sender.Login { - // TODO: should be set only when the sender is maintainer of all modified ports - isMaintainer = true + allMaintainers := append(portMaintainer.Others, portMaintainer.Primary) + isPortMaintainer := false + for _, maintainer := range allMaintainers { + if maintainer.GithubHandle != "" { + handles[maintainer.GithubHandle] = append(handles[maintainer.GithubHandle], port) + if maintainer.GithubHandle == *event.Sender.Login { + isPortMaintainer = true + isOneMaintainer = true + } } } + if changes[i] > 7 && !isPortMaintainer { + isMaintainer = false + } } + isMaintainer = isOneMaintainer && isMaintainer switch *event.Action { case "opened": @@ -61,7 +72,11 @@ func (receiver *Receiver) handlePullRequest(body []byte) { mentionSymbol = "@" } if len(handles) > 0 { - body := "Notifying maintainers: " + mentionSymbol + strings.Join(handles, " "+mentionSymbol) + body := "Notifying maintainers:\n" + for handle, ports := range handles { + body += mentionSymbol + handle + " for port " + strings.Join(ports, ", ") + ".\n" + } + body += "\nBy a harmless bot." err = receiver.githubClient.CreateComment(owner, repo, number, &body) if err != nil { log.Println(err)