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 }