From 800d3df18b17f94bd872717f36c6ba63b77ffe9c Mon Sep 17 00:00:00 2001 From: Stuart Leeks Date: Thu, 5 Jun 2025 14:54:57 +0000 Subject: [PATCH 1/2] Change the update process to be async This improves the usability when offline or on a a slow connection and an update check is due --- .gitignore | 1 + go.mod | 9 ++--- go.sum | 27 +++++++-------- main.go | 96 +++++++++++++++++++++++++++++------------------------- 4 files changed, 65 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 2c2ee49..14fd583 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ pick-a-browser.exe +.pick-a-browser.exe.old dist/** diff --git a/go.mod b/go.mod index 213ef48..3183b9b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/rhysd/go-github-selfupdate v1.2.3 github.com/sirupsen/logrus v1.8.1 github.com/tidwall/jsonc v0.3.2 - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 + golang.org/x/sys v0.5.0 gotest.tools v2.2.0+incompatible ) @@ -19,16 +19,11 @@ require ( github.com/google/go-github/v30 v30.1.0 // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect - github.com/kyoh86/richgo v0.3.11 // indirect - github.com/kyoh86/xdg v1.2.0 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/stretchr/testify v1.4.0 // indirect + github.com/stretchr/testify v1.8.2 // indirect github.com/tcnksm/go-gitconfig v0.1.2 // indirect github.com/ulikunitz/xz v0.5.9 // indirect - github.com/wacul/ptr v1.0.0 // indirect golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 // indirect diff --git a/go.sum b/go.sum index 1bcda8f..03cbf19 100644 --- a/go.sum +++ b/go.sum @@ -21,18 +21,10 @@ github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kyoh86/richgo v0.3.11 h1:Y8ro+7M1GOWAHR+vSPuaN+Kg5C9SM0FotcgKauD7lmA= -github.com/kyoh86/richgo v0.3.11/go.mod h1:M7fIBc+Qx+S4NBNAVW7GQJQnRv3IRLWhfwlL3fNYD1I= -github.com/kyoh86/xdg v1.2.0 h1:CERuT/ShdTDj+A2UaX3hQ3mOV369+Sj+wyn2nIRIIkI= -github.com/kyoh86/xdg v1.2.0/go.mod h1:/mg8zwu1+qe76oTFUBnyS7rJzk7LLC0VGEzJyJ19DHs= github.com/lxn/walk v0.0.0-20210112085537-c389da54e794 h1:NVRJ0Uy0SOFcXSKLsS65OmI1sgCCfiDUPj+cwnH7GZw= github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -43,9 +35,13 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stuartleeks/go-github-selfupdate v1.2.4 h1:NouxmmBBSSZNK7SG+16YGqqYMYGADJxCVzk6BwuS/l0= github.com/stuartleeks/go-github-selfupdate v1.2.4/go.mod h1:mp/N8zj6jFfBQy/XMYoWsmfzxazpPAODuqarmPDe2Rg= github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw= @@ -54,8 +50,6 @@ github.com/tidwall/jsonc v0.3.2 h1:ZTKrmejRlAJYdn0kcaFqRAKlxxFIC21pYq8vLa4p2Wc= github.com/tidwall/jsonc v0.3.2/go.mod h1:dw+3CIxqHi+t8eFSpzzMlcVYxKp08UP5CD8/uSFCyJE= github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/wacul/ptr v1.0.0 h1:FIKu08Wx0YUIf9MNsfF62OCmBSmz5A1Tk65zWhOIL/I= -github.com/wacul/ptr v1.0.0/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -72,9 +66,8 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= @@ -92,8 +85,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/main.go b/main.go index cbf6992..c935195 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ package main import ( "fmt" "os" - "os/exec" "path/filepath" "strings" "time" @@ -101,21 +100,15 @@ func main() { return } - updated, err := PerformUpdateCheck(settings) - if err != nil { - logger.Errorln("UpdateCheck failed", err) - walk.MsgBox(nil, "pick-a-browser error...", fmt.Sprintf("Failed to update:\n%s", err), walk.MsgBoxOK|walk.MsgBoxIconError) - } - if updated { - // launch the updated exe with original args and exit - cmd := exec.Command(os.Args[0], args...) - logger.Infoln("Updated - re-launching...") - if err = cmd.Start(); err != nil { - logger.Errorln("Error re-launching after update", err) - walk.MsgBox(nil, "pick-a-browser error...", fmt.Sprintf("Failed to re-launch after update:\n%s", err), walk.MsgBoxOK|walk.MsgBoxIconError) + updateCheckCompleted := make(chan bool, 1) + go func() { + _, err := PerformUpdateCheck(settings, logger) + if err != nil { + logger.Errorln("UpdateCheck failed", err) + walk.MsgBox(nil, "pick-a-browser error...", fmt.Sprintf("Failed to update:\n%s", err), walk.MsgBoxOK|walk.MsgBoxIconError) } - return - } + updateCheckCompleted <- true + }() url := "" if len(args) == 1 { @@ -127,50 +120,63 @@ func main() { logger.Errorln("HandleUrl failed", err) walk.MsgBox(nil, "pick-a-browser error...", fmt.Sprintf("Error handling URL:\n%s", err), walk.MsgBoxOK|walk.MsgBoxIconError) } + + // ensure the update check is completed before exiting + <-updateCheckCompleted } -func PerformUpdateCheck(settings *config.Settings) (bool, error) { +func PerformUpdateCheck(settings *config.Settings, logger *log.Entry) (bool, error) { state, err := appstate.Load() if err != nil { return false, err } if settings.UpdateCheck == config.UpdateCheckAuto || settings.UpdateCheck == config.UpdateCheckPrompt { - if time.Now().After(state.LastUpdateCheck.Add(updateCheckInterval)) { - latest, err := CheckForUpdate(version) - if err != nil { - return false, err - } - state.LastUpdateCheck = time.Now().UTC() - if err = appstate.Save(state); err != nil { - return false, fmt.Errorf("error checking for updates:\n%s", err) - } - - if latest == nil { - return false, nil - } + if time.Now().Before(state.LastUpdateCheck.Add(updateCheckInterval)) { + logger.Debugln("Skipping update check, within interval") + return false, nil // skip update check if within interval + } + logger.Debugln("Performing update check...") + latest, err := CheckForUpdate(version) + if err != nil { + logger.Errorln("Error checking for updates:", err) + return false, err + } + state.LastUpdateCheck = time.Now().UTC() + if err = appstate.Save(state); err != nil { + logger.Errorln("Error saving app state:", err) + return false, fmt.Errorf("error saving app state:\n%s", err) + } - // apply on auto - apply := settings.UpdateCheck == config.UpdateCheckAuto - if settings.UpdateCheck == config.UpdateCheckPrompt { - result := walk.MsgBox(nil, "pick-a-browser update...", fmt.Sprintf("Version %s is available\n\n Update?", latest.Version), walk.MsgBoxYesNo|walk.MsgBoxIconQuestion) - apply = result == walk.DlgCmdYes - } + if latest == nil { + logger.Debugln("No updates available") + return false, nil + } - if apply { - exe, err := os.Executable() - if err != nil { - return false, fmt.Errorf("failed to locate executable:\n%s", err) - } - if err := selfupdate.NoGitUpdater().UpdateTo(latest, exe); err != nil { - return false, fmt.Errorf("failed to perform update:\n%s", err) - } + // apply on auto + apply := settings.UpdateCheck == config.UpdateCheckAuto + if settings.UpdateCheck == config.UpdateCheckPrompt { + logger.Debugln("Asking user whether to update...") + result := walk.MsgBox(nil, "pick-a-browser update...", fmt.Sprintf("Version %s is available\n\n Update?", latest.Version), walk.MsgBoxYesNo|walk.MsgBoxIconQuestion) + apply = result == walk.DlgCmdYes + } - walk.MsgBox(nil, "pick-a-browser...", fmt.Sprintf("Successfully updated to version %s", latest.Version), walk.MsgBoxOK) - return true, nil + if apply { + logger.Infoln("Updating to version", latest.Version) + exe, err := os.Executable() + if err != nil { + return false, fmt.Errorf("failed to locate executable:\n%s", err) } + if err := selfupdate.NoGitUpdater().UpdateTo(latest, exe); err != nil { + return false, fmt.Errorf("failed to perform update:\n%s", err) + } + + logger.Infoln("Update applied successfully", latest.Version) + walk.MsgBox(nil, "pick-a-browser...", fmt.Sprintf("Successfully updated to version %s", latest.Version), walk.MsgBoxOK) + return true, nil } } + logger.Debugln("No updates applied") return false, nil } From 5dd342de5174cd4b3295c5d7ae33184746d7dcb0 Mon Sep 17 00:00:00 2001 From: Stuart Leeks Date: Thu, 5 Jun 2025 16:01:22 +0000 Subject: [PATCH 2/2] update devcontainers/ci task --- .github/workflows/ci-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 37b26e2..a4bdcfb 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -27,7 +27,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and run CLI - uses: devcontainers/ci@v0.2 + uses: devcontainers/ci@v0.3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BUILD_NUMBER: ${{ github.run_id }}