diff options
| -rw-r--r-- | argv.go | 6 | ||||
| -rw-r--r-- | doPublish.go | 41 | ||||
| -rw-r--r-- | doRelease.go | 244 | ||||
| -rw-r--r-- | findNext.go | 86 |
4 files changed, 370 insertions, 7 deletions
@@ -82,9 +82,9 @@ type UpgradeCmd struct { } type PublishCmd struct { - Protobuf bool `arg:"--protobuf" help:"force all protobufs to be republished"` - Doit bool `arg:"--doit" help:"actually publish"` - // Gomod bool `arg:"--keep-gomod" help:"don't really do anything"` + Protobuf bool `arg:"--protobuf" help:"force all protobufs to be republished"` + Doit bool `arg:"--doit" help:"actually publish"` + KeepGomod bool `arg:"--keep-gomod" help:"don't really do anything"` } type InstallCmd struct { diff --git a/doPublish.go b/doPublish.go index efa8af2..9b11ddd 100644 --- a/doPublish.go +++ b/doPublish.go @@ -9,6 +9,7 @@ import ( "go.wit.com/lib/env" "go.wit.com/lib/protobuf/argvpb" + "go.wit.com/log" ) func doPublish() error { @@ -16,11 +17,43 @@ func doPublish() error { // publish := me.forge.RunOnReposNewDumb(me.forge.Repos, rePrepareReleaseNew) // doesn't use Rill() publish := me.forge.RunOnReposNew(me.forge.Repos, rePrepareReleaseNew) - if publish != nil { - publish = publish.SortActual() - footer := publish.PrintPublishNewTB() - fmt.Printf("publish.len(%d) PrintPublishTable() footer: %s\n", publish.Len(), footer) + if publish == nil { + return errors.New("nothing to publish. you actually have to write code first") } + + for repo := range publish.IterAll() { + // update the target version + // repo.IncrementTargetMinor() + repo.IncrementTargetRevision() + } + + publish = publish.SortActual() + footer := publish.PrintPublishNewTB() + fmt.Printf("publish.len(%d) PrintPublishTable() footer: %s\n", publish.Len(), footer) + + tryme := findNext(publish) + if len(tryme) == 0 { + return errors.New("can't find something safe to publish") + } + + startRepo := me.forge.Repos.FindByNamespace("go.wit.com/lib/xgb") + if startRepo == nil { + return errors.New("a startRepo can't be found") + } + + releaseReason := "new attempt" + + for i, repo := range tryme { + log.Info("tryme:", i, repo.FullPath) + if env.True("--doit") { + err := doRelease(repo, startRepo, releaseReason) + if err != nil { + return err + } + } + log.Printf("WOULD HAVE RUN: doRelease(%s, %s, %s) %s\n", repo.Namespace, startRepo.Namespace, releaseReason, repo.GetTargetVersion()) + } + if !env.True("--doit") { return errors.New("run with --doit to actually try to publish") } diff --git a/doRelease.go b/doRelease.go new file mode 100644 index 0000000..d5a203c --- /dev/null +++ b/doRelease.go @@ -0,0 +1,244 @@ +// This is a simple example +package main + +import ( + "errors" + "fmt" + "os" + "strings" + "time" + + "go.wit.com/lib/gui/shell" + "go.wit.com/lib/protobuf/argvpb" + "go.wit.com/lib/protobuf/gitpb" + "go.wit.com/log" +) + +func doRelease(current *gitpb.Repo, startRepo *gitpb.Repo, releaseReason string) error { + releaseVersion := current.GetTargetVersion() + log.Info("doRelease() on", current.GetGoPath(), releaseVersion) + // double check release version logic + + if shell.Exists("go.mod") { + log.Info("go.mod exists ok") + } else { + pwd, _ := os.Getwd() + log.Info("go.mod missing in working dir", pwd) + return fmt.Errorf("go.mod missing %s", current.GetGoPath()) + } + + curName := current.GetCurrentBranchName() + mName := current.GetMasterBranchName() + if curName != mName { + log.Info("\trepo is not working from main branch", curName, "!=", mName) + return fmt.Errorf("not on main branch %s", current.GetGoPath()) + } + + // check if the git tag already exists somehow + testtag := releaseVersion + if t := current.IfRefExists(testtag); t != nil { + log.Info("TAG ALREADY EXISTS", testtag) + return log.Errorf("%s TAG ALREADY EXISTS %s", current.FullPath, testtag) + } else { + log.Info("TAG IS NEW", testtag) + } + + if me.forge.Config.IsPrivate(current.GetGoPath()) { + // do not self update private repos + log.Info("This is a private repo.") + var retag [][]string + retag = append(retag, []string{"git", "tag", "-m", releaseReason, releaseVersion}) + retag = append(retag, []string{"git", "push", "origin", releaseVersion}) + if !current.RunAll(retag) { + log.Info("retag failed") + return fmt.Errorf("RETAG FAILED %s", current.GetGoPath()) + } + return nil + } + // me.done = append(me.done, current.GetGoPath()) + if err := finalGoDepsCheckOk(current); err != nil { + msg := fmt.Sprint("the go.mod file is wrong. fix it here?", current.GetGoPath()) + return errors.New(msg) + } + if current.GetGoPath() == startRepo.GetGoPath() { + log.Info("CAN NOT SELF UPDATE.", current.GetGoPath(), "is the same as os.Getwd()") + log.Info("go get must be run from somewhere else other than startRepo") + log.Info("chdir to autotypist if it exists") + msg := fmt.Sprint("CAN NOT SELF UPDATE.", current.GetGoPath(), "is the same as os.Getwd()") + return errors.New(msg) + } + if !startRepo.Exists("go.mod") { + log.Info("go.sum missing in", startRepo.GetGoPath()) + log.Info("pick a different repo here") + log.Info("todo: error out earlier knowing this will upgrade") + log.Info("versions", startRepo.GetTargetVersion(), startRepo.GetMasterVersion()) + panic("redo go.sum") + } + + log.Info("\ttag and push", curName, releaseVersion, releaseReason) + + if err := current.ValidGoSum(); err != nil { + log.Info("ValidGoSum() error", current.GetGoPath(), err) + msg := fmt.Sprint("ValidGoSum() error", current.GetGoPath(), err) + return errors.New(msg) + } + + // TODO: re-add this and double check again (?) + // _, err := current.RunVerboseOnError([]string{"go-mod-clean", "strict"}) + // if err != nil { + // return err + // } + + var all [][]string + var autogen []string + all = append(all, []string{"git", "add", "-f", "go.mod"}) + autogen = append(autogen, "go.mod") + if current.GoInfo.GoPrimitive { + // don't add go.sum here. TODO: check for go.sum file and fail + } else { + all = append(all, []string{"git", "add", "-f", "go.sum"}) + autogen = append(autogen, "go.sum") + } + if ok, compiled, err := current.ScanProtobuf(); ok { + log.Info("\tIsProtobuf() == true") + if err != nil { + log.Info("\tERROR: There are protobuf files, but they are not compiled") + log.Info("\tERROR: can not continue") + msg := fmt.Sprint("ERROR: There are protobuf files, but they are not compiled") + return errors.New(msg) + } + log.Info("\tshould add the protobuf files here") + log.Info("\tcompiled files found:", compiled) + for _, s := range compiled { + log.Info("\tcompiled file found:", s) + all = append(all, []string{"git", "add", "-f", s}) + autogen = append(autogen, s) + } + } else { + log.Info("\tIsProtobuf() == false") + } + all = append(all, []string{"git", "commit", "-m", releaseReason}) + all = append(all, []string{"git", "push"}) + all = append(all, []string{"git", "tag", "-m", releaseReason, releaseVersion}) + all = append(all, []string{"git", "push", "origin", releaseVersion}) + + // save the autogenerated files in git metadata (aka: notes) + cname := current.GetCurrentBranchName() + if err := current.AutogenSave(autogen, cname, true); err != nil { + log.Info("AutogenSave() error", err) + msg := fmt.Sprint("AutogenSave() error", err) + return errors.New(msg) + } + + if !current.RunAll(all) { + log.Info("failed to make new release", releaseVersion) + return fmt.Errorf("setting findOK = false %s", current.GetGoPath()) + } + log.Info("RELEASE OK") + + // 'publish' the version to the golang package versioning system + if err := doPublishVersion(current, startRepo, releaseVersion); err != nil { + time.Sleep(3 * time.Second) + // this can fail to update, try it again after sleep(3s) + if err := doPublishVersion(current, startRepo, releaseVersion); err != nil { + log.Info("PUBLISH FAILED gopath=%s", current.GetGoPath()) + return err + } + } + + log.Info("PUBLISH OK") + // current.SetGoState("RELEASED") + + if argv.Publish.KeepGomod { + log.Info("TRY THE CRAZY THING HERE") + + // delete tag + var retag [][]string + retag = append(retag, []string{"git", "tag", "--delete", releaseVersion}) + retag = append(retag, []string{"git", "push", "--delete", "origin", releaseVersion}) + if !current.RunAll(retag) { + log.Info("delete failed") + argvpb.BadExit("--keep-gomod testing", fmt.Errorf("DELETE TAG FAILED %s", current.GetGoPath())) + } + + // switch to devel branch ? + if current.CheckoutDevel() { + // ok? + } else { + // holy crap. die here + argvpb.BadExit("CheckoutDevel() failed", nil) + } + retag = append(retag, []string{"git", "tag", "-m", releaseReason, releaseVersion}) + retag = append(retag, []string{"git", "push", "origin", releaseVersion}) + + if !current.RunAll(retag) { + log.Info("retag failed") + argvpb.BadExit("--keep-gomod testing", fmt.Errorf("RETAG FAILED %s", current.GetGoPath())) + } + argvpb.BadExit("did --keep-gomod work?", nil) // MUST FAIL HERE + } else { + // unwind and re-tag. Now that the go.mod and go.sum are published, revert + // to the development branch + if !current.RevertMasterToDevel() { + log.Info("Revert Failed") + return fmt.Errorf("REVERT FAILED %s", current.GetGoPath()) + } + + // update tag + var retag [][]string + retag = append(retag, []string{"git", "tag", "--delete", releaseVersion}) + retag = append(retag, []string{"git", "push", "--delete", "origin", releaseVersion}) + retag = append(retag, []string{"git", "tag", "-m", releaseReason, releaseVersion}) + retag = append(retag, []string{"git", "push", "origin", releaseVersion}) + + if !current.RunAll(retag) { + log.Info("retag failed") + return fmt.Errorf("RETAG FAILED %s", current.GetGoPath()) + } + } + log.Info("EVERYTHING OK. RERELEASED", current.GetGoPath()) + + return nil +} + +// this pulls the new tag from the golang package repository +// to insert the new version +func doPublishVersion(current *gitpb.Repo, startRepo *gitpb.Repo, releaseVersion string) error { + gopath := current.GetGoPath() + docmd := []string{"go", "get", "-v", gopath + "@" + releaseVersion} + log.Info("SHOULD RUN cmd HERE:", docmd) + + if me.forge.Config.IsPrivate(current.GetGoPath()) { + // do not self update private repos + return errors.New("This is a private repo and can not be self checked") + } + + // try to pull from google + if gopath == startRepo.GetGoPath() { + log.Info("CAN NOT SELF UPDATE. cmd =", docmd) + log.Info("go get must be run from somewhere else other than startRepo") + log.Info("chdir to autotypist if it exists") + msg := fmt.Sprint("CAN NOT SELF UPDATE. cmd =", docmd) + return errors.New(msg) + } + // publish go.mod & go.sum for use with go + os.Unsetenv("GO111MODULE") + log.Info("TRYING TO SELF UPDATE HERE. cmd =", docmd) + result := startRepo.Run(docmd) + + if result.Error != nil { + log.Info("SELF UPDATE FAILED. error =", result.Error) + log.Info("SELF UPDATE FAILED. exit =", result.Exit) + log.Info("SELF UPDATE FAILED. out =", result.Stdout) + return errors.New("SELF UPDATE FAILED") + } + if result.Exit != 0 { + log.Info("SELF UPDATE FAILED. error =", result.Error) + log.Info("SELF UPDATE FAILED. exit =", result.Exit) + log.Info("SELF UPDATE FAILED. out =", result.Stdout) + return errors.New("SELF UPDATE FAILED") + } + log.Info("SELF UPDATE OK. out =", strings.Join(result.Stdout, "\n")) + log.Info("SELF UPDATE WORKED") + return nil +} diff --git a/findNext.go b/findNext.go new file mode 100644 index 0000000..b1c23f9 --- /dev/null +++ b/findNext.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "os" + + "go.wit.com/log" + + "go.wit.com/lib/cobol" + "go.wit.com/lib/protobuf/gitpb" +) + +// trys to figure out if there is still something to update +// todo: redo this logic as it is terrible +// rename this findNext() +func findNext(found *gitpb.Repos) []*gitpb.Repo { + var trythese []*gitpb.Repo + // findCounter = 0 + var simpletable [][]string + simpletable = append(simpletable, []string{"namespace", "function", "err reason"}) + for check := range found.IterAll() { + if check.GetMasterBranchName() != check.GetCurrentBranchName() { + log.Info("FIND NEXT: YOU MUST BE ON THE MASTER BRANCH", check.GetNamespace()) + continue + } + if check.IsDirty() { + // log.Info("FIND NEXT: CAN NOT RELEASE DIRTY REPO", check.GetNamespace()) + simpletable = append(simpletable, []string{check.GetNamespace(), "CAN NOT RELEASE DIRTY REPO"}) + continue + } + /* + if alreadyDone(check) { + log.Info("FIND NEXT: findNext() alreadyDone. WHY IS THIS STILL CHECKING?", check.GetNamespace()) + continue + } + */ + // log.Info("FIND NEXT: CHECKING START:", check.GetNamespace()) + + if me.forge.Config.IsPrivate(check.GetNamespace()) { + log.Info("FIND NEXT: GOOD TO GO ON PRIVATE REPO", check.GetNamespace()) + trythese = append(trythese, check) + continue + } + + godepsNew, err := check.GoSumFromRepo() + if err != nil { + errs := fmt.Sprintf("%v", err) + simpletable = append(simpletable, []string{check.GetNamespace(), "check.GoSumFromRepo()", errs}) + continue + + } + if godepsNew == nil { + // don't check godepsNew, but check to make sure go mod tidy actually ran without error + os.Unsetenv("GO111MODULE") + cmd := []string{"go", "mod", "tidy"} + err := check.RunVerbose(cmd) + if err != nil { + log.Info("FIND NEXT: go mod tidy failed. this go package needs to be examined by hand as it doesn't appear to be primitive") + log.Info("FIND NEXT:", check.FullPath, cmd) + os.Exit(-1) + } + // if godepsNew == nil, then this go package is a primitive and there is no go.sum file + } else { + if err := testGoDepsCheckOk(godepsNew); err != nil { + log.Info("FIND NEXT: CHECKING current repo deps failed", err) + continue + } + } + + if err := finalGoDepsCheckOk(check); err != nil { + // if err := me.forge.FinalGoDepsCheckOk(check, false); err != nil { + // log.Info("FIND NEXT: FinalGoDepsCheckOk() repo=", check.GetNamespace(), "err:", err) + // log.Info("FIND NEXT: CHECKING END:", check.GetNamespace()) + // log.Info("FIND NEXT: ") + simpletable = append(simpletable, []string{check.GetNamespace(), fmt.Sprintf("FinalGoDepsCheckOk() err(%v)", err)}) + continue + } + log.Info("FIND NEXT: GOOD TO GO ON", check.GetNamespace()) + // setCurrentRepo(check, "should be good to release", "pretty sure") + trythese = append(trythese, check) + } + + footer := cobol.SimpleTable(simpletable) + log.Info("reasons against publishing:", footer) + return trythese +} |
