github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/generic-autobumper/updater/updater.go (about)

     1  /*
     2  Copyright 2019 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 updater handles creation and updates of GitHub PullRequests.
    18  package updater
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"github.com/sirupsen/logrus"
    24  
    25  	"sigs.k8s.io/prow/pkg/github"
    26  )
    27  
    28  // Indicates whether maintainers can modify a pull request in fork.
    29  const (
    30  	AllowMods   = true
    31  	PreventMods = false
    32  )
    33  
    34  type updateClient interface {
    35  	UpdatePullRequest(org, repo string, number int, title, body *string, open *bool, branch *string, canModify *bool) error
    36  	BotUser() (*github.UserData, error)
    37  	FindIssues(query, sort string, asc bool) ([]github.Issue, error)
    38  }
    39  
    40  type ensureClient interface {
    41  	updateClient
    42  	AddLabel(org, repo string, number int, label string) error
    43  	CreatePullRequest(org, repo, title, body, head, base string, canModify bool) (int, error)
    44  	GetIssue(org, repo string, number int) (*github.Issue, error)
    45  }
    46  
    47  func EnsurePRWithQueryTokens(org, repo, title, body, source, baseBranch, queryTokensString string, allowMods bool, gc ensureClient) (*int, error) {
    48  	n, err := updatePRWithQueryTokens(org, repo, title, body, queryTokensString, gc)
    49  	if err != nil {
    50  		return nil, fmt.Errorf("update error: %w", err)
    51  	}
    52  	if n == nil {
    53  		pr, err := gc.CreatePullRequest(org, repo, title, body, source, baseBranch, allowMods)
    54  		if err != nil {
    55  			return nil, fmt.Errorf("create error: %w", err)
    56  		}
    57  		n = &pr
    58  	}
    59  
    60  	return n, nil
    61  }
    62  
    63  func updatePRWithQueryTokens(org, repo, title, body, queryTokensString string, gc updateClient) (*int, error) {
    64  	logrus.Info("Looking for a PR to reuse...")
    65  	me, err := gc.BotUser()
    66  	if err != nil {
    67  		return nil, fmt.Errorf("bot name: %w", err)
    68  	}
    69  
    70  	issues, err := gc.FindIssues(fmt.Sprintf("is:open is:pr archived:false repo:%s/%s author:%s %s", org, repo, me.Login, queryTokensString), "updated", false)
    71  	if err != nil {
    72  		return nil, fmt.Errorf("find issues: %w", err)
    73  	} else if len(issues) == 0 {
    74  		logrus.Info("No reusable issues found")
    75  		return nil, nil
    76  	}
    77  	n := issues[0].Number
    78  	logrus.Infof("Found %d", n)
    79  	var ignoreOpen *bool
    80  	var ignoreBranch *string
    81  	var ignoreModify *bool
    82  	if err := gc.UpdatePullRequest(org, repo, n, &title, &body, ignoreOpen, ignoreBranch, ignoreModify); err != nil {
    83  		return nil, fmt.Errorf("update %d: %w", n, err)
    84  	}
    85  
    86  	return &n, nil
    87  }
    88  
    89  func EnsurePRWithLabels(org, repo, title, body, source, baseBranch, headBranch string, allowMods bool, gc ensureClient, labels []string) (*int, error) {
    90  	return EnsurePRWithQueryTokensAndLabels(org, repo, title, body, source, baseBranch, "head:"+headBranch, allowMods, labels, gc)
    91  }
    92  
    93  func EnsurePRWithQueryTokensAndLabels(org, repo, title, body, source, baseBranch, queryTokensString string, allowMods bool, labels []string, gc ensureClient) (*int, error) {
    94  	n, err := EnsurePRWithQueryTokens(org, repo, title, body, source, baseBranch, queryTokensString, allowMods, gc)
    95  	if err != nil {
    96  		return n, err
    97  	}
    98  
    99  	if len(labels) == 0 {
   100  		return n, nil
   101  	}
   102  
   103  	issue, err := gc.GetIssue(org, repo, *n)
   104  	if err != nil {
   105  		return n, fmt.Errorf("failed to get PR: %w", err)
   106  	}
   107  
   108  	for _, label := range labels {
   109  		if issue.HasLabel(label) {
   110  			continue
   111  		}
   112  
   113  		if err := gc.AddLabel(org, repo, *n, label); err != nil {
   114  			return n, fmt.Errorf("failed to add label %q: %w", label, err)
   115  		}
   116  		logrus.WithField("label", label).Info("Added label")
   117  	}
   118  	return n, nil
   119  }