tools/commentMonitor/client.go (122 lines of code) (raw):
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"bytes"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
"text/template"
)
type commentMonitorClient struct {
ghClient *githubClient
allArgs map[string]string
regex *regexp.Regexp
events []webhookEvent
prefixes []commandPrefix
helpTemplate string
shouldVerifyUser bool
eventType string
commentTemplate string
label string
}
// Set eventType and commentTemplate if
// regexString is validated against provided command.
func (c *commentMonitorClient) validateRegex(command string) bool {
for _, e := range c.events {
c.regex = regexp.MustCompile(e.RegexString)
if c.regex.MatchString(command) {
c.commentTemplate = e.CommentTemplate
c.eventType = e.EventType
c.label = e.Label
log.Println("comment validation successful")
return true
}
}
return false
}
func (c *commentMonitorClient) checkCommandPrefix(command string) bool {
for _, p := range c.prefixes {
if strings.HasPrefix(command, p.Prefix) {
c.helpTemplate = p.HelpTemplate
c.shouldVerifyUser = p.VerifyUser
return true
}
}
return false
}
// Verify if user is allowed to perform activity.
func (c commentMonitorClient) verifyUser() error {
if c.shouldVerifyUser {
var allowed bool
allowedAssociations := []string{"COLLABORATOR", "MEMBER", "OWNER"}
for _, a := range allowedAssociations {
if a == c.ghClient.authorAssociation {
allowed = true
}
}
if !allowed {
b := fmt.Sprintf("@%s is not a org member nor a collaborator and cannot execute benchmarks.", c.ghClient.author)
if err := c.ghClient.postComment(b); err != nil {
return fmt.Errorf("%v : couldn't post comment", err)
}
return fmt.Errorf("author is not a member or collaborator")
}
log.Println("author is a member or collaborator")
}
return nil
}
// Extract args if regexString provided.
func (c *commentMonitorClient) extractArgs(command string) error {
var err error
if c.regex != nil {
// Add command arguments.
commandArgs := c.regex.FindStringSubmatch(command)[1:]
commandArgsNames := c.regex.SubexpNames()[1:]
for i, argName := range commandArgsNames {
if argName == "" {
return fmt.Errorf("using named groups is mandatory")
}
c.allArgs[argName] = commandArgs[i]
}
// Add non-comment arguments if any.
c.allArgs["PR_NUMBER"] = strconv.Itoa(c.ghClient.pr)
c.allArgs["LAST_COMMIT_SHA"], err = c.ghClient.getLastCommitSHA()
if err != nil {
return fmt.Errorf("%v: could not fetch SHA", err)
}
// TODO (geekodour) : We could run this in a seperate method.
err = c.ghClient.createRepositoryDispatch(c.eventType, c.allArgs)
if err != nil {
return fmt.Errorf("%v: could not create repository_dispatch event", err)
}
}
return nil
}
func (c commentMonitorClient) postLabel() error {
if c.label != "" {
if err := c.ghClient.createLabel(c.label); err != nil {
return fmt.Errorf("%v : couldn't set label", err)
}
log.Println("label successfully set")
}
return nil
}
func (c commentMonitorClient) generateAndPostSuccessComment() error {
return c.generateAndPostComment(c.commentTemplate)
}
func (c commentMonitorClient) generateAndPostErrorComment() error {
return c.generateAndPostComment(c.helpTemplate)
}
func (c commentMonitorClient) generateAndPostComment(commentTemplate string) error {
if commentTemplate != "" {
// Add all env vars to allArgs.
for _, e := range os.Environ() {
tmp := strings.Split(e, "=")
c.allArgs[tmp[0]] = tmp[1]
}
// Generate the comment template.
var buf bytes.Buffer
ct := template.Must(template.New("Comment").Parse(commentTemplate))
if err := ct.Execute(&buf, c.allArgs); err != nil {
return err
}
// Post the comment.
if err := c.ghClient.postComment(buf.String()); err != nil {
return fmt.Errorf("%v : couldn't post generated comment", err)
}
log.Println("comment successfully posted")
}
return nil
}