Compare commits

..

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

17 changed files with 1001 additions and 946 deletions

View File

@ -1,10 +1,9 @@
VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d)
all: install
all: build
goimports:
reset
goimports -w *.go
# // to globally reset paths:
# // gofmt -w -r "go.wit.com/gui -> go.wit.com/gui/gui" .
@ -14,33 +13,36 @@ vet:
build:
echo "build it!"
touch resources/blank.so
-rm resources/*.so
-mkdir resources/
-cp -a ~/go/src/go.wit.com/toolkits/*/*.so resources/
touch resources/blank.so
cp -a ~/go/src/go.wit.com/toolkits/*.so resources/
GO111MODULE=off go build \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
clean:
rm -f go.*
install:
-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/
touch resources/blank.so
cp -a ~/go/src/go.wit.com/toolkits/*.so resources/
GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
test: build
GUIRELEASE_REASON='test build' ./guireleaser
check-git-clean:
@git diff-index --quiet HEAD -- || (echo "Git repository is dirty, please commit your changes first"; exit 1)
redomod:
rm -f go.*
GO111MODULE= go mod init
GO111MODULE= go mod tidy
go mod edit -go=1.20
curl-help:
curl --silent http://localhost:9419/help
tempWin:
curl --silent http://localhost:9419/tempWin
curl-rescan-All:
curl --silent http://localhost:9419/rescanAll
@ -60,6 +62,7 @@ showNext:
doRelease:
reset
make curl-list-changed
make showNext
sleep 10
curl --silent http://localhost:9419/doRelease
@ -67,10 +70,6 @@ doRelease:
curl-setCurrent-go-wit-com-gui:
curl --silent http://localhost:9419/setCurrentRepo?repo=go.wit.com/gui
curl-setCurrent-go-clone:
curl --silent http://localhost:9419/setCurrentRepo?repo=go.wit.com/apps/go-clone
make showNext
curl-setTargetVersion-virtigo-v0.1.1:
curl --silent http://localhost:9419/setTargetVersion?version=v0.1.1
@ -85,41 +84,14 @@ curl-incrementAllTargetVersions:
list-release-notdone:
curl --silent http://localhost:9419/releaseList?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
# only show repos that need to be merged to the master branch
curl-list-changed:
curl --silent http://localhost:9419/list?perfect=false
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"
# include repos that you probably can't git push commits
curl-list-everything:
curl --silent http://localhost:9419/list?readonly=true
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
curl-file-for-go.wit.com:
curl --silent http://localhost:9419/goweblist?readonly=true
curl --silent http://localhost:9419/goweblist?readonly=true |sort > ~/go.wit.com.versions

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"

75
argv.go
View File

@ -1,41 +1,22 @@
package main
import (
"fmt"
"os"
"os/user"
)
/*
this parses the command line arguements
this enables command line options from other packages like 'gui' and 'log'
*/
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 argv 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"`
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"`
}
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 {
}
func (a args) Description() string {
func (a argv) Description() string {
return `
Example usage:
guireleaser go.wit.com/apps/go-clone --increment --release --dry-run --reason "blerg"
@ -44,42 +25,6 @@ This will pull down the go sources and
the repositories in the go.sum file using git clone`
}
func (args) Version() string {
func (argv) 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

@ -2,154 +2,73 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/go-cmd/cmd"
"go.wit.com/lib/gui/repolist"
"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())
}
func doRelease() bool {
log.Info("doRelease() on", me.current.Name())
// 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") {
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())
log.Info("go.mod disappeared. need to run go mod init and go mod tidy here:", pwd)
shell.RunRealtime([]string{"go", "mod", "init"})
shell.RunRealtime([]string{"go", "mod", "tidy"})
shell.RunRealtime([]string{"go", "mod", "edit", "-go=1.20"})
}
curName := me.current.GetCurrentBranchName()
mName := me.current.GetMasterBranchName()
curName := me.current.Status.GetCurrentBranchName()
mName := me.current.Status.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 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 {
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")
if !checkValidGoSum(me.current) {
return false
}
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 {
if me.current.Status.IsPrimitive() {
// 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))
os.Exit(-1)
}
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")
@ -159,30 +78,16 @@ func doRelease() error {
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) {
if !me.current.Status.DoAll(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")
// '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 FAILED")
return false
}
log.Info("PUBLISH OK")
@ -190,10 +95,9 @@ func doRelease() error {
// unwind and re-tag. Now that the go.mod and go.sum are published, revert
// to the development branch
if !me.current.RevertMasterToDevel() {
if !me.current.Status.RevertMasterToDevel() {
log.Info("Revert Failed")
findOk = false
return fmt.Errorf("REVERT FAILED %s", check.GetGoPath())
return false
}
// update tag
@ -203,42 +107,117 @@ 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 !me.current.RunAll(retag) {
if !me.current.Status.DoAll(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())
log.Info("EVERYTHING OK. RERELEASED", me.current.Name())
return nil
// update the values in the GUI
me.current.NewScan()
pb := me.forge.Repos.FindByGoPath(me.current.GoPath())
if pb != nil {
pb.RedoGoMod()
loop := pb.Published.SortByGoPath()
for loop.Scan() {
t := loop.Next()
log.Info("orig Published dep:", t.GetGoPath(), t.GetVersion())
}
pb.UpdatePublished()
loop = pb.Published.SortByGoPath()
for loop.Scan() {
t := loop.Next()
log.Info("new Published dep:", t.GetGoPath(), t.GetVersion())
}
me.forge.Repos.ConfigSave()
}
// attempt to find another repo to release
if !doReleaseFindNext() {
log.Info("doReleaseFindNext() could not find a new")
log.Info("THIS PROBABLY MEANS THAT ACTUALLY WE ARE TOTALLY DONE?")
os.Setenv("FindNextDone", "true")
return false
}
log.Info("GOOD TO RUN ANOTHER DAY ON:", me.current.Name())
return true
}
func checkValidGoSum(repo *repolist.RepoRow) bool {
ok, err := me.repos.View.CheckValidGoSum(repo)
if err != nil {
log.Info("go mod tidy not ok", err)
return false
}
if ok {
log.Info("repo has go.sum requirements that are clean")
// me.current.setGoSumStatus("CLEAN")
me.release.status.SetValue("GOOD")
me.release.notes.SetValue("CheckValidGoSum() does not seem to lie")
return true
}
me.release.notes.SetValue("CheckValidGoSum() failed")
return false
}
// try to figure out if there is another package to update
func doReleaseFindNext() bool {
// scan for new repo
if findNext() {
log.Info("findNext() found something")
} else {
log.Info("findNext() could not find anything")
return false
}
if checkValidGoSum(me.current) {
return true
}
return false
}
// this pulls the new tag from the golang package repository
// to insert the new version
func doPublishVersion() bool {
gopath := me.current.GetGoPath()
gopath := me.current.GoPath()
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()) {
// right now, you can't publish this because the go.* files in this project are screwed up
if me.release.guireleaser == nil {
log.Info("CAN NOT SELF UPDATE HERE. cmd =", docmd)
return false
}
homeDir, _ := os.UserHomeDir()
gosum := filepath.Join(homeDir, "go/src/go.wit.com/apps/guireleaser/go.sum")
if !shell.Exists(gosum) {
log.Info("go.sum must exist here")
me.release.guireleaser.MakeRedoMod()
}
if me.current.Status.IsPrivate() {
// 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() {
var result cmd.Status
if gopath == "go.wit.com/apps/guireleaser" {
log.Info("CAN NOT SELF UPDATE. cmd =", docmd)
log.Info("go get must be run from somewhere else other than startRepo")
log.Info("go get must be run from somewhere else other than guireleaser")
log.Info("chdir to autotypist if it exists")
msg := fmt.Sprint("CAN NOT SELF UPDATE. cmd =", docmd)
badExit(errors.New(msg))
if shell.Exists("/home/jcarr/go/src/go.wit.com/apps/autotypist") {
os.Chdir("/home/jcarr/go/src/go.wit.com/apps/autotypist")
} else {
log.Info("need to chdir somewhere with go.sum & go.mod")
return false
}
// result = shell.PathRun("/home/jcarr/go/src/go.wit.com/apps/autotypist", docmd)
} else {
// publish go.mod & go.sum for use with go
os.Unsetenv("GO111MODULE")
log.Info("TRYING TO SELF UPDATE HERE. cmd =", docmd)
result = me.release.guireleaser.Status.Run(docmd)
}
// 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)
@ -253,7 +232,7 @@ func doPublishVersion() bool {
log.Info("SELF UPDATE FAILED")
return false
}
log.Info("SELF UPDATE OK. out =", strings.Join(result.Stdout, "\n"))
log.Info("SELF UPDATE OK. out =", result.Stdout)
log.Info("SELF UPDATE WORKED")
return true
}

19
exit.go
View File

@ -1,19 +0,0 @@
package main
import (
"os"
"go.wit.com/log"
)
func okExit(thing string) {
log.Info(thing, "ok")
// log.Info("Finished go-clean on", check.GetNamespace(), "ok")
me.forge.Exit()
os.Exit(0)
}
func badExit(err error) {
log.Info("forge failed: ", err, me.forge.Config.ReposDir)
os.Exit(-1)
}

View File

@ -1,167 +0,0 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"go.wit.com/log"
"go.wit.com/lib/protobuf/gitpb"
)
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()
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())
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
}
if findCounter == 0 {
log.Info("NOTHING TO UPDATE. findCounter =", findCounter, "found len =", me.found.Len())
if me.found.Len() == 0 {
printDone()
okExit("")
}
} else {
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())
}
me.release.status.SetText(s)
me.release.notes.SetText(note)
// me.release.openrepo.Enable()
return true
}
func testGoDepsCheckOk(godeps *gitpb.GoDeps, verbose bool) error {
if godeps == nil {
return errors.New("testGoDepsCheckOk() godeps == nil")
}
all := godeps.SortByGoPath()
for all.Scan() {
depRepo := all.Next()
fullpath := filepath.Join(me.forge.Config.ReposDir, depRepo.GoPath)
found := me.found.FindByFullPath(fullpath)
if found == nil {
continue
}
return fmt.Errorf("dep is being upgraded %s", depRepo.GoPath)
}
return nil
}

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,46 @@ 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()
me.Disable()
me.release.box.Disable()
defer me.Enable()
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")
}
}
findNext()
if setAllBranchesToMaster() {
// if it succeeds, disable this button
me.setBranchesToMasterB.Disable()
me.release.box.Enable()
me.repos.View.PrintReleaseReport("", "")
} else {
log.Info("setAllBranchesToMaster() failed")
}
})
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()
}

210
http.go
View File

@ -4,10 +4,9 @@ import (
"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 +26,10 @@ 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")
readonly := r.URL.Query().Get("readonly")
onlydirty := r.URL.Query().Get("onlydirty")
perfect := r.URL.Query().Get("perfect")
whitelist := r.URL.Query().Get("whitelist")
switch route {
case "/help":
@ -44,9 +47,18 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
log.Info("")
log.Info("setVersion?repo=go.wit.com/gui?target=0.2 attempts to set the target version to 0.2")
log.Info("")
case "/tempWin":
tempWin := makeTempView()
loop := me.repos.View.UnmergedRepos()
for loop.Scan() {
repo := loop.Repo()
tempWin.View.ShowRepo(repo)
log.Info("UnmergedRepo: " + repo.Name())
}
case "/doRelease":
buttonDisable()
if err := doRelease(); err == nil {
if doRelease() {
buttonEnable()
log.Info("doRelease() worked")
} else {
@ -70,59 +82,197 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
return
}
// log.Info(me.current.StandardHeader())
log.Info(me.forge.StandardReleaseHeader(me.current, "todoing"))
log.Info(me.current.StandardHeader())
log.Info(me.current.StandardReleaseHeader())
case "/rescanAll":
me.repos.View.ScanRepositories()
case "/setCurrentRepo":
log.Info("repo: " + repoName)
log.Info("version: " + version)
log.Info("comment: " + comment)
repo := me.forge.FindByGoPath(repoName)
repo := me.repos.View.FindByName(repoName)
if repo == nil {
log.Info("FindRepoByName() returned nil")
return
}
setCurrentRepo(repo, "HTTP", "doRelease() ?")
case "/IncrementRevisonVersion":
log.Info("repo: " + repoName)
log.Info("version: " + version)
me.current.Status.IncrementRevisionVersion(comment)
case "/IncrementMinorVersion":
log.Info("repo: " + repoName)
log.Info("version: " + version)
me.current.Status.IncrementMinorVersion("trying minor")
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.Status.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 "/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
}
if checkValidGoSum(me.current) {
log.Info("checkValidGoSum() == true")
} else {
log.Info("checkValidGoSum() == false SHOULD NOT RELEASE THIS")
}
if me.current.Status.IsReleased() {
log.Info("IsReleased() == true SHOULD NOT RELEASE THIS")
} else {
log.Info("IsReleased() == false")
}
if me.current.Status.CheckDirty() {
log.Info("CheckDirty() == true. SHOULD NOT RELEASE THIS")
} else {
log.Info("CheckDirty() == false")
}
if me.current.Status.IsPrimitive() {
log.Info("IsPrimitive() == true")
} else {
log.Info("IsPrimitive() == false")
}
if me.current.Status.IsPrivate() {
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 {
log.Info(log.Sprint("IsProtobuf() == err", err))
os.Exit(-1)
}
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))
}
}
if me.current.Status.Whitelist {
log.Info("Whitelist == true SHOULD NOT RELEASE THIS")
} else {
log.Info("Whitelist == false")
}
log.Info("")
log.Info(repolist.ReportHeader())
log.Info(me.current.StandardHeader())
log.Info("")
log.Info(repolist.ReleaseReportHeader())
log.Info(me.current.StandardReleaseHeader())
case "/list":
me.forge.PrintHumanTable(me.found)
return
me.repos.View.PrintReport(readonly, onlydirty, perfect)
case "/releaseList":
me.forge.PrintHumanTable(me.found)
return
me.repos.View.PrintReleaseReport(readonly, perfect)
case "/quit":
log.Info("Got URL /quit")
os.Exit(0)
case "/goweblist":
loop := me.repos.View.ReposAll()
for loop.Scan() {
repo := loop.Repo()
lastTag := repo.LastTag()
tag := repo.Status.NewestTag()
gitAge, err := tag.GetDate()
if err != nil {
log.Info(fmt.Sprintf("tag date error", repo.Name()))
}
// if lastTag == "" {
// lastTag = tag.Name()
// }
if repo.ReadOnly() {
if readonly == "true" {
continue
}
}
// dur := time.Since(gitAge)
// log.Info(fmt.Sprintf("%-60s %s %s %s", repo.Name(), lastTag, shell.FormatDuration(dur), lastTag, tag.Name()))
log.Info(fmt.Sprintf("%s %d %s", repo.Name(), gitAge.Unix(), lastTag))
/*
for _, tag := range repo.Tags.ListAll() {
log.Info(fmt.Sprintf("%-60s %s", "", tag.Name()))
}
*/
}
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)
p := fmt.Sprintf(":%d", argv.Port)
p := fmt.Sprintf(":%d", myargs.Port)
log.Println("Running on port", p)
err := http.ListenAndServe(p, nil)

177
main.go
View File

@ -2,49 +2,41 @@ package main
import (
"embed"
"errors"
"fmt"
"os"
"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/gowit"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
var VERSION string
var ARGNAME string = "guireleaser"
//go:embed resources/*
var resources embed.FS
var argv args
var myargs argv
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(&myargs)
// save the ENV var here
me.releaseReasonS = os.Getenv("GUIRELEASE_REASON")
if me.releaseReasonS == "" {
badExit(errors.New("shell ENV GUIRELEASE_REASON not set"))
log.Info("shell ENV GUIRELEASE_REASON not set")
os.Exit(0)
}
// unset the go development ENV var to generate release files
@ -52,20 +44,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
@ -74,58 +62,129 @@ func main() {
homeDir, _ := os.UserHomeDir()
gowork := filepath.Join(homeDir, "go/src/go.work")
if shell.Exists(gowork) {
badExit(errors.New("go.work must be deleted"))
log.Info("go.work must be deleted")
os.Exit(0)
}
/*
// sanity check of things that might be around that mess
// up things later
// check to make sure we have a go.sum here
gosum := filepath.Join(homeDir, "go/src/go.wit.com/apps/guireleaser/go.sum")
if !shell.Exists(gosum) {
log.Info("go.sum must exist here")
os.Exit(0)
}
*/
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()
if myargs.DumpVersions {
gowit.DumpVersions(me.repos.View)
os.Exit(0)
}
// 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.IsReadOnly(repo.GoPath()) {
repo.Status.SetReadOnly(true)
} else {
repo.Status.SetReadOnly(false)
}
if !argv.Force {
os.Exit(-1)
if me.forge.IsPrivate(repo.GoPath()) {
repo.Status.SetPrivate(true)
} else {
repo.Status.SetPrivate(false)
}
}
if me.startRepo == nil {
pwd, _ := os.Getwd()
msg := fmt.Sprint("Can not run if pwd is not a repo", pwd)
badExit(errors.New(msg))
// the repo from the command line
// var myrepo *repolist.RepoRow
// find myself. the guireleaser directory is used as a working scratchpad
// for running go commands that can mess up the go.* files
loop = me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo.GoPath() == "go.wit.com/apps/guireleaser" {
if me.release.guireleaser == nil {
me.release.guireleaser = repo
}
}
log.Info("repolist.ReposSortByName() found", repo.GoPath())
/*
if repo.GoPath() == myargs.Repo {
myrepo = repo
}
*/
}
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")
}
if me.release.guireleaser == nil {
log.Info("Can not release if guireleaser was not found")
os.Exit(0)
}
me.Enable()
me.release.box.Enable()
// start the http server for polling status
startHTTP()
// 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,297 +0,0 @@
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 forceReleaseVersion(repo *gitpb.Repo) {
if argv.Minor {
// if v1.2.3 change to v.1.3.0
repo.IncrementTargetMinor()
} else {
// if v1.2.3 change to v.1.2.4
repo.IncrementTargetRevision()
}
}
func checkpkgcache(repo *gitpb.Repo) error {
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
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
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())
}
}
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())
continue
}
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
// can't release readonly repos
continue
}
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
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"
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)
}
}
}
}
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
}

View File

@ -3,14 +3,16 @@ package main
import (
"fmt"
"time"
"os"
"path/filepath"
"strings"
"go.wit.com/gui"
"go.wit.com/log"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repolist"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/gitpb"
)
type releaseStruct struct {
@ -25,14 +27,19 @@ type releaseStruct struct {
releaseVersionB *gui.Node
reason *gadgets.BasicEntry
// openrepo *gui.Node
openrepo *gui.Node
goGetB *gui.Node
checkGoSumB *gui.Node
checkDirtyB *gui.Node
makeRedomodB *gui.Node
sendVersionB *gui.Node
checkSafeB *gui.Node
// whitelist map[string]*repolist.RepoRow
whitelist map[string]*repolist.RepoRow
// store myself here. use myself to
// do garbage go get tests and other potential junk
guireleaser *repolist.RepoRow
}
func (w *autoType) Disable() {
@ -51,20 +58,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 +73,13 @@ 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() {
me.current.Status.Toggle()
})
me.release.openrepo.Disable()
me.release.grid.NextRow()
me.release.status = gadgets.NewOneLiner(me.release.grid, "status")
me.release.grid.NextRow()
@ -101,79 +97,233 @@ 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)
homeDir, err := os.UserHomeDir()
if err != nil {
log.Warn("Error getting home directory:", err)
homeDir = "/home/autotypist"
}
me.userHomePwd.SetText(homeDir)
srcDir := filepath.Join(homeDir, "go/src")
me.goSrcPwd.SetText(srcDir)
testf := filepath.Join(srcDir, "go.wit.com/apps/guireleaser", "go.sum")
if !shell.Exists(testf) {
pb := me.forge.Repos.FindByGoPath("go.wit.com/apps/guireleaser")
if pb != nil {
pb.RedoGoMod()
}
if !shell.Exists(testf) {
log.Info("go.sum missing", testf)
panic("redo go.sum")
}
}
group := me.release.box.NewGroup("Run on Current Repo")
grid := group.NewGrid("buildOptions", 0, 0)
grid.NewButton("whitelist", func() {
// tmp := me.current.GoState()
log.Info("trying to whitelist repo", me.current.GoPath())
me.current.Status.Whitelist = true
findNext()
})
me.release.checkGoSumB = grid.NewButton("checkValidGoSum()", func() {
buttonDisable()
checkValidGoSum(me.current)
buttonEnable()
})
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() {
var worked bool = true
buttonDisable()
doReleaseAll()
// rather than loop forever, at least limit this to the number of repos
// incase something, somewhere, goes wrong
duration := repolist.TimeFunction(func() {
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
loop.Repo()
if doRelease() {
log.Info("doRelease() worked")
} else {
if os.Getenv("FindNextDone") == "true" {
log.Info("findNext says it was done")
log.Info("findNext says it was done")
log.Info("we can os.Exit here")
}
if me.release.status.String() == "ALL DONE?" {
log.Info("maybe ALL DONE?")
buttonEnable()
worked = true
os.Exit(0)
}
log.Info("doRelease() failed")
worked = false
break
}
}
})
s := fmt.Sprint(duration)
log.Info("release returned", worked, "and ran for", s)
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()
grid.NewButton("git ls-files |grep go.mod", func() {
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
log.Info("repo:", repo.Name())
if repo.Status.ReadOnly() {
continue
}
if repo.Status.Whitelist {
log.Warn("skipping whitelist", repo.GoPath())
continue
}
good, files := repo.Status.GitLsFiles()
if !good {
log.Warn("Something went wrong", repo.GoPath())
continue
}
for _, filename := range strings.Split(files, "\n") {
log.Info("\tfile", filename)
if filename == "go.mod" {
log.Info("Found go.mod. does version match release version?")
log.Info(repo.Status.GetLastTagVersion(), "vs", repo.Status.GetTargetVersion())
if repo.Status.GetLastTagVersion() != repo.Status.GetTargetVersion() {
log.Info(repo.Status.GetLastTagVersion(), "vs", repo.Status.GetTargetVersion())
log.Info("Found go.sum. version mismatch")
setCurrentRepo(repo, "VERY BROKEN", "rewind go.mod commit")
return
}
}
if filename == "go.sum" {
log.Info("Found go.sum. does version match release version?")
log.Info(repo.Status.GetLastTagVersion(), "vs", repo.Status.GetTargetVersion())
if repo.Status.GetLastTagVersion() != repo.Status.GetTargetVersion() {
log.Info(repo.Status.GetLastTagVersion(), "vs", repo.Status.GetTargetVersion())
log.Info("Found go.sum. version mismatch")
setCurrentRepo(repo, "VERY BROKEN", "rewind go.mod commit")
return
}
}
}
}
log.Info("All repos seem okay")
})
grid.NextRow()
var longB *gui.Node
longB = grid.NewButton("generate go.sum files", func() {
me.Disable()
var worked bool = true
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo.Status.Whitelist {
continue
}
ok, err := me.repos.View.CheckValidGoSum(repo)
if !ok {
log.Info("redo go.sum failed on", repo.GoPath(), err)
worked = false
}
}
log.Info("redo go.sum finished with", worked)
me.Enable()
longB.SetLabel("go.sum files created")
if worked {
longB.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
}
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
}
func buttonDisable() {
me.Disable()
me.release.box.Disable()
}
func buttonEnable() {
me.Enable()
me.release.box.Enable()
}
func setCurrentRepo(newcur *repolist.RepoRow, s string, note string) bool {
if newcur.ReadOnly() {
return false
}
me.release.repo.SetText(newcur.GoPath())
me.release.status.SetText(s)
me.release.notes.SetText(note)
me.current = newcur
me.release.version.SetText(me.current.Status.GetTargetVersion())
me.release.releaseVersionB.SetText("release version " + me.current.Status.GetTargetVersion())
me.release.openrepo.Enable()
return true
}
// 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 {
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo.Status.IsReleased() {
continue
}
if repo.Status.Whitelist {
continue
}
if repo.ReadOnly() {
// log.Info("findNext() skipping readonly")
continue
}
if repo.CheckDirty() {
log.Info("findNext() skipping dirty")
continue
}
// do makeredomod here
// if ! repo.Status.Exists("go.sum") {
// }
if repo.Status.IsPrimitive() {
log.Info("findNext()", repo.GoPath())
if setCurrentRepo(repo, "PRIMATIVE", "release new version") {
return true
}
continue
}
log.Info("findNext()", repo.GoPath(), "is not a primative repo")
if checkValidGoSum(repo) {
setCurrentRepo(repo, "should be good to release", "pretty sure")
return true
}
}
log.Info("tried to findNext() but not sure what to do next")
me.release.status.SetText("ALL DONE?")
return false
}

79
repoview.go Normal file
View File

@ -0,0 +1,79 @@
package main
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/gowit"
"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()
box2 := hbox.Box().Vertical()
box2.NewButton("Dump version file", func() {
gowit.DumpVersions(me.repos.View)
})
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

78
setTargetVersion.go Normal file
View File

@ -0,0 +1,78 @@
package main
import (
"os"
"strings"
"go.wit.com/log"
)
func setTargetVersion() {
// go through and set the target versions for each repo
// todo: add sanity checking in repolist to verify these and/or autocompute them
// for now, just don't be stupid when you set your ENV vars
// widget I versioned early before I knew what the hell this would mean and can
// not be down versioned because that's not how GO versioning works. Once you
// set the version for a path, it's set in stone forever. (smart system!)
// we could rename go.wit.com/widget to go.wit.com/newwidget and restart the versioning
// system, but that's rediculous and this servers to always remind me to never make this mistake again
var count int
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo == nil {
log.Info("initial scan repo = nil")
continue
}
if repo.Status == nil {
log.Info("repo.status == nil", repo.Name())
continue
}
if repo.GoPath() == "go.wit.com/widget" {
repo.Status.SetTargetVersion("v" + os.Getenv("GUIRELEASE_WIDGET"))
} else {
prefix := "v" + os.Getenv("GUIRELEASE_VERSION")
lasttag := repo.Status.LastTag()
if strings.HasPrefix(lasttag, prefix) {
repo.Status.SetTargetVersion(lasttag)
} else {
repo.Status.SetTargetVersion(prefix)
}
}
if strings.HasPrefix(repo.GoPath(), "go.wit.com/dev/") {
lasttag := repo.Status.GetLastTagVersion()
repo.Status.SetTargetVersion(lasttag)
}
// repo.NewScan()
count += 1
}
log.Info("target versions set for", count, "repos")
}
// trys to figure out if the version needs to be incremented
func incrementTargetVersion() bool {
var count int
loop := me.repos.View.ReposSortByName()
for loop.Scan() {
repo := loop.Repo()
if repo.ReadOnly() {
continue
}
lasttag := repo.Status.GetLastTagVersion()
master := repo.Status.GetMasterVersion()
if lasttag != master {
log.Info("increment target version", repo.GoPath(), lasttag, master)
count += 1
} else {
// check go dependancies for target version changes
}
}
log.Info("need to update target versions for", count, "repos")
if count == 0 {
return true
}
return false
}

View File

@ -2,39 +2,54 @@
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/gui/repolist"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
)
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
// this is the repo we are starting in
// make sure it never changes so go.mod and go.sum are always there
// 'go get' is called from here
startRepo *gitpb.Repo
releaseReasonS string // = "gocui dropdown select"
release releaseStruct
reposbox *gui.Node
reposgrid *gui.Node
reposgroup *gui.Node
current *repolist.RepoRow
// 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
@ -45,6 +60,9 @@ type autoType struct {
// The current working directory
autoWorkingPwd *gadgets.OneLiner
// shows what is being used as your home dir
userHomePwd *gadgets.OneLiner
// shows what directory being used as ~/go/src
goSrcPwd *gadgets.OneLiner
@ -60,3 +78,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()
}
*/

46
tempView.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repolist"
"go.wit.com/log"
)
func makeTempView() *repoWindow {
r := new(repoWindow)
r.win = gadgets.RawBasicWindow("unmerged repositories")
r.win.Make()
r.box = r.win.Box().NewBox("bw vbox", false)
r.win.Custom = func() {
log.Warn("GOT HERE: makeTempView() close")
log.Warn("GOT HERE: makeTempView() 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()
box2 := hbox.Box().Vertical()
box2.NewButton("merge user to devel", func() {
log.Warn("todo")
})
box2.NewButton("merge devel to master", func() {
log.Warn("todo")
})
box2.NewButton("rescan values", func() {
log.Warn("figure this out")
r.View.ListRows()
// for _, repo := range r.View.AllRepos() {
// log.Warn("repo:", repo.Name())
// }
})
r.View = repolist.TempWindowView(r.box)
r.Show()
return r
}