github.com/abayer/test-infra@v0.0.5/prow/plugins/welcome/welcome.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package welcome implements a prow plugin to welcome new contributors
    18  package welcome
    19  
    20  import (
    21  	"bytes"
    22  	"fmt"
    23  	"html/template"
    24  
    25  	"github.com/sirupsen/logrus"
    26  
    27  	"k8s.io/test-infra/prow/github"
    28  	"k8s.io/test-infra/prow/pluginhelp"
    29  	"k8s.io/test-infra/prow/plugins"
    30  )
    31  
    32  const (
    33  	pluginName = "welcome"
    34  )
    35  
    36  // PRInfo contains info used provided to the welcome message template
    37  type PRInfo struct {
    38  	Org         string
    39  	Repo        string
    40  	AuthorLogin string
    41  	AuthorName  string
    42  }
    43  
    44  func init() {
    45  	plugins.RegisterPullRequestHandler(pluginName, handlePullRequest, helpProvider)
    46  }
    47  
    48  func helpProvider(config *plugins.Configuration, enabledRepos []string) (*pluginhelp.PluginHelp, error) {
    49  	// The {WhoCanUse, Usage, Examples} fields are omitted because this plugin is not triggered with commands.
    50  	return &pluginhelp.PluginHelp{
    51  			Description: "The welcome plugin posts a welcoming message when it detects a user's first contribution to a repo.",
    52  			Config: map[string]string{
    53  				"": fmt.Sprintf(
    54  					"The welcome plugin is configured to post using following welcome template: %s.",
    55  					config.Welcome.MessageTemplate,
    56  				),
    57  			},
    58  		},
    59  		nil
    60  }
    61  
    62  type githubClient interface {
    63  	CreateComment(owner, repo string, number int, comment string) error
    64  	FindIssues(query, sort string, asc bool) ([]github.Issue, error)
    65  }
    66  
    67  type client struct {
    68  	GitHubClient githubClient
    69  	Logger       *logrus.Entry
    70  }
    71  
    72  func getClient(pc plugins.PluginClient) client {
    73  	return client{
    74  		GitHubClient: pc.GitHubClient,
    75  		Logger:       pc.Logger,
    76  	}
    77  }
    78  
    79  func handlePullRequest(pc plugins.PluginClient, pre github.PullRequestEvent) error {
    80  	return handlePR(getClient(pc), pre, pc.PluginConfig.Welcome.MessageTemplate)
    81  }
    82  
    83  func handlePR(c client, pre github.PullRequestEvent, welcomeTemplate string) error {
    84  	// Only consider newly opened PRs
    85  	if pre.Action != github.PullRequestActionOpened {
    86  		return nil
    87  	}
    88  
    89  	// search for PRs from the author in this repo
    90  	org := pre.PullRequest.Base.Repo.Owner.Login
    91  	repo := pre.PullRequest.Base.Repo.Name
    92  	user := pre.PullRequest.User.Login
    93  	query := fmt.Sprintf("is:pr repo:%s/%s author:%s", org, repo, user)
    94  	issues, err := c.GitHubClient.FindIssues(query, "", false)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	// if there is exactly one result, this is the first! post the welcome comment
   100  	if len(issues) == 1 {
   101  		// load the template, and run it over the PR info
   102  		parsedTemplate, err := template.New("welcome").Parse(welcomeTemplate)
   103  		if err != nil {
   104  			return err
   105  		}
   106  		var msgBuffer bytes.Buffer
   107  		err = parsedTemplate.Execute(&msgBuffer, PRInfo{
   108  			Org:         org,
   109  			Repo:        repo,
   110  			AuthorLogin: user,
   111  			AuthorName:  pre.PullRequest.User.Name,
   112  		})
   113  		if err != nil {
   114  			return err
   115  		}
   116  
   117  		// actually post the comment
   118  		return c.GitHubClient.CreateComment(org, repo, pre.PullRequest.Number, msgBuffer.String())
   119  	}
   120  
   121  	return nil
   122  }