Compare commits

..

No commits in common. "master" and "v0.23.13" have entirely different histories.

16 changed files with 914 additions and 720 deletions

View File

@ -22,15 +22,10 @@ build:
GO111MODULE=off go build \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
clean:
rm -f go.*
-rm resources/*.so
touch resources/blank.so
install: goimports
touch resources/blank.so
-rm resources/*.so
# -cp -a ~/go/src/go.wit.com/toolkits/*/*.so resources/
-cp -a ~/go/src/go.wit.com/toolkits/*/*.so resources/
touch resources/blank.so
GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
@ -55,11 +50,18 @@ curl-setBranchesToMasterB:
findNext:
curl --silent http://localhost:9419/findNext
fixNext:
curl --silent http://localhost:9419/fixNext
showNext:
curl --silent http://localhost:9419/showNext
testNext:
curl --silent http://localhost:9419/testNext
doRelease:
reset
make curl-list-changed
make showNext
sleep 10
curl --silent http://localhost:9419/doRelease
@ -85,41 +87,10 @@ curl-incrementAllTargetVersions:
list-release-notdone:
curl --silent http://localhost:9419/releaseList?readonly=true
list-all:
curl --silent http://localhost:9419/list?readonly=true
safe-build: install
# forge list --private
wit-test install --verbose
# cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui gocui --gui-verbose --gui-file ../../toolkits/gocui/gocui.so >/tmp/forge.log 2>&1
rm -f go.* ; git checkout go.mod ; cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs
build-quick: install
wit-test install --verbose
# rm -f go.* ; git checkout go.mod ;cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs quick
sudo "wit update"
autocomplete:
guireleaser --bash > ~/.local/share/bash-completion/completions/guireleaser
test-build-force:
GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs --force
# time GUIRELEASE_REASON="safe-build" make test-build
test-build:
wit-test install --verbose
rm ~/go/bin/forged
cd ~/go/src/go.wit.com/lib/xgb/ && rm -f go.*
cd ~/go/src/go.wit.com/lib/xgb/ && git checkout go.mod
cd ~/go/src/go.wit.com/lib/xgb/ && time guireleaser --gui andlabs
cd ~/go/src/go.wit.com/apps/guireleaser
wit-test debian --verbose
do-aptly
# time GUIRELEASE_REASON="safe-build" make test-build-quick
test-build-quick:
wit-test install --verbose
rm ~/go/bin/forged
cd ~/go/src/go.wit.com/lib/xgb/ && rm -f go.*
cd ~/go/src/go.wit.com/lib/xgb/ && git checkout go.mod
cd ~/go/src/go.wit.com/lib/xgb/ && time guireleaser --gui andlabs quick
cd ~/go/src/go.wit.com/apps/guireleaser
wit-test debian --verbose
do-aptly
forge --find-private
wit-package --no-gui --make-install
cd ~/go/src/go.wit.com/lib/xgb/ && GUIRELEASE_REASON="safe-build" guireleaser

8
TODO
View File

@ -1,8 +0,0 @@
notes on what to fix next
go-args make patches for alexflint
go-mod-clean --restore *.pb.go files
go-mod-clean set ctime on files
guireleaser change "title small" to the package being updated"

72
argv.go
View File

@ -1,11 +1,5 @@
package main
import (
"fmt"
"os"
"os/user"
)
/*
this parses the command line arguements
@ -13,26 +7,16 @@ import (
*/
type args struct {
Quick *QuickCmd `arg:"subcommand:quick" help:"only do repos with patches"`
DryRun bool `arg:"--dry-run,env:DRYRUN" help:"don't actually do the release"`
Minor bool `arg:"--minor" help:"increment minor verion numbers"`
Protobuf bool `arg:"--protobuf" help:"increment protobuf repos"`
Verbose bool `arg:"--verbose" help:"talk alot"`
Full bool `arg:"--full" help:"build every package"`
Reason string `arg:"--reason" help:"tag message"`
Force bool `arg:"--force" help:"try harder than normal"`
Port int `arg:"--port" default:"9419" help:"do fun stuff with curl"`
Bash bool `arg:"--bash" help:"generate bash completion"`
BashAuto []string `arg:"--auto-complete" help:"does the actual autocompletion"`
}
type QuickCmd struct {
List *EmptyCmd `arg:"subcommand:list" help:"list available patches"`
Show *EmptyCmd `arg:"subcommand:show" help:"show a specific patch"`
NoLibs *EmptyCmd `arg:"subcommand:show" help:"skip libraries that aren't changed"`
}
type EmptyCmd struct {
// Repo string `arg:"positional" help:"go import path"`
// Increment bool `arg:"--increment" help:"auto increment"`
// Release bool `arg:"--release" help:"do a release an exit"`
DryRun bool `arg:"--dry-run,env:DRYRUN" help:"don't actually do the release"`
Fix bool `arg:"--fix" help:"run fixGoMod() on startup"`
Minor bool `arg:"--minor" help:"increment minor verion numbers"`
Protobuf bool `arg:"--protobuf" help:"increment protobuf repos"`
Reason string `arg:"--reason" help:"tag message"`
DumpVersions bool `arg:"--dump-versions" help:"dump the versions file for go.wit.com"`
Port int `arg:"--port" default:"9419" help:"do fun stuff with curl"`
}
func (a args) Description() string {
@ -47,39 +31,3 @@ the repositories in the go.sum file using git clone`
func (args) Version() string {
return "guireleaser " + VERSION
}
/*
handles shell autocomplete
*/
func (a args) DoAutoComplete(argv []string) {
switch argv[0] {
case "checkout":
usr, _ := user.Current()
fmt.Println("user devel master " + usr.Username)
case "commit":
fmt.Println("--all")
case "config":
fmt.Println("add fix list delete")
case "list":
fmt.Println("--all --mine --favorites --private")
case "pull":
fmt.Println("--all --mine --favorites --private")
case "patch":
fmt.Println("--list --submit --show")
case "dirty":
fmt.Println("--show-files")
case "user":
fmt.Println("--force")
case "devel":
fmt.Println("--force")
case "master":
fmt.Println("--force")
default:
if argv[0] == ARGNAME {
// list the subcommands here
fmt.Println("--bash quick")
}
}
os.Exit(0)
}

View File

@ -8,28 +8,29 @@ import (
"strings"
"time"
"github.com/go-cmd/cmd"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/log"
)
func doRelease() error {
check := me.current
func doRelease() bool {
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())
return false
}
// 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())
return false
}
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())
return false
}
if shell.Exists("go.mod") {
@ -37,54 +38,25 @@ func doRelease() error {
} else {
pwd, _ := os.Getwd()
log.Info("go.mod missing in working dir", pwd)
return fmt.Errorf("go.mod missing %s", check.GetGoPath())
return false
}
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())
return false
}
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.ReloadCheck()
return fmt.Errorf("already released %s", check.GetGoPath())
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, you didn't git clone", me.current.GetGoPath())
return false
}
// check if the git tag already exists somehow
testtag := me.release.version.String()
if check.LocalTagExists(testtag) {
log.Info("TAG ALREADY EXISTS", testtag)
return log.Errorf("%s TAG ALREADY EXISTS %s", check.FullPath, testtag)
} else {
log.Info("TAG IS NEW", testtag)
}
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 {
if !me.forge.FinalGoDepsCheckOk(check) {
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)
return false
}
if check.GetGoPath() == me.startRepo.GetGoPath() {
log.Info("CAN NOT SELF UPDATE.", check.GetGoPath(), "is the same as os.Getwd()")
@ -109,23 +81,6 @@ func doRelease() error {
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"})
@ -170,7 +125,7 @@ func doRelease() error {
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())
return false
}
log.Info("RELEASE OK")
@ -179,12 +134,26 @@ func doRelease() error {
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())
log.Info("PUBLISH FAILED")
findOk = false
return fmt.Errorf("PUBLISH FAILED gopath=%s", check.GetGoPath())
return false
}
}
pb := me.forge.FindByGoPath(me.current.GetGoPath())
if pb != nil {
// pb.UpdatePublished()
/* remove. earlier protected against nil
if !pb.IsPrimitive() {
loop := pb.Published.SortByGoPath()
for loop.Scan() {
t := loop.Next()
log.Info("new Published dep:", t.GetGoPath(), t.GetVersion())
}
}
*/
}
log.Info("PUBLISH OK")
// me.current.SetGoState("RELEASED")
@ -193,7 +162,7 @@ func doRelease() error {
if !me.current.RevertMasterToDevel() {
log.Info("Revert Failed")
findOk = false
return fmt.Errorf("REVERT FAILED %s", check.GetGoPath())
return false
}
// update tag
@ -203,14 +172,85 @@ func doRelease() error {
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 err := check.AutogenRestore(cname); err != nil {
log.Info("AutogenRestore() failed", err)
} else {
cmd := []string{"git", "push", "origin", "refs/notes/*:refs/notes/*"}
check.Run(cmd)
}
if !me.current.RunAll(retag) {
log.Info("retag failed")
findOk = false
return fmt.Errorf("RETAG FAILED %s", check.GetGoPath())
return false
}
log.Info("EVERYTHING OK. RERELEASED", me.current.GetGoPath())
return nil
// save autogen files under the tag version (for example: "v0.2.3")
newtag := me.release.version.String()
if err := check.AutogenSave(autogen, newtag, true); err != nil {
log.Info("AutogenSave() error", err)
msg := fmt.Sprint("AutogenSave() error", err)
badExit(errors.New(msg))
}
me.forge.ConfigSave()
cmd := []string{"forge", "--delete", check.GetGoPath()}
shell.RunRealtime(cmd)
me.forge = forgepb.Init()
// run this each time something gets published successfully
rePrepareRelease()
/*
// notsure about this anymore
// update the values in the GUI
if repov := me.repos.View.FindByPath(check.GetGoPath()); repov != nil {
repov.NewScan2(check)
}
*/
// attempt to find another repo to release
if !doReleaseFindNext() {
log.Info("doReleaseFindNext() could not find a new", findCounter)
log.Info("THIS PROBABLY MEANS THAT ACTUALLY WE ARE TOTALLY DONE?", findCounter)
count := me.forge.PrintReleaseReport(me.found)
log.Info("count =", count)
os.Setenv("FindNextDone", "true")
return false
}
log.Info("GOOD TO RUN ANOTHER DAY ON:", me.current.GetGoPath())
return true
}
// try to figure out if there is another package to update
// returns true if it finds something
func doReleaseFindNext() bool {
// scan for new repo
if findNext() {
log.Info("findNext() found something")
} else {
// this means findNext() didn't find anything but there are
// still packages to release. start trying to fix the go.sum files
if findCounter != 0 {
findFix = true
}
log.Info("findNext() could not find anything")
return false
}
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, you didn't git clone", me.current.GetGoPath())
return false
}
if findFix {
fixGodeps(check)
}
if me.forge.FinalGoDepsCheckOk(check) {
// the go.sum file is ok to release
return true
}
return false
}
// this pulls the new tag from the golang package repository
@ -227,6 +267,7 @@ func doPublishVersion() bool {
}
// try to pull from google
var result cmd.Status
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")
@ -237,7 +278,7 @@ func doPublishVersion() bool {
// 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)
result = me.startRepo.Run(docmd)
if result.Error != nil {
log.Info("SELF UPDATE FAILED. error =", result.Error)

View File

@ -8,12 +8,11 @@ import (
func okExit(thing string) {
log.Info(thing, "ok")
// log.Info("Finished go-clean on", check.GetNamespace(), "ok")
me.forge.Exit()
// log.Info("Finished go-clean on", check.GetGoPath(), "ok")
os.Exit(0)
}
func badExit(err error) {
log.Info("forge failed: ", err, me.forge.Config.ReposDir)
log.Info("forge failed: ", err, me.forge.GetGoSrc())
os.Exit(-1)
}

View File

@ -1,10 +1,8 @@
// This is a simple example
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
@ -15,153 +13,142 @@ var findCounter int
var findFix bool = false
var findOk bool = true
func checkDeps(repo *gitpb.Repo) error {
if repo.GoDeps == nil {
return fmt.Errorf("%s has GoDeps == nil", repo.GetNamespace())
}
for dep := range repo.GoDeps.IterAll() {
// log.Info(repo.GetNamespace(), dep.GoPath, dep.Version)
// check if the package in question is waiting for another package to publish
found := me.forge.FindByGoPath(dep.GoPath)
if found == nil {
return fmt.Errorf("%s has dep == nil", repo.GetNamespace(), dep.GoPath)
}
// loop through all the repos that need to be published with new go versions
all := me.found.SortByFullPath()
for all.Scan() {
check := all.Next()
if found.GetNamespace() == check.GetNamespace() {
// this package is waiting on other packages to publish
return fmt.Errorf("%s is waiting on %s", repo.GetNamespace(), found.GetNamespace())
}
}
// found package isn't being published. is the version correct?
// never check this? we are done?
/*
if found.GetLastTag() == dep.Version {
// everything is normal
} else {
return fmt.Errorf("%s version mismatch on %s (%s vs %s)", repo.GetNamespace(), found.GetNamespace(), found.GetLastTag(), dep.Version)
}
*/
}
// everything might be cool?
return nil
}
// trys to figure out if there is still something to update
// todo: redo this logic as it is terrible
// rename this findNext()
func findNext() bool {
findCounter = 0
all := me.found.SortByFullPath()
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
check := all.Next()
if check.GetMasterBranchName() != check.GetCurrentBranchName() {
log.Info("YOU MUST BE ON THE MASTER BRANCH", check.GetNamespace())
continue
}
if check.IsDirty() {
log.Info("CAN NOT RELEASE DIRTY REPO", check.GetNamespace())
continue
}
if alreadyDone(check) {
log.Info("findNext() alreadyDone. WHY IS THIS STILL CHECKING?", check.GetNamespace())
continue
}
log.Info("CHECKING START:", check.GetNamespace())
if me.forge.Config.IsPrivate(check.GetNamespace()) {
log.Info("GOOD TO GO ON PRIVATE REPO", check.GetNamespace())
if check.GetTargetVersion() == "" {
// not set to upgrade
continue
}
if check.GetLastTag() == check.GetTargetVersion() {
// log.Info("findNext() no update needed", check.GetGoPath, check.GetTargetVersion(), "vs", check.GetCurrentBranchVersion())
continue
} else {
log.Info("findNext() update needed", check.GetGoPath(), check.GetTargetVersion(), "vs", check.GetCurrentBranchVersion())
}
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
log.Info("findNext() skipping readonly")
continue
}
if check.CheckDirty() {
log.Info("findNext() skipping dirty")
continue
}
if findFix {
log.Info("findFix is true. running fixGoDeps()")
if fixGodeps(check) {
log.Info("fixGoDeps() returned true")
} else {
log.Info("fixGoDeps() returned false")
}
}
findCounter += 1
if !check.ParseGoSum() {
continue
}
if me.forge.FinalGoDepsCheckOk(check) {
setCurrentRepo(check, "should be good to release", "pretty sure")
return true
}
godepsNew, err := check.GoSumFromRepo()
if err != nil {
log.Info("CHECKING go deps from repo failed", err)
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("go mod tidy failed. this go package needs to be examined by hand as it doesn't appear to be primitive")
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, argv.Verbose); err != nil {
log.Info("CHECKING current repo deps failed", err)
continue
}
}
if err := me.forge.FinalGoDepsCheckOk(check, argv.Verbose); err != nil {
// if err := me.forge.FinalGoDepsCheckOk(check, false); err != nil {
log.Info("FinalGoDepsCheckOk() repo=", check.GetNamespace(), "err:", err)
log.Info("CHECKING END:", check.GetNamespace())
log.Info("")
continue
}
log.Info("GOOD TO GO ON", check.GetNamespace())
setCurrentRepo(check, "should be good to release", "pretty sure")
return true
log.Info("findNext() got to the end. repo", check.GetGoPath(), "did not work. trying to find a new one now")
}
if findCounter == 0 {
log.Info("NOTHING TO UPDATE. findCounter =", findCounter, "found len =", me.found.Len())
if me.found.Len() == 0 {
printDone()
okExit("")
}
log.Info("NOTHING TO UPDATE. findCounter =", findCounter)
} else {
findFix = true
log.Info("me.current is nil findCounter =", findCounter, "so set findFix =", findFix)
}
log.Info("tried to findNext() but not sure what to do next counter =", findCounter, "findFix =", findFix)
setCurrentRepo(nil, "findNext found nothing", "crap")
me.release.status.SetText("ALL DONE?")
return false
}
func setCurrentRepo(check *gitpb.Repo, s string, note string) bool {
me.current = check
if check == nil {
me.release.repo.SetText("")
me.release.version.SetText("")
me.release.releaseVersionB.SetText("nope")
me.release.version.SetText("badver")
} else {
me.release.repo.SetText(check.GetNamespace())
me.release.version.SetText(check.GetTargetVersion())
me.release.releaseVersionB.SetText("release version " + check.GetTargetVersion())
me.release.version.SetText(check.GetTargetVersion())
func runGoClean(check *gitpb.Repo, myarg string) bool {
// check if the package dependancies changed, if so, re-publish
check.GoDeps = nil
cmd := []string{"go-mod-clean", myarg}
log.Info("Running", cmd, "in", check.GetGoPath())
result := check.Run(cmd)
if result.Error != nil {
log.Info(cmd, "failed with", result.Error, check.GetGoPath())
log.Info("STDOUT")
log.Info(strings.Join(result.Stdout, "\n"))
log.Info("STDERR")
log.Info(strings.Join(result.Stderr, "\n"))
return false
}
me.release.status.SetText(s)
me.release.notes.SetText(note)
// me.release.openrepo.Enable()
return true
if result.Exit != 0 {
log.Info(cmd, "failed with", result.Exit, check.GetGoPath())
log.Info("STDOUT")
log.Info(strings.Join(result.Stdout, "\n"))
log.Info("STDERR")
log.Info(strings.Join(result.Stderr, "\n"))
return false
}
if check.ParseGoSum() {
return true
}
log.Info("ParseGoSum() failed")
return false
}
func testGoDepsCheckOk(godeps *gitpb.GoDeps, verbose bool) error {
if godeps == nil {
return errors.New("testGoDepsCheckOk() godeps == nil")
// tries to fix the go.mod and go.sum files
func fixGodeps(check *gitpb.Repo) bool {
var good bool = true
if !runGoClean(check, "--strict") {
return false
}
all := godeps.SortByGoPath()
for all.Scan() {
depRepo := all.Next()
fullpath := filepath.Join(me.forge.Config.ReposDir, depRepo.GoPath)
found := me.found.FindByFullPath(fullpath)
// skip primative ones
if check.GetGoPrimitive() {
if check.Exists("go.sum") {
log.Info("fixGoDeps() has go.sum but says it is primitive", check.GetGoPath())
return false
}
log.Info("fixGoDeps() skipping primitive", check.GetGoPath())
return true
}
log.Printf("current repo %s go dependancy count: %d", check.GetGoPath(), check.GoDepsLen())
deps := check.GoDeps.SortByGoPath()
for deps.Scan() {
depRepo := deps.Next()
// log.Info("found dep", depRepo.GetGoPath())
if me.forge.Config.IsReadOnly(depRepo.GetGoPath()) {
log.Info("IsReadOnly = true", depRepo.GetGoPath())
continue
} else {
// log.Info("IsReadOnly = false", depRepo.GetGoPath())
}
found := me.forge.FindByGoPath(depRepo.GetGoPath())
if found == nil {
log.Info("not found:", depRepo.GetGoPath())
continue
}
return fmt.Errorf("dep is being upgraded %s", depRepo.GoPath)
if depRepo.GetVersion() != found.GetMasterVersion() {
log.Printf("%-48s %10s (gitpb depRepo)", depRepo.GetGoPath(), depRepo.GetVersion())
log.Printf("%-48s %10s (gitpb found)", found.GetGoPath(), found.GetMasterVersion())
cmd := []string{"go", "get", depRepo.GetGoPath() + "@latest"}
check.Run(cmd)
}
}
return nil
return good
}
func setCurrentRepo(check *gitpb.Repo, s string, note string) bool {
me.release.repo.SetText(check.GetGoPath())
me.release.status.SetText(s)
me.release.notes.SetText(note)
me.current = check
me.release.version.SetText(check.GetTargetVersion())
me.release.releaseVersionB.SetText("release version " + check.GetTargetVersion())
me.release.openrepo.Enable()
return true
}

View File

@ -4,6 +4,7 @@ import (
"go.wit.com/gui"
"go.wit.com/lib/debugger"
"go.wit.com/lib/gui/logsettings"
"go.wit.com/log"
)
func globalDisplayOptions(box *gui.Node) {
@ -11,24 +12,23 @@ func globalDisplayOptions(box *gui.Node) {
group1 := vbox.NewGroup("Global Display Options")
/*
hidegrid := group1.NewGrid("hidecfg", 0, 0)
hidegrid.NewButton("Show Repository Window", func() {
if me.repos.Hidden() {
me.repos.Show()
} else {
me.repos.Hide()
}
log.Info("showing reposwin")
})
hidegrid.NextRow()
*/
hidegrid := group1.NewGrid("hidecfg", 0, 0)
hidegrid.NewButton("Show Repository Window", func() {
if me.repos.Hidden() {
me.repos.Show()
} else {
me.repos.Hide()
}
log.Info("showing reposwin")
})
hidegrid.NextRow()
group1 = vbox.NewGroup("prep for release")
grid := group1.RawGrid()
grid.NewButton("make prepare-release", func() {
rePrepareRelease()
makePrepareRelease()
})
grid.NextRow()

42
hideFunction.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"os"
"go.wit.com/lib/gui/repolist"
)
// like tcl/tk, use ENV variables to set display preferences
func hideFunction(r *repolist.RepoRow) {
// always show dirty repos
if r.Status.IsDirty() {
r.Show()
return
}
// hide read-only repos
if os.Getenv("AUTOTYPIST_READONLY") == "hide" {
if r.Status.ReadOnly() {
// log.Info(r.Name(), "hiding read-only repo")
r.Hide()
return
} else {
// log.Info(r.Name(), "not hiding read-only repo")
}
}
// show repos with mismatched mode
// this means, if you are in "devel" mode, show all the repos that
// might be stuck on the wrong branch, like 'master' or '<username>'
if os.Getenv("AUTOTYPIST_MODE") != "" {
if !r.Status.IsCorrectMode(os.Getenv("AUTOTYPIST_MODE")) {
r.Show()
return
}
}
// show everything else. often this will be "unconforming" repos
// if you what those repos ignored, add these to the config file
// as read-only=true
r.Show()
}

192
http.go
View File

@ -1,13 +1,14 @@
package main
import (
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/lib/gui/repolist"
"go.wit.com/log"
)
@ -27,6 +28,7 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
repoName := r.URL.Query().Get("repo")
version := r.URL.Query().Get("version")
comment := r.URL.Query().Get("comment")
whitelist := r.URL.Query().Get("whitelist")
switch route {
case "/help":
@ -46,7 +48,7 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
log.Info("")
case "/doRelease":
buttonDisable()
if err := doRelease(); err == nil {
if doRelease() {
buttonEnable()
log.Info("doRelease() worked")
} else {
@ -72,7 +74,10 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
// log.Info(me.current.StandardHeader())
log.Info(me.forge.StandardReleaseHeader(me.current, "todoing"))
case "/rescanAll":
me.repos.View.ScanRepositories()
case "/setCurrentRepo":
log.Info("repo: " + repoName)
log.Info("version: " + version)
log.Info("comment: " + comment)
@ -84,40 +89,98 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
}
setCurrentRepo(repo, "HTTP", "doRelease() ?")
case "/IncrementRevisonVersion":
log.Info("repo: " + repoName)
log.Info("version: " + version)
me.current.IncrementTargetRevision()
case "/IncrementMinorVersion":
log.Info("repo: " + repoName)
log.Info("version: " + version)
me.current.IncrementTargetMinor()
case "/setAllBranchesToMaster":
log.Info("set all branches to master")
me.Disable()
defer me.Enable()
if setAllBranchesToMaster() {
// if it succeeds, disable this button
me.setBranchesToMasterB.Disable()
}
return
case "/showNext":
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, current is missing", me.current.GetGoPath())
case "/setTargetVersion":
log.Info("repo: " + repoName)
log.Info("version: " + version)
if repoName != "" {
repo := me.repos.View.FindByName(repoName)
if repo == nil {
log.Info("could not find repo", repoName)
} else {
log.Info("setting target version", version)
repo.Status.SetTargetVersion(version)
}
return
}
testGoRepo(check)
me.forge.HumanPrintRepo(check)
log.Info("upgrade reason:", me.reason[check])
if me.current == nil {
log.Info("me.current == nil")
return
}
me.current.SetTargetVersion(version)
return
case "/setAllTargetVersions":
log.Info("version: " + version)
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
master := repo.Status.GetMasterVersion()
lastTag := repo.Status.LastTag()
if master == lastTag {
repo.Status.SetTargetVersion(master)
} else {
repo.Status.IncrementRevisionVersion("Nov 2024 test")
}
}
case "/whitelist":
repo := me.repos.View.FindByName(repoName)
if repo == nil {
log.Info("FindRepoByName() returned nil")
return
}
log.Info("whitelisted " + repo.Name())
if whitelist == "false" {
repo.Status.Whitelist = false
} else {
repo.Status.Whitelist = true
}
case "/testNext":
testNext()
return
case "/fixNext":
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, you didn't git clone", me.current.GetGoPath())
return
}
// destroy and recreate the go.sum
fixGodeps(check)
findOk = true
return
case "/showNext":
showNext()
return
case "/list":
me.forge.PrintHumanTable(me.found)
me.forge.PrintReleaseReport(me.forge.Repos)
return
case "/releaseList":
me.forge.PrintHumanTable(me.found)
me.forge.PrintReleaseReport(me.found)
return
default:
log.Info("BAD URL = " + route)
}
}
func testGoRepo(check *gitpb.Repo) {
data, _ := os.ReadFile(filepath.Join(check.FullPath, "go.mod"))
log.Info(string(data))
if err := me.forge.FinalGoDepsCheckOk(check, true); err == nil {
log.Info("forge.FinalGoDepsCheck(check) worked!")
} else {
log.Info("forge.FinalGoDepsCheck(check) failed. boo.")
}
}
// starts and sits waiting for HTTP requests
func startHTTP() {
http.HandleFunc("/", okHandler)
@ -130,3 +193,86 @@ func startHTTP() {
log.Println("Error starting server:", err)
}
}
func testNext() {
// re-scans the go.sum file. DOES NOT MODIFY ANYTHING
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, you didn't git clone", me.current.GetGoPath())
return
}
data, _ := os.ReadFile(filepath.Join(check.FullPath, "go.mod"))
log.Info(string(data))
if me.forge.FinalGoDepsCheckOk(check) {
log.Info("forge.FinalGoDepsCheck(check) worked!")
} else {
log.Info("forge.FinalGoDepsCheck(check) failed. boo.")
}
}
func showNext() {
log.Info("gui repo: " + me.release.repo.String())
log.Info("gui name: " + me.release.version.String())
log.Info("gui notes: " + me.release.notes.String())
log.Info("gui status: " + me.release.status.String())
log.Info("")
if me.current == nil {
log.Info("me.current == nil")
return
}
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("forge: how was this not found?", me.current.GetGoPath())
return
}
if me.current.GetTargetVersion() == "" {
log.Info("TargetVersion == blank")
}
if me.current.GetTargetVersion() == me.current.GetCurrentVersion() {
log.Info("IsReleased() == true. do not release this a second time")
} else {
log.Info("IsReleased() == false")
}
if check.CheckDirty() {
log.Info("CheckDirty() == true. do not release dirty repos")
} else {
log.Info("CheckDirty() == false")
}
if check.GetGoPrimitive() {
log.Info("IsPrimitive() == true")
} else {
log.Info("IsPrimitive() == false")
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
log.Info("IsPrivate() == true")
} else {
log.Info("IsPrivate() == false")
}
if ok, compiled, err := me.current.IsProtobuf(); ok {
log.Info(log.Sprint("IsProtobuf() == true compiled protobuf files = ", compiled))
if err != nil {
msg := fmt.Sprint("IsProtobuf() == err", err)
badExit(errors.New(msg))
}
for _, s := range compiled {
log.Info("\tcompiled file found:", s)
}
} else {
log.Info("IsProtobuf() == false")
if err != nil {
log.Info(log.Sprint("IsProtobuf() == err", err))
}
}
testNext()
log.Info(repolist.ReportHeader())
log.Info("")
log.Info(repolist.ReleaseReportHeader())
log.Info(me.forge.StandardReleaseHeader(me.current, "notsure"))
}

56
human.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
"fmt"
"go.wit.com/lib/gui/repolist"
"go.wit.com/log"
)
func PrintReport(readonly string, onlydirty string, perfect string) {
var count int
log.Info(repolist.ReportHeader())
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
count += 1
header := repo.StandardHeader()
if onlydirty == "true" {
if repo.CheckDirty() {
log.Info(header + "")
}
continue
}
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
if readonly == "true" {
log.Info(header + "readonly")
}
continue
}
if repo.State() == "PERFECT" {
if perfect == "false" {
continue
}
}
if repo.State() != "merge to main" {
log.Info(header + "")
continue
}
if repo.CheckDirty() {
log.Info(header + "")
continue
}
log.Info(header + "")
check := me.forge.FindByGoPath(repo.GetGoPath())
if check == nil {
log.Info("boo, you didn't git clone", repo.GetGoPath())
continue
}
me.forge.StandardReleaseHeader(check, repo.State())
}
log.Info(fmt.Sprintf("EVERYTHING WORKED repo count = %d", count))
}

130
main.go
View File

@ -8,9 +8,7 @@ import (
"path/filepath"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/fhelp"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/gui"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
@ -18,7 +16,6 @@ import (
)
var VERSION string
var ARGNAME string = "guireleaser"
//go:embed resources/*
var resources embed.FS
@ -27,18 +24,16 @@ var argv args
func main() {
me = new(autoType)
prep.Bash(ARGNAME, argv.DoAutoComplete) // this line should be: prep.Bash(argv)
me.myGui = prep.Gui() // prepares the GUI package for go-args
me.pp = arg.MustParse(&argv)
// load the ~/.config/forge/ config
me.forge = forgepb.Init()
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
me.found = new(gitpb.Repos)
fhelp.CheckGoModCleanExit()
// me.forge.ConfigPrintTable()
os.Setenv("REPO_WORK_PATH", me.forge.Config.ReposDir)
os.Setenv("REPO_WORK_PATH", me.forge.GetGoSrc())
// parse the command line
arg.MustParse(&argv)
// save the ENV var here
me.releaseReasonS = os.Getenv("GUIRELEASE_REASON")
@ -52,20 +47,16 @@ func main() {
// user drops to a shell or xterm, then they shouldn't be set there either
os.Unsetenv("GO111MODULE")
me.myGui.Start() // loads the GUI toolkit
me.myGui = gui.New()
me.myGui.InitEmbed(resources)
me.myGui.Default()
// our main window
me.mainWindow = gadgets.RawBasicWindow("GUI release manager " + VERSION)
me.mainWindow.Custom = func() {
log.Warn("Window closed. forge configsave")
// sets the hidden flag to false so Toggle() works
me.forge.ConfigSave()
okExit("")
}
me.mainWindow.Make()
me.mainWindow.Show()
me.mainWindow = me.myGui.NewWindow("GUI release manager " + VERSION)
me.mainBox = me.mainWindow.NewBox("bw hbox", true)
me.mainBox = me.mainWindow.Box()
// start the http server for polling status
go startHTTP()
// sanity check of things that might be around that mess
// up things later
@ -79,53 +70,94 @@ func main() {
log.Info("Creating the Release Window")
// initialize the repo list window
// which should be all the git repositories in ~/go/src & the .config file
me.repos = makeRepoView()
// the left side of the window options
globalDisplayOptions(me.mainBox)
// create the right side of the main window
createReleaseBox(me.mainBox)
// disable the open repo button. this isn't really important
// but does indicates the app (and toolkit) is working
// this can be removed later, but in these early days, I'm using this
// tool to release the code for this app, the gui and the gui toolkits
// and sometimes they lie, don't display stuff, don't even disable things
// so I can't trust even what I see. It's complicated right now still.
me.release.openrepo.Disable()
// disable the gui until the repos are scanned
me.release.box.Disable()
me.Disable()
// todo: add this to forgepb
me.startRepo = me.forge.FindWorkingDirRepo()
// register a Show/Hide function for the repo list table
me.repos.View.RegisterHideFunction(hideFunction)
if _, count, _, err := me.forge.IsEverythingOnMaster(); err != nil {
log.Info("not everything is on the master branch (", count, "repos)")
if argv.Quick != nil {
// quick also means ignore the master branch check
argv.Force = true
// scan in the State of all the repos
// TODO: should not really be necessary directly after init()
me.repos.View.ScanRepositories()
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
repo.Status.SetReadOnly(true)
} else {
repo.Status.SetReadOnly(false)
}
if !argv.Force {
os.Exit(-1)
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
repo.Status.SetPrivate(true)
} else {
repo.Status.SetPrivate(false)
}
}
// todo: add this to forgepb
me.startRepo = me.forge.FindWorkingDirRepo()
if me.startRepo == nil {
pwd, _ := os.Getwd()
msg := fmt.Sprint("Can not run if pwd is not a repo", pwd)
badExit(errors.New(msg))
}
me.forge.RillFuncError(rillPurge)
// run this each time something gets published successfully
rePrepareRelease()
if findNext() {
log.Info("prepare release findNext() returned true")
} else {
// check if nothing is found an exit?
if me.found.Len() == 0 {
log.Info("nothing found to publish")
okExit("found nothing")
}
}
me.Enable()
me.release.box.Enable()
// start the http server for polling status
startHTTP()
// set all branches to master & findNext()
makePrepareRelease()
// intermittently scans the status indefinitly
me.repos.View.Watchdog(func() {
log.Info("In main()")
// processing is done. update the repo summary box
// me.summary.Update()
})
}
// start the initail scan and make sure each repo is set
// to the master branch
func setAllBranchesToMaster() bool {
var worked bool = true
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo.ReadOnly() {
continue
}
if repo.IsDirty() {
continue
}
if repo.Status.Whitelist {
continue
}
if repo.Status.CheckoutMaster() {
log.Warn("git checkout master branch worked", repo.Name())
} else {
log.Warn("git checkout master branch failed", repo.Name())
worked = false
}
// repo.NewScan()
}
return worked
}

View File

@ -1,18 +1,35 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
func makePrepareRelease() {
me.Disable()
me.release.box.Disable()
defer me.Enable()
if setAllBranchesToMaster() {
// if it succeeds, disable this button
me.setBranchesToMasterB.Disable()
me.release.box.Enable()
me.forge.PrintReleaseReport(me.found)
} else {
log.Info("setAllBranchesToMaster() failed")
}
// run this each time something gets published successfully
rePrepareRelease()
if findNext() {
log.Info("prepare release findNext() returned true")
}
me.release.box.Enable()
}
func forceReleaseVersion(repo *gitpb.Repo) {
if argv.Minor {
// if v1.2.3 change to v.1.3.0
@ -21,277 +38,80 @@ func forceReleaseVersion(repo *gitpb.Repo) {
// if v1.2.3 change to v.1.2.4
repo.IncrementTargetRevision()
}
}
// empty git notes
repo.Run([]string{"git", "notes", "remove"})
func checkpkgcache(repo *gitpb.Repo) error {
homedir, err := os.UserHomeDir()
if err != nil {
return err
if !runGoClean(repo, "--restore") {
log.Info("go-mod-clean probably failed here. that's ok", repo.GetGoPath())
// os.Exit(-1)
}
rver := repo.GetLastTag()
if rver == "" {
return errors.New("could not get master version")
}
moddir := filepath.Join(homedir, "go/pkg/mod", repo.GetGoPath()+"@"+rver)
if shell.IsDir(moddir) {
return nil
}
getpath := repo.GetGoPath() + "@" + repo.GetLastTag()
log.Infof("~/go/pkg/mod/ IS MISSING %s so I'm running go get here.", getpath)
_, err = me.startRepo.RunVerboseOnError([]string{"go", "get", getpath})
return err
}
var rillcount int
func rillPurge(repo *gitpb.Repo) error {
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
return nil
}
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
return nil
}
_, err := repo.RunQuiet([]string{"go-mod-clean", "purge"})
rillcount += 1
if err != nil {
log.Info("go-mod-clean purge failed", repo.GetGoPath(), err)
return err
}
return nil
}
func rillRestore(repo *gitpb.Repo) error {
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
return nil
}
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
return nil
}
var err error
if argv.Verbose {
log.Info("go-mod-clean lax START", repo.GetGoPath())
result := repo.RunRealtime([]string{"go-mod-clean", "lax"})
log.Info("go-mod-clean lax END", repo.GetGoPath())
if result.Exit != 0 {
err = fmt.Errorf("repo %s failed %d", repo.GetGoPath(), result.Exit)
}
} else {
_, err = repo.RunQuiet([]string{"go-mod-clean", "lax"})
}
rillcount += 1
if err != nil {
log.Info("go-mod-clean lax failed", repo.GetGoPath(), err)
return err
}
return nil
}
func rePrepareRelease() {
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
// reload the config
me.forge = forgepb.Init()
me.found = new(gitpb.Repos)
me.reason = make(map[*gitpb.Repo]string) // stores the reason repos need to be versioned & released
log.Printf("rePrepareRelease() START rill go-mod-clean lax (11 seconds?)")
rillcount = 0
forgepb.RillX = 2
forgepb.RillY = 2
now := time.Now()
me.forge.RillFuncError(rillRestore)
log.Printf("showRestore() (%d total repos) took:%s\n", rillcount, shell.FormatDuration(time.Since(now)))
log.Sleep(1)
all2 := me.forge.Repos.SortByFullPath()
for all2.Scan() {
check := all2.Next()
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
continue
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
continue
}
// this should be rare? nonexistant?
if err := checkpkgcache(check); err != nil {
log.Info("go get checks failed here.", err, check.GetGoPath())
}
}
// blank all the target versions incase they were saved in the config .pb file
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
check := all.Next()
if alreadyDone(check) {
// means it was already published
// protects against logic errors that might result
// in an infinite loop
log.Info("WARNING alreadyDone rePrepareRelease()", check.GetGoPath())
// set the target version to the current master version
lastTag := check.GetLastTag()
check.SetTargetVersion(lastTag)
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
// can't release readonly repos
continue
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
// can't release readonly repos
continue
}
if !runGoClean(check, "--restore") {
log.Info("go-mod-clean probably failed here. that's ok", check.GetGoPath())
// os.Exit(-1)
}
}
all = me.forge.Repos.SortByFullPath()
for all.Scan() {
check := all.Next()
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
// can't release readonly repos
continue
}
// if master != lastTag, always increment
master := check.GetMasterVersion()
lastTag := check.GetLastTag()
if argv.Quick != nil {
// if argv has 'quick' don't do anything
// that doesn't actually have a patch
if master == lastTag {
continue
}
}
log.Info("LAST TAG", check.FullPath, master, lastTag)
// this is detailed. It makes sure the go.* files are absolutely perfect
if !me.forge.Config.IsPrivate(check.GetGoPath()) {
if err := checkPublishedGodeps(check); err != nil {
// this means the published godeps are no longer up to date
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
log.Info("checkPublishedGodeps failed with err", check.GetGoPath(), err)
continue
} else {
// log.Info("checkPublishedGodeps is ok", check.GetGoPath())
}
}
// if master != lastTag, always increment
if master != lastTag {
newmhash := check.GetTagHash(master)
oldlhash := check.GetTagHash(lastTag)
if newmhash == oldlhash {
// they are actually equal
continue
}
b1 := check.CountDiffObjects(oldlhash, newmhash)
b2 := check.CountDiffObjects(newmhash, oldlhash)
if b1 != 0 {
log.Printf("HASH ERROR %-50s tag %s < %s\n", check.GetGoPath(), newmhash, oldlhash)
log.Info("old vs new count", b1, b2, "git merge", oldlhash)
}
if b1 == 0 && b2 == 0 {
log.Info("got to identical repo", check.GetGoPath(), b1, b2)
log.Info("got to identical repo", check.GetGoPath(), oldlhash, newmhash)
// actually identical. do nothing
continue
}
if gitpb.IsGoTagVersionGreater(lastTag, master) {
// this function is not right really. the hash error above should catch it correctly
// log.Printf("PROBABLY NOT NEE %-50s tag %s < %s\n", check.GetGoPath(), lastTag, master)
}
log.Printf("NEED RELEASE FOR %-50s tag %s != %s\n", check.GetGoPath(), master, lastTag)
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "master != lastTag"
continue
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
// only checks after this are GO dep related which don't matter for private repos
me.found.AppendUniqueGoPath(check)
continue
}
if argv.Protobuf && check.GetRepoType() == "protobuf" {
log.Printf("NEED RELEASE FOR %s err: %v\n", check.GetGoPath(), "because --protobuf")
// if --protobuf, this will force upgrade each one
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "protobuf repo deps changed"
me.found.AppendUniqueGoPath(check)
continue
}
// if the repo is a go binary or plugin for a new release for
// any library version change
// if check.GetRepoType() == "binary" || check.GetRepoType() == "plugin" {
// check if the package dependancies changed, if so, re-publish
if err := me.forge.FinalGoDepsCheckOk(check, false); err == nil {
// log.Printf("go.sum is perfect! %s\n", check.GetGoPath())
continue
} else {
log.Printf("NEED RELEASE FOR %-50s err: %v\n", check.GetGoPath(), err)
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "FinalGoDepsCheckOk() failed even though master tag == last tag"
}
}
me.forge.PrintHumanTable(me.found)
// todo: verify each found repo is on the master branch
for repo := range me.found.IterAll() {
if repo.CurrentBranchName != repo.MasterBranchName {
log.Info("repo not on master branch", repo.FullPath)
if !argv.Force {
os.Exit(-1)
if check.GetRepoType() == "binary" || check.GetRepoType() == "plugin" {
// check if the package dependancies changed, if so, re-publish
if me.forge.FinalGoDepsCheckOk(check) {
log.Printf("go.sum is perfect! %s\n", check.GetGoPath())
continue
}
log.Printf("dependancy checks indicate a new release is needed for %s\n", check.GetGoPath())
forceReleaseVersion(check)
me.found.AppendUniqueGoPath(check)
}
}
}
func printDone() {
for _, gopath := range me.done {
log.Info("printDone() THESE WERE PUBLISHED", gopath)
}
log.Info("printDone() total finished so far:", len(me.done))
time.Sleep(time.Second)
}
func alreadyDone(repo *gitpb.Repo) bool {
for _, gopath := range me.done {
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
if repo.GetGoPath() == gopath {
log.Info("FOUND. RETURN TRUE. already done", gopath, repo.GetGoPath())
return true
}
}
return false
}
/*
func upgradeReason(repo *gitpb.Repo) string {
for _, gopath := range me.reason {
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
if repo.GetGoPath() == gopath {
log.Info("FOUND. RETURN TRUE. already done", gopath, repo.GetGoPath())
return true
}
}
return false
}
*/
func checkPublishedGodeps(repo *gitpb.Repo) error {
godepsOld, err := repo.GoSumFromPkgDir()
if err != nil {
return err
}
if godepsOld != nil {
if err := me.forge.TestGoDepsCheckOk(godepsOld, argv.Verbose); err != nil {
return err
}
}
godepsNew, err := repo.GoSumFromRepo()
if err != nil {
return err
}
if godepsOld == nil {
if godepsNew == nil {
log.Printf("%s published godeps == nil && real == nil\n", repo.GetGoPath())
return nil
} else {
return fmt.Errorf("published godeps == nil vs real != nil")
}
}
if err := me.forge.TestGoDepsCheckOk(godepsNew, argv.Verbose); err != nil {
return err
}
return nil
me.forge.ConfigSave()
}

View File

@ -3,14 +3,14 @@ package main
import (
"fmt"
"os"
"time"
"go.wit.com/gui"
"go.wit.com/log"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/lib/gui/repolist"
)
type releaseStruct struct {
@ -25,14 +25,14 @@ type releaseStruct struct {
releaseVersionB *gui.Node
reason *gadgets.BasicEntry
// openrepo *gui.Node
openrepo *gui.Node
goGetB *gui.Node
checkGoSumB *gui.Node
checkDirtyB *gui.Node
sendVersionB *gui.Node
checkSafeB *gui.Node
// whitelist map[string]*repolist.RepoRow
whitelist map[string]*repolist.RepoRow
}
func (w *autoType) Disable() {
@ -51,20 +51,14 @@ func createReleaseBox(box *gui.Node) {
me.release.releaseVersionB = me.release.grid.NewButton("release version", func() {
buttonDisable()
fpath := me.current.FullPath
if err := doRelease(); err == nil {
if doRelease() {
buttonEnable()
log.Info("doRelease() worked", fpath)
log.Info("doRelease() worked")
} else {
log.Info("doRelease() failed", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
log.Info("doRelease() failed")
}
skipToNext()
me.forge.PrintHumanTable(me.found)
})
me.release.grid.NewButton("Find Next", func() {
me.release.grid.NewButton("Find Next Releasable", func() {
me.Disable()
defer me.Enable()
if findNext() {
@ -72,18 +66,15 @@ func createReleaseBox(box *gui.Node) {
return
}
})
me.release.grid.NewButton("Show Next", func() {
check := me.current
if check == nil {
log.Info("boo, current is missing", me.current.GetGoPath())
return
}
testGoRepo(check)
me.forge.HumanPrintRepo(check)
})
me.release.grid.NextRow()
me.release.repo = gadgets.NewOneLiner(me.release.grid, "repo")
me.release.openrepo = me.release.grid.NewButton("Configure", func() {
if repov := me.repos.View.FindByPath(me.current.GetGoPath()); repov != nil {
repov.Status.Toggle()
}
})
me.release.openrepo.Disable()
me.release.grid.NextRow()
me.release.status = gadgets.NewOneLiner(me.release.grid, "status")
me.release.grid.NextRow()
@ -101,71 +92,141 @@ func createReleaseBox(box *gui.Node) {
me.autoWorkingPwd = gadgets.NewOneLiner(me.release.grid, "working directory (pwd)")
me.release.grid.NextRow()
// me.userHomePwd = gadgets.NewOneLiner(me.release.grid, "user home")
// me.release.grid.NextRow()
me.goSrcPwd = gadgets.NewOneLiner(me.release.grid, "go src home")
me.release.grid.NextRow()
// me.userHomePwd.SetText(homeDir)
me.goSrcPwd.SetText(me.forge.Config.ReposDir)
me.goSrcPwd.SetText(me.forge.GetGoSrc())
group := me.release.box.NewGroup("Run on Current Repo")
grid := group.NewGrid("buildOptions", 0, 0)
grid.NewButton("whitelist", func() {
// tmp := me.current.GoState()
if repov := me.repos.View.FindByPath(me.current.GetGoPath()); repov != nil {
log.Info("trying to whitelist repo", me.current.GetGoPath())
repov.Status.Whitelist = true
}
findNext()
})
grid.NextRow()
group = me.release.box.NewGroup("Publish until done")
group = me.release.box.NewGroup("Process against all repos")
grid = group.NewGrid("buildOptions", 0, 0)
grid.NewButton("doRelease() all", func() {
buttonDisable()
doReleaseAll()
// rather than loop forever, at least limit this to the number of repos
// incase something, somewhere, goes wrong
ok, duration := doReleaseAll()
s := fmt.Sprint(duration)
log.Info("release returned", ok, "and ran for", s, "findCounter =", findCounter)
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
return
}
first := findCounter
if findCounter != 0 {
log.Info("should try thsi doRelease() loop again since findCounter =", findCounter)
ok, duration := doReleaseAll()
s := fmt.Sprint(duration)
log.Info("release returned", ok, "and ran for", s, "findCounter =", findCounter)
}
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
return
}
second := findCounter
log.Info("doReleaseAll() first =", first, "second =", second)
if first == 0 {
log.Info("doReleaseAll() first is 0. everything is done. second is", second)
log.Info("exit() here safely")
me.forge.ConfigSave()
okExit("")
return
}
if first != second {
// try a third time
log.Info("doReleaseAll() first second do not match. findNext()")
findNext()
ok, duration := doReleaseAll()
s := fmt.Sprint(duration)
log.Info("release returned", ok, "and ran for", s, "findCounter =", findCounter)
third := findCounter
log.Info("doReleaseAll() findCounter first =", first, "second =", second, "third =", third)
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
return
}
if (second == 0) && (third == 0) {
log.Info("doReleaseAll() SaveConfig() here and Exit(0)")
me.forge.ConfigSave()
okExit("")
}
} else {
log.Info("doReleaseAll() first second match. something has gone terribly wrong")
log.Info("killing guireleaser is a bad idea here. it will potentially loose state")
log.Info("the only way now is to parse 'go list' or ~/go/pkg/mod/<gopath>/go.sum files")
log.Info("to determine the last known version to make sure everything is redone correctly")
log.Info("this is the worst case. the better idea is to make sure it never fails")
log.Info("and restarts correctly where it left off. That might not be possible?")
log.Info("because 'go get @foo.com/bar@latest' appears to be global and so")
log.Info("some go.sum files might be correct when some are not actually published")
log.Info("TODO: is this true or not?")
}
buttonEnable()
})
grid.NextRow()
group = me.release.box.NewGroup("experimental and potentially dangerous stuff")
grid = group.NewGrid("buildOptions", 0, 0)
me.setBranchesToMasterB = grid.NewButton("set all branches to master", func() {
me.Disable()
defer me.Enable()
if setAllBranchesToMaster() {
// if it succeeds, disable this button
me.setBranchesToMasterB.Disable()
}
})
grid.NextRow()
}
func doReleaseAll() {
count := 0
for {
log.Info("START doRelease() LOOP count =", count, "len me.done =", len(me.done))
if err := doRelease(); err != nil {
break
func doReleaseAll() (bool, time.Duration) {
var worked bool = true
findCounter = 0
duration := repolist.TimeFunction(func() {
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
loop.Repo()
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
worked = false
break
}
if doRelease() {
log.Info("doRelease() worked. findCounter =", findCounter)
} else {
if os.Getenv("FindNextDone") == "true" {
log.Info("findNext says it was done. findCounter =", findCounter)
log.Info("findNext says it was done. findCounter =", findCounter)
log.Info("we can exit here")
}
if me.release.status.String() == "ALL DONE?" {
log.Info("maybe ALL DONE?. findCounter =", findCounter)
worked = true
}
log.Info("doRelease() failed. findCounter =", findCounter)
worked = false
break
}
}
if err := skipToNext(); err != nil {
break
}
count += 1
if count > me.forge.Repos.Len() {
// never allow a loop longer than all the known repos
// this probably doesn't matter, but often this code is wrong
// so this is a safety check. never remove this check.
break
}
}
}
func skipToNext() error {
shell.RunVerbose([]string{"forge", "dirty"})
log.Info("Sleeping for 2 seconds for no reason.")
time.Sleep(1)
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
me.found = new(gitpb.Repos)
me.current.ReloadCheck()
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
})
return worked, duration
}
func buttonDisable() {

73
repoview.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repolist"
"go.wit.com/log"
"go.wit.com/gui"
)
type repoWindow struct {
win *gadgets.BasicWindow
box *gui.Node
View *repolist.RepoList
}
func (r *repoWindow) Hidden() bool {
return r.win.Hidden()
}
func (r *repoWindow) Show() {
r.win.Show()
}
func (r *repoWindow) Hide() {
r.win.Hide()
}
func (r *repoWindow) Disable() {
r.box.Disable()
}
func (r *repoWindow) Enable() {
r.box.Enable()
}
// you can only have one of these
func makeRepoView() *repoWindow {
if me.repos != nil {
return me.repos
}
r := new(repoWindow)
r.win = gadgets.RawBasicWindow("GUI repositories in ~/go/src/")
r.win.Make()
r.box = r.win.Box().NewBox("bw vbox", false)
r.win.Custom = func() {
log.Warn("GOT HERE: main() gadgets.NewBasicWindow() close")
log.Warn("Should I do something special here?")
}
// reposbox.SetExpand(false)
group1 := r.box.NewGroup("Run on all repos:")
hbox := group1.Box()
// hbox.Horizontal()
hbox.Vertical()
r.View = repolist.InitBox(me.forge, r.box)
r.View.Enable()
r.View.ScanRepositories()
/*
r.View = repolist.GuireleaserView(r.box)
showncount := r.View.MirrorShownCount()
box2.Append(showncount)
duration := r.View.MirrorScanDuration()
box2.Append(duration)
*/
return r
}

View File

@ -1 +0,0 @@
* you can put toolkit .so binaries here

View File

@ -2,10 +2,8 @@
package main
import (
"go.wit.com/dev/alexflint/arg"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
)
@ -13,17 +11,15 @@ import (
var me *autoType
type autoType struct {
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
myGui *prep.GuiPrep // the gui handle itself
releaseReasonS string // = "gocui dropdown select"
release releaseStruct // notsure
reposbox *gui.Node // notsure
reposgrid *gui.Node // notsure
reposgroup *gui.Node // notsure
current *gitpb.Repo // tracks the next repo to publish
found *gitpb.Repos // stores the list of repos to process things on
done []string // gopaths for repos already published
reason map[*gitpb.Repo]string // the reason this package is going to be updated
myGui *gui.Node
releaseReasonS string // = "gocui dropdown select"
release releaseStruct
reposbox *gui.Node
reposgrid *gui.Node
reposgroup *gui.Node
current *gitpb.Repo
found *gitpb.Repos // stores the list of repos to process things on
// this is the repo we are starting in
// make sure it never changes so go.mod and go.sum are always there
@ -31,10 +27,35 @@ type autoType struct {
startRepo *gitpb.Repo
// guireleaser window
mainWindow *gadgets.BasicWindow
mainWindow *gui.Node
mainBox *gui.Node
forge *forgepb.Forge // your customized repo preferences and settings
// our view of the repositories
repos *repoWindow
// your customized repo preferences and settings
forge *forgepb.Forge
// #### autotypist Global Build Options
// what to change all the branches to
// so, as a developer, you can move all the repos
// to the 'devel' branch and then test a devel branch build
// then switch back to your 'username' branch and do a build there
// toMoveToBranch string
// displays the preferred names used for the repo tree state
// mainBranch *gadgets.BasicCombobox
// develBranch *gadgets.BasicCombobox
// userBranch *gadgets.BasicCombobox
// this button will regenerate everyones go.mod & go.sum
rerunGoMod *gui.Node
// if checked, will stop trying to os.Exec() things after failure
stopOnErrors *gui.Node
// button to attempt to autorebuild
autoRebuildButton *gui.Node
// checkbox for --dry-run
autoDryRun *gui.Node
@ -60,3 +81,9 @@ type autoType struct {
// show the time it took to do a scan
duration *gui.Node
}
/*
func (my *autoType) GoSrcPath() string {
return my.goSrcPwd.String()
}
*/