github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/plugins/testfreeze/testfreeze.go (about)

     1  /*
     2  Copyright 2022 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 testfreeze
    18  
    19  import (
    20  	"fmt"
    21  	"html/template"
    22  	"strings"
    23  	"time"
    24  
    25  	"github.com/sirupsen/logrus"
    26  
    27  	"sigs.k8s.io/prow/pkg/config"
    28  	"sigs.k8s.io/prow/pkg/github"
    29  	"sigs.k8s.io/prow/pkg/pluginhelp"
    30  	"sigs.k8s.io/prow/pkg/plugins"
    31  	"sigs.k8s.io/prow/pkg/plugins/testfreeze/checker"
    32  )
    33  
    34  const (
    35  	PluginName                  = "testfreeze"
    36  	defaultKubernetesBranch     = "master"
    37  	defaultKubernetesRepoAndOrg = "kubernetes"
    38  	templateString              = `Please note that we're already in [Test Freeze](https://github.com/kubernetes/sig-release/blob/master/releases/release_phases.md#test-freeze) for the ` + "`{{ .Branch }}`" + ` branch. This means every merged PR will be automatically fast-forwarded via the periodic [ci-fast-forward](https://testgrid.k8s.io/sig-release-releng-blocking#git-repo-kubernetes-fast-forward) job to the release branch of the upcoming {{ .Tag }} release.
    39  
    40  Fast forwards are scheduled to happen every 6 hours, whereas the most recent run was: {{ .LastFastForward }}.
    41  `
    42  )
    43  
    44  func init() {
    45  	plugins.RegisterPullRequestHandler(PluginName, handlePullRequestEvent, helpProvider)
    46  }
    47  
    48  func helpProvider(*plugins.Configuration, []config.OrgRepo) (*pluginhelp.PluginHelp, error) {
    49  	return &pluginhelp.PluginHelp{
    50  		Description: fmt.Sprintf(
    51  			"The %s plugin adds additional documentation about cherry-picks during the Test Freeze period.",
    52  			PluginName,
    53  		),
    54  	}, nil
    55  }
    56  
    57  func handlePullRequestEvent(p plugins.Agent, e github.PullRequestEvent) error {
    58  	h := newHandler()
    59  	log := p.Logger
    60  	if err := h.handle(
    61  		log,
    62  		p.GitHubClient,
    63  		e.Action,
    64  		e.Number,
    65  		e.Repo.Owner.Login,
    66  		e.Repo.Name,
    67  		e.PullRequest.Base.Ref,
    68  	); err != nil {
    69  		log.WithError(err).Error("skipping")
    70  	}
    71  	return nil
    72  }
    73  
    74  type handler struct {
    75  	verifier verifier
    76  }
    77  
    78  func newHandler() *handler {
    79  	return &handler{
    80  		verifier: &defaultVerifier{},
    81  	}
    82  }
    83  
    84  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
    85  //counterfeiter:generate . verifier
    86  type verifier interface {
    87  	CheckInTestFreeze(*logrus.Entry) (*checker.Result, error)
    88  	CreateComment(plugins.PluginGitHubClient, string, string, int, string) error
    89  }
    90  
    91  type defaultVerifier struct{}
    92  
    93  func (*defaultVerifier) CheckInTestFreeze(log *logrus.Entry) (*checker.Result, error) {
    94  	return checker.New(log).InTestFreeze()
    95  }
    96  
    97  func (*defaultVerifier) CreateComment(
    98  	client plugins.PluginGitHubClient,
    99  	org, repo string,
   100  	number int,
   101  	comment string,
   102  ) error {
   103  	return client.CreateComment(org, repo, number, comment)
   104  }
   105  
   106  func (h *handler) handle(
   107  	log *logrus.Entry,
   108  	client plugins.PluginGitHubClient,
   109  	action github.PullRequestEventAction,
   110  	number int,
   111  	org, repo, branch string,
   112  ) error {
   113  	funcStart := time.Now()
   114  	defer func() {
   115  		log.WithField("duration", time.Since(funcStart).String()).
   116  			Debug("Completed handlePullRequest")
   117  	}()
   118  
   119  	if action != github.PullRequestActionOpened &&
   120  		action != github.PullRequestActionReopened {
   121  		log.Debugf("Skipping pull request action %s", action)
   122  		return nil
   123  	}
   124  
   125  	if org != defaultKubernetesRepoAndOrg ||
   126  		repo != defaultKubernetesRepoAndOrg ||
   127  		branch != defaultKubernetesBranch {
   128  		log.Debug("Skipping non k/k master branch PR")
   129  		return nil
   130  	}
   131  
   132  	result, err := h.verifier.CheckInTestFreeze(log)
   133  	if err != nil {
   134  		return fmt.Errorf("get test freeze result: %w", err)
   135  	}
   136  
   137  	if !result.InTestFreeze {
   138  		log.Debugf("Not in test freeze, skipping")
   139  		return nil
   140  	}
   141  
   142  	comment := &strings.Builder{}
   143  	tpl, err := template.New(PluginName).Parse(templateString)
   144  	if err != nil {
   145  		return fmt.Errorf("parse template: %w", err)
   146  	}
   147  	if err := tpl.Execute(comment, result); err != nil {
   148  		return fmt.Errorf("execute template: %w", err)
   149  	}
   150  
   151  	if err := h.verifier.CreateComment(
   152  		client, org, repo, number, comment.String(),
   153  	); err != nil {
   154  		return fmt.Errorf("create comment on %s/%s#%d: %q: %w", org, repo, number, comment, err)
   155  	}
   156  
   157  	return nil
   158  }