in cmd/publishing-bot/main.go [47:214]
func main() {
configFilePath := flag.String("config", "", "the config file in yaml format")
githubHost := flag.String("github-host", "", "the address of github (defaults to github.com)")
basePackage := flag.String("base-package", "", "the name of the package base (defaults to k8s.io when source repo is kubernetes, "+
"otherwise github-host/target-org)")
dryRun := flag.Bool("dry-run", false, "do not push anything to github")
tokenFile := flag.String("token-file", "", "the file with the github token")
rulesFile := flag.String("rules-file", "", "the file or URL with repository rules")
// TODO: make absolute
repoName := flag.String("source-repo", "", "the name of the source repository (eg. kubernetes)")
repoOrg := flag.String("source-org", "", "the name of the source repository organization, (eg. kubernetes)")
targetOrg := flag.String("target-org", "", `the target organization to publish into (e.g. "k8s-publishing-bot")`)
basePublishScriptPath := flag.String("base-publish-script-path", "./publish_scripts", `the base path in source repo where bot will look for publishing scripts`)
interval := flag.Uint("interval", 0, "loop with the given seconds of wait in between")
serverPort := flag.Int("server-port", 0, "start a webserver on the given port listening on 0.0.0.0")
flag.Usage = Usage
flag.Parse()
cfg := config.Config{}
if *configFilePath != "" {
bs, err := ioutil.ReadFile(*configFilePath)
if err != nil {
glog.Fatalf("Failed to load config file from %q: %v", *configFilePath, err)
}
if err := yaml.Unmarshal(bs, &cfg); err != nil {
glog.Fatalf("Failed to parse config file at %q: %v", *configFilePath, err)
}
}
// override with flags
if *dryRun {
cfg.DryRun = true
}
if *targetOrg != "" {
cfg.TargetOrg = *targetOrg
}
if *repoName != "" {
cfg.SourceRepo = *repoName
}
if *repoOrg != "" {
cfg.SourceOrg = *repoOrg
}
if *tokenFile != "" {
cfg.TokenFile = *tokenFile
}
if *rulesFile != "" {
cfg.RulesFile = *rulesFile
}
if *basePublishScriptPath != "" {
cfg.BasePublishScriptPath = *basePublishScriptPath
}
if *githubHost != "" {
cfg.GithubHost = *githubHost
}
if *basePackage != "" {
cfg.BasePackage = *basePackage
}
// defaulting to github.com when it is not specified.
if cfg.GithubHost == "" {
cfg.GithubHost = "github.com"
}
var err error
cfg.BasePublishScriptPath, err = filepath.Abs(cfg.BasePublishScriptPath)
if err != nil {
glog.Fatalf("Failed to get absolute path for base-publish-script-path %q: %v", cfg.BasePublishScriptPath, err)
}
if cfg.SourceRepo == "" || cfg.SourceOrg == "" {
glog.Fatalf("source-org and source-repo cannot be empty")
}
if cfg.TargetOrg == "" {
glog.Fatalf("Target organization cannot be empty")
}
// set the baseRepoPath
gopath := os.Getenv("GOPATH")
// defaulting when base package is not specified
if cfg.BasePackage == "" {
if cfg.SourceRepo == "kubernetes" {
cfg.BasePackage = "k8s.io"
} else {
cfg.BasePackage = filepath.Join(cfg.GithubHost, cfg.TargetOrg)
}
}
baseRepoPath := fmt.Sprintf("%s/%s/%s", gopath, "src", cfg.BasePackage)
// If RULE_FILE_PATH is detected, check if the source repository include rules files.
if len(os.Getenv("RULE_FILE_PATH")) > 0 {
cfg.RulesFile = filepath.Join(baseRepoPath, cfg.SourceRepo, os.Getenv("RULE_FILE_PATH"))
}
if cfg.RulesFile == "" {
glog.Fatalf("No rules file provided")
}
runChan := make(chan bool, 1)
// start server
server := Server{
Issue: cfg.GithubIssue,
config: cfg,
RunChan: runChan,
}
if *serverPort != 0 {
if err := server.Run(*serverPort); err != nil {
glog.Fatalf("Failed to run healthz server: %v", err)
}
}
githubIssueErrorf := glog.Fatalf
if *interval != 0 {
githubIssueErrorf = glog.Errorf
}
for {
waitfor := *interval
last := time.Now()
publisher := New(&cfg, baseRepoPath)
if cfg.TokenFile != "" && cfg.GithubIssue != 0 && !cfg.DryRun {
// load token
bs, err := ioutil.ReadFile(cfg.TokenFile)
if err != nil {
glog.Fatalf("Failed to load token file from %q: %v", cfg.TokenFile, err)
}
token := strings.Trim(string(bs), " \t\n")
// run
logs, hash, err := publisher.Run()
server.SetHealth(err == nil, hash)
if err != nil {
glog.Infof("Failed to run publisher: %v", err)
if err := ReportOnIssue(err, logs, token, cfg.TargetOrg, cfg.SourceRepo, cfg.GithubIssue); err != nil {
githubIssueErrorf("Failed to report logs on github issue: %v", err)
server.SetHealth(false, hash)
}
if strings.HasSuffix(err.Error(), memory.ErrRefHasChanged.Error()) {
// TODO: If the issue is just "reference has changed concurrently",
// then let us wait for 5 minutes and try again. We really need to dig
// into the problem and fix the flakiness
glog.Infof("Waiting for 5 minutes")
waitfor = uint(5 * 60)
}
} else if err := CloseIssue(token, cfg.TargetOrg, cfg.SourceRepo, cfg.GithubIssue); err != nil {
githubIssueErrorf("Failed to close issue: %v", err)
server.SetHealth(false, hash)
}
} else {
// run
if _, _, err := publisher.Run(); err != nil {
glog.Infof("Failed to run publisher: %v", err)
}
}
if *interval == 0 {
break
}
select {
case <-runChan:
case <-time.After(time.Duration(int(waitfor)-int(time.Since(last).Seconds())) * time.Second):
}
}
}