gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/tools/github/main.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Binary github is the entry point for GitHub utilities. 16 package main 17 18 import ( 19 "context" 20 "flag" 21 "fmt" 22 "io/ioutil" 23 "log" 24 "os" 25 "strings" 26 27 "github.com/google/go-github/github" 28 "golang.org/x/oauth2" 29 "gvisor.dev/gvisor/tools/github/reviver" 30 ) 31 32 var ( 33 owner string 34 repo string 35 tokenFile string 36 paths stringList 37 commit string 38 dryRun bool 39 ) 40 41 type stringList []string 42 43 func (s *stringList) String() string { 44 return strings.Join(*s, ",") 45 } 46 47 func (s *stringList) Set(value string) error { 48 *s = append(*s, value) 49 return nil 50 } 51 52 // Keep the options simple for now. Supports only a single path and repo. 53 func init() { 54 flag.StringVar(&owner, "owner", "", "GitHub project org/owner") 55 flag.StringVar(&repo, "repo", "", "GitHub repo") 56 flag.StringVar(&tokenFile, "oauth-token-file", "", "file containing the GitHub token (or GITHUB_TOKEN is set)") 57 flag.Var(&paths, "path", "path(s) to scan (required for revive)") 58 flag.BoolVar(&dryRun, "dry-run", false, "just print changes to be made") 59 } 60 61 func filterPaths(paths []string) (existing []string) { 62 for _, path := range paths { 63 if _, err := os.Stat(path); err != nil { 64 log.Printf("WARNING: skipping %v: %v", path, err) 65 continue 66 } 67 existing = append(existing, path) 68 } 69 return 70 } 71 72 func main() { 73 // Set defaults from the environment. 74 repository := os.Getenv("GITHUB_REPOSITORY") 75 if parts := strings.SplitN(repository, "/", 2); len(parts) == 2 { 76 owner = parts[0] 77 repo = parts[1] 78 } 79 80 // Parse flags. 81 flag.Usage = func() { 82 fmt.Fprintf(flag.CommandLine.Output(), "usage: %s [options] <command>\n", os.Args[0]) 83 fmt.Fprintf(flag.CommandLine.Output(), "commands: revive, nogo\n") 84 flag.PrintDefaults() 85 } 86 flag.Parse() 87 args := flag.Args() 88 if len(args) != 1 { 89 fmt.Fprintf(flag.CommandLine.Output(), "extra arguments: %s\n", strings.Join(args[1:], ", ")) 90 flag.Usage() 91 os.Exit(1) 92 } 93 94 // Check for mandatory parameters. 95 command := args[0] 96 if len(owner) == 0 { 97 fmt.Fprintln(flag.CommandLine.Output(), "missing --owner option.") 98 flag.Usage() 99 os.Exit(1) 100 } 101 if len(repo) == 0 { 102 fmt.Fprintln(flag.CommandLine.Output(), "missing --repo option.") 103 flag.Usage() 104 os.Exit(1) 105 } 106 filteredPaths := filterPaths(paths) 107 if len(filteredPaths) == 0 { 108 fmt.Fprintln(flag.CommandLine.Output(), "no valid --path options provided.") 109 flag.Usage() 110 os.Exit(1) 111 } 112 113 // The access token may be passed as a file so it doesn't show up in 114 // command line arguments. It also may be provided through the 115 // environment to faciliate use through GitHub's CI system. 116 token := os.Getenv("GITHUB_TOKEN") 117 if len(tokenFile) != 0 { 118 bytes, err := ioutil.ReadFile(tokenFile) 119 if err != nil { 120 fmt.Println(err.Error()) 121 os.Exit(1) 122 } 123 token = string(bytes) 124 } 125 var client *github.Client 126 if len(token) == 0 { 127 // Client is unauthenticated. 128 client = github.NewClient(nil) 129 } else { 130 // Using the above token. 131 ts := oauth2.StaticTokenSource( 132 &oauth2.Token{AccessToken: token}, 133 ) 134 tc := oauth2.NewClient(context.Background(), ts) 135 client = github.NewClient(tc) 136 } 137 138 switch command { 139 case "revive": 140 // Load existing GitHub bugs. 141 bugger, err := reviver.NewGitHubBugger(client, owner, repo, dryRun) 142 if err != nil { 143 fmt.Fprintf(os.Stderr, "Error getting github issues: %v\n", err) 144 os.Exit(1) 145 } 146 // Scan the provided path. 147 rev := reviver.New(filteredPaths, []reviver.Bugger{bugger}) 148 if errs := rev.Run(); len(errs) > 0 { 149 fmt.Fprintf(os.Stderr, "Encountered %d errors:\n", len(errs)) 150 for _, err := range errs { 151 fmt.Fprintf(os.Stderr, "\t%v\n", err) 152 } 153 os.Exit(1) 154 } 155 default: 156 // Not a known command. 157 fmt.Fprintf(flag.CommandLine.Output(), "unknown command: %s\n", command) 158 flag.Usage() 159 os.Exit(1) 160 } 161 }