guireleaser/doRelease.go

270 lines
9.4 KiB
Go

// This is a simple example
package main
import (
"errors"
"fmt"
"os"
"strings"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func doRelease() error {
check := me.current
log.Info("doRelease() on", me.current.GetGoPath())
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
return fmt.Errorf("findOK = false %s", check.GetGoPath())
}
// double check release version logic
if me.release.releaseVersionB.String() != "release version "+me.release.version.String() {
log.Warn("something went wrong with the release.version:", me.release.version.String())
return fmt.Errorf("GUI lied %s", check.GetGoPath())
}
if strings.HasPrefix(me.release.version.String(), "v") {
log.Warn("everything is ok. version starts with v.", me.release.version.String())
} else {
log.Warn("version does not start with v.", me.release.version.String())
return fmt.Errorf("release does not start with a v %s", check.GetGoPath())
}
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", check.GetGoPath())
}
curName := me.current.GetCurrentBranchName()
mName := me.current.GetMasterBranchName()
if curName != mName {
log.Info("\trepo is not working from main branch", curName, "!=", mName)
return fmt.Errorf("not on main branch %s", check.GetGoPath())
}
if alreadyDone(check) {
// means it was already published
// protects against logic errors that might result
// in an infinite loop
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
check.Reload()
return fmt.Errorf("already released %s", check.GetGoPath())
}
if me.forge.Config.IsPrivate(me.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", me.releaseReasonS, me.release.version.String()})
retag = append(retag, []string{"git", "push", "origin", me.release.version.String()})
if !me.current.RunAll(retag) {
log.Info("retag failed")
findOk = false
return fmt.Errorf("RETAG FAILED %s", check.GetGoPath())
}
return skipToNext()
}
me.done = append(me.done, me.current.GetGoPath())
if err := me.forge.FinalGoDepsCheckOk(check, true); err != nil {
msg := fmt.Sprint("the go.mod file is wrong. fix it here?", check.GetGoPath())
badExit(errors.New(msg))
return fmt.Errorf("FinalGoDeps %s err %v", check.GetGoPath(), err)
}
if check.GetGoPath() == me.startRepo.GetGoPath() {
log.Info("CAN NOT SELF UPDATE.", check.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.", check.GetGoPath(), "is the same as os.Getwd()")
badExit(errors.New(msg))
}
if !me.startRepo.Exists("go.mod") {
log.Info("go.sum missing in", me.startRepo.GetGoPath())
log.Info("pick a different repo here")
log.Info("todo: error out earlier knowing this will upgrade")
log.Info("versions", me.startRepo.GetTargetVersion(), me.startRepo.GetMasterVersion())
panic("redo go.sum")
}
log.Info("\ttag and push", curName, me.release.version.String(), me.releaseReasonS)
if err := check.ValidGoSum(); err != nil {
log.Info("ValidGoSum() error", check.GetGoPath(), err)
msg := fmt.Sprint("ValidGoSum() error", check.GetGoPath(), err)
badExit(errors.New(msg))
}
// this is the final check. even here, just to be a total asshole
// I rerun go mod init and go mod tidy
// the re-parse all the results
// this is the last and final check.
// believe it or not, I've seen this fail. It's not worth being careful here
// or liberal about it. if it doesn't work, yep, you are stuck here you bastard
// (bastard being me. I designed this to be so annoying that if it makes it
// past this point it always works. that is the whole point of this code. NEVER
// EVER FAIL PAST THIS POINT
// )
// so let's do it: let's run go-mod-clean strict
// then reparse everything
_, err := check.RunVerboseOnError([]string{"go-mod-clean", "strict"})
if err != nil {
badExit(err)
}
var all [][]string
var autogen []string
all = append(all, []string{"git", "add", "-f", "go.mod"})
autogen = append(autogen, "go.mod")
if check.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 := me.current.IsProtobuf(); 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")
badExit(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", me.releaseReasonS})
all = append(all, []string{"git", "push"})
all = append(all, []string{"git", "tag", "-m", me.releaseReasonS, me.release.version.String()})
all = append(all, []string{"git", "push", "origin", me.release.version.String()})
// save the autogenerated files in git metadata (aka: notes)
cname := check.GetCurrentBranchName()
if err := check.AutogenSave(autogen, cname, true); err != nil {
log.Info("AutogenSave() error", err)
msg := fmt.Sprint("AutogenSave() error", err)
badExit(errors.New(msg))
}
if !me.current.RunAll(all) {
log.Info("failed to make new release", me.release.version.String())
findOk = false
return fmt.Errorf("setting findOK = false %s", check.GetGoPath())
}
log.Info("RELEASE OK")
// 'publish' the version to the golang package versioning system
if !doPublishVersion() {
time.Sleep(3 * time.Second)
// this can fail to update, try it again after sleep(3s)
if !doPublishVersion() {
log.Info("PUBLISH FAILED gopath=%s", check.GetGoPath())
findOk = false
return fmt.Errorf("PUBLISH FAILED gopath=%s", check.GetGoPath())
}
}
log.Info("PUBLISH OK")
// me.current.SetGoState("RELEASED")
// unwind and re-tag. Now that the go.mod and go.sum are published, revert
// to the development branch
if !me.current.RevertMasterToDevel() {
log.Info("Revert Failed")
findOk = false
return fmt.Errorf("REVERT FAILED %s", check.GetGoPath())
}
// update tag
var retag [][]string
retag = append(retag, []string{"git", "tag", "--delete", me.release.version.String()})
retag = append(retag, []string{"git", "push", "--delete", "origin", me.release.version.String()})
retag = append(retag, []string{"git", "tag", "-m", me.releaseReasonS, me.release.version.String()})
retag = append(retag, []string{"git", "push", "origin", me.release.version.String()})
if !me.current.RunAll(retag) {
log.Info("retag failed")
findOk = false
return fmt.Errorf("RETAG FAILED %s", check.GetGoPath())
}
log.Info("EVERYTHING OK. RERELEASED", me.current.GetGoPath())
return skipToNext()
}
func skipToNext() error {
me.current.Reload()
me.forge.SetConfigSave(true)
me.forge.ConfigSave()
log.Info("sleep 2")
time.Sleep(2 * time.Second)
printDone()
rePrepareRelease()
findNext()
if me.current == nil {
log.Info("NOT GOOD TO RUN ANOTHER DAY")
log.Info("took out all the loop code")
setCurrentRepo(nil, "loop by hand motherfucker", "fucknuts")
return fmt.Errorf("findNext returned next repo == nil")
}
log.Info("GOOD TO RUN ANOTHER DAY ON:", me.current.GetGoPath())
return nil
}
// this pulls the new tag from the golang package repository
// to insert the new version
func doPublishVersion() bool {
gopath := me.current.GetGoPath()
docmd := []string{"go", "get", "-v", gopath + "@" + me.release.version.String()}
log.Info("SHOULD RUN cmd HERE:", docmd)
if me.forge.Config.IsPrivate(me.current.GetGoPath()) {
// do not self update private repos
log.Info("This is a private repo and can not be self checked")
return true
}
// try to pull from google
if gopath == me.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)
badExit(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 := me.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)
log.Info("SELF UPDATE FAILED")
return false
}
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)
log.Info("SELF UPDATE FAILED")
return false
}
log.Info("SELF UPDATE OK. out =", strings.Join(result.Stdout, "\n"))
log.Info("SELF UPDATE WORKED")
return true
}