sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/cmd/invitations-accepter/main.go (about)

     1  /*
     2  Copyright 2021 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 main
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"os"
    23  
    24  	"github.com/sirupsen/logrus"
    25  
    26  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    27  
    28  	"sigs.k8s.io/prow/pkg/flagutil"
    29  	"sigs.k8s.io/prow/pkg/github"
    30  )
    31  
    32  const (
    33  	defaultTokens = 300
    34  	defaultBurst  = 300
    35  )
    36  
    37  type options struct {
    38  	github flagutil.GitHubOptions
    39  
    40  	dryRun bool
    41  }
    42  
    43  type githubClient interface {
    44  	ListCurrentUserRepoInvitations() ([]github.UserRepoInvitation, error)
    45  	AcceptUserRepoInvitation(invitationID int) error
    46  	ListCurrentUserOrgInvitations() ([]github.UserOrgInvitation, error)
    47  	AcceptUserOrgInvitation(org string) error
    48  	BotUser() (*github.UserData, error)
    49  }
    50  
    51  func gatherOptions() options {
    52  	o := options{}
    53  	fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
    54  
    55  	fs.BoolVar(&o.dryRun, "dry-run", true, "Dry run for testing. Uses API tokens but does not mutate.")
    56  
    57  	o.github.AddCustomizedFlags(fs, flagutil.ThrottlerDefaults(defaultTokens, defaultBurst))
    58  	if err := fs.Parse(os.Args[1:]); err != nil {
    59  		logrus.WithError(err).Fatal("could not parse input")
    60  	}
    61  	return o
    62  }
    63  
    64  func (o *options) Validate() error {
    65  	return o.github.Validate(o.dryRun)
    66  }
    67  
    68  func main() {
    69  	o := gatherOptions()
    70  
    71  	gc, err := o.github.GitHubClient(o.dryRun)
    72  	if err != nil {
    73  		logrus.WithError(err).Fatal("Error getting GitHub client.")
    74  	}
    75  
    76  	if err := acceptInvitations(gc, o.dryRun); err != nil {
    77  		logrus.WithError(err).Fatal("Errors occurred.")
    78  	}
    79  }
    80  
    81  func acceptInvitations(gc githubClient, dryRun bool) error {
    82  	var errs []error
    83  
    84  	botUser, err := gc.BotUser()
    85  	if err != nil {
    86  		return fmt.Errorf("couldn't get bot's user name: %w", err)
    87  	}
    88  
    89  	logger := logrus.WithField("bot-user", botUser.Login)
    90  
    91  	if err := acceptOrgInvitations(gc, dryRun, logger); err != nil {
    92  		errs = append(errs, err)
    93  	}
    94  
    95  	if err := acceptRepoInvitations(gc, dryRun, logger); err != nil {
    96  		errs = append(errs, err)
    97  	}
    98  
    99  	return utilerrors.NewAggregate(errs)
   100  }
   101  
   102  func acceptOrgInvitations(gc githubClient, dryRun bool, logger *logrus.Entry) error {
   103  	var errs []error
   104  
   105  	orgInvitations, err := gc.ListCurrentUserOrgInvitations()
   106  	if err != nil {
   107  		return fmt.Errorf("couldn't get org invitations for the authenticated user: %w", err)
   108  	}
   109  
   110  	for _, inv := range orgInvitations {
   111  		org := inv.Org.Login
   112  		orgLogger := logger.WithField("org", org)
   113  		if dryRun {
   114  			orgLogger.Info("(dry-run) Accepting organization invitation.")
   115  		} else {
   116  			orgLogger.Info("Accepting organization invitation.")
   117  			errs = append(errs, gc.AcceptUserOrgInvitation(org))
   118  		}
   119  	}
   120  	return utilerrors.NewAggregate(errs)
   121  
   122  }
   123  
   124  func acceptRepoInvitations(gc githubClient, dryRun bool, logger *logrus.Entry) error {
   125  	var errs []error
   126  
   127  	repoInvitations, err := gc.ListCurrentUserRepoInvitations()
   128  	if err != nil {
   129  		return fmt.Errorf("couldn't get repo invitations for the authenticated user: %w", err)
   130  	}
   131  
   132  	for _, inv := range repoInvitations {
   133  		repoLogger := logger.WithFields(logrus.Fields{"invitation-id": inv.InvitationID, "repo": inv.Repository.FullName})
   134  		if dryRun {
   135  			repoLogger.Info("(dry-run) Accepting repository invitation.")
   136  		} else {
   137  			repoLogger.Info("Accepting repository invitation.")
   138  			errs = append(errs, gc.AcceptUserRepoInvitation(inv.InvitationID))
   139  		}
   140  	}
   141  	return utilerrors.NewAggregate(errs)
   142  }