...

Source file src/edge-infra.dev/pkg/tools/hack/cmd/owners/create.go

Documentation: edge-infra.dev/pkg/tools/hack/cmd/owners

     1  package owners
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/peterbourgon/ff/v3"
    11  	"github.com/peterbourgon/ff/v3/ffcli"
    12  	"gopkg.in/yaml.v2"
    13  
    14  	repoowners "edge-infra.dev/pkg/f8n/devinfra/repo/owners"
    15  )
    16  
    17  const (
    18  	pkg     = "pkg/"
    19  	cmd     = "cmd/"
    20  	pallets = "config/pallets/"
    21  )
    22  
    23  type arrayFlags []string
    24  
    25  func (i *arrayFlags) String() string {
    26  	return "list of strings"
    27  }
    28  
    29  func (i *arrayFlags) Set(value string) error {
    30  	*i = append(*i, value)
    31  	return nil
    32  }
    33  
    34  type create struct {
    35  	*owners
    36  
    37  	teams     arrayFlags
    38  	usernames arrayFlags
    39  	dirs      arrayFlags
    40  	pkg       bool
    41  	cmd       bool
    42  	pallets   bool
    43  }
    44  
    45  // hack owners create
    46  func newCreate(o *owners) *ffcli.Command {
    47  	c := &create{owners: o}
    48  
    49  	fs := flag.NewFlagSet("hack owners create", flag.ExitOnError)
    50  	c.owners.RegisterFlags(fs)
    51  
    52  	fs.Var(&c.teams, "team", "list of teams to add")
    53  	fs.Var(&c.usernames, "username", "list of usernames to add")
    54  	fs.Var(&c.dirs, "dir", "list of directories to create a new OWNERS file")
    55  
    56  	fs.BoolVar(&c.pkg, "pkg", false, "create the /pkg dir")
    57  	fs.BoolVar(&c.cmd, "cmd", false, "create the /cmd dir")
    58  	fs.BoolVar(&c.pallets, "pallets", false, "create the config/pallets dir")
    59  
    60  	return &ffcli.Command{
    61  		Name:    "create",
    62  		FlagSet: fs,
    63  		Exec:    c.Exec,
    64  		Options: []ff.Option{
    65  			ff.WithEnvVarNoPrefix(),
    66  		},
    67  	}
    68  }
    69  
    70  func (c *create) Exec(_ context.Context, _ []string) error {
    71  	// if there's no teams or users defined err
    72  	if len(c.teams) == 0 && len(c.usernames) == 0 {
    73  		return fmt.Errorf("a team or user must be defined")
    74  	}
    75  
    76  	// if there's no dir defined err
    77  	if len(c.dirs) == 0 {
    78  		return fmt.Errorf("a directory must be defined")
    79  	}
    80  
    81  	// get all the owners files that exist
    82  	_, ownersFiles, err := c.collectOwners()
    83  	if err != nil {
    84  		return fmt.Errorf("failed to collect OWNERS files: %w", err)
    85  	}
    86  
    87  	// if the user doesnt give the specific folder flag just assume the dir is the full path
    88  	if !c.pkg && !c.cmd && !c.pallets {
    89  		for _, dir := range c.dirs {
    90  			c.generateFile(dir, ownersFiles)
    91  		}
    92  		return c.update()
    93  	}
    94  
    95  	// create the new files
    96  	dir := c.dirs[0] // just grab the first dir
    97  	if len(c.dirs) > 1 {
    98  		fmt.Printf("⚠️ more than one dir was given but only %s will be used \n", dir)
    99  		fmt.Println("⚠️ drop the pkg, cmd, or pallet flag for all dirs to be created")
   100  	}
   101  
   102  	if c.pkg {
   103  		c.generateFile(filepath.Join(pkg, dir), ownersFiles)
   104  	}
   105  
   106  	if c.cmd {
   107  		c.generateFile(filepath.Join(cmd, dir), ownersFiles)
   108  	}
   109  
   110  	if c.pallets {
   111  		c.generateFile(filepath.Join(pallets, dir), ownersFiles)
   112  	}
   113  	return c.update()
   114  }
   115  
   116  // update the pbot file
   117  func (c *create) update() error {
   118  	u := &update{owners: c.owners}
   119  	d, err := u.generatePBotCfg()
   120  	if err != nil {
   121  		return err
   122  	}
   123  	return u.createFile(d)
   124  }
   125  
   126  func (c *create) generateFile(dir string, ownersFiles map[string]repoowners.File) {
   127  	// if the owner files does not already exist for the
   128  	// path create it
   129  	if _, ok := ownersFiles[dir]; !ok {
   130  		f := repoowners.DefaultFile(c.usernames, c.teams, dir)
   131  		fp := filepath.Join(c.Paths.RepoRoot, dir, repoowners.FileName)
   132  		fmt.Printf("✅ %s created \n", fp)
   133  		err := createPathAndFile(f, fp)
   134  		if err != nil {
   135  			fmt.Printf("failed to create file and path: %v", err)
   136  		}
   137  	} else {
   138  		fmt.Printf("〰️ %s already exists ignoring \n", dir)
   139  	}
   140  }
   141  
   142  func createPathAndFile(file *repoowners.File, path string) error {
   143  	if err := os.MkdirAll(filepath.Dir(path), 0770); err != nil {
   144  		return fmt.Errorf("Error creating dirs: %w", err)
   145  	}
   146  	_, err := os.Create(path)
   147  	if err != nil {
   148  		return fmt.Errorf("could not create file path: %w", err)
   149  	}
   150  
   151  	yamlData, err := yaml.Marshal(&file)
   152  	if err != nil {
   153  		return fmt.Errorf("Error while Marshaling: %w", err)
   154  	}
   155  
   156  	err = os.WriteFile(path, yamlData, 0644)
   157  	if err != nil {
   158  		return fmt.Errorf("unable to write data into the file: %w", err)
   159  	}
   160  	return nil
   161  }
   162  

View as plain text