Skip to content

Commit

Permalink
Check for updates on startup (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
amalshaji authored Nov 28, 2024
1 parent a299f2c commit 2e30f9f
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 3 deletions.
23 changes: 23 additions & 0 deletions tunnel/cmd/portr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ func main() {
os.Exit(0)
}

// for debugging cli commands
// because the config file is not loaded when this is set
debugForCli := os.Getenv("DEBUG_FOR_CLI") == "1"

go func() {
if err := checkForUpdates(); err != nil {
if debugForCli {
fmt.Println(color.Red(err.Error()))
}
}
}()

versionToUpdate, err := getVersionToUpdate()
if err != nil {
if debugForCli {
fmt.Println(color.Red(err.Error()))
}
} else {
if versionToUpdate != "" {
fmt.Printf(color.Yellow("A new version of Portr is available: %s. https://github.com/amalshaji/portr/releases/tag/%s\n"), versionToUpdate, versionToUpdate)
}
}

if err := app.Run(os.Args); err != nil {
fmt.Println(color.Red(err.Error()))
os.Exit(0)
Expand Down
165 changes: 165 additions & 0 deletions tunnel/cmd/portr/updates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package main

import (
"encoding/json"
"net/http"
"os"
"time"

"github.com/Masterminds/semver"
"github.com/amalshaji/portr/internal/client/config"
"github.com/go-resty/resty/v2"
)

var UpdatesFilePath = config.DefaultConfigDir + "/updates.json"

type GithubRelease struct {
TagName string `json:"tag_name"`
}

type UpdateInfo struct {
CheckedAt time.Time `json:"checked_at"`
Version string `json:"version"`
}

func createUpdatesFileIfNotExists() error {
if _, err := os.Stat(UpdatesFilePath); err != nil {
if os.IsNotExist(err) {
f, err := os.Create(UpdatesFilePath)
if err != nil {
return err
}
defer f.Close()

if _, err := f.WriteString("{}"); err != nil {
return err
}
} else {
return err
}
}

return nil
}

func getUpdateState() (UpdateInfo, error) {
data, err := os.ReadFile(UpdatesFilePath)
if err != nil {
return UpdateInfo{}, err
}

var updateInfo UpdateInfo
err = json.Unmarshal(data, &updateInfo)
if err != nil {
return UpdateInfo{}, err
}

return updateInfo, nil
}

func checkForUpdates() error {
if err := createUpdatesFileIfNotExists(); err != nil {
return err
}

updateInfo, err := getUpdateState()
if err != nil {
return err
}

if updateInfo.Version == "" {
return getLatestRelease()
}

currentVersion, err := semver.NewVersion(VERSION)
if err != nil {
return err
}

lastCheckedVersion, err := semver.NewVersion(updateInfo.Version)
if err != nil {
return err
}

if updateInfo.CheckedAt.Before(time.Now().Add(-24*time.Hour)) && currentVersion.Equal(lastCheckedVersion) {
return getLatestRelease()
}

return nil
}

func getLatestRelease() error {
if err := createUpdatesFileIfNotExists(); err != nil {
return err
}

var lastCheck UpdateInfo
data, err := os.ReadFile(UpdatesFilePath)
if err != nil {
return err
}

err = json.Unmarshal(data, &lastCheck)
if err != nil {
return err
}

if time.Since(lastCheck.CheckedAt) < 24*time.Hour {
return nil
}

client := resty.New()

var release GithubRelease
resp, err := client.R().SetResult(&release).Get("https://api.github.com/repos/amalshaji/portr/releases/latest")
if err != nil {
return err
}

if resp.StatusCode() != http.StatusOK {
return err
}

updateInfo := UpdateInfo{
CheckedAt: time.Now().UTC(),
Version: release.TagName,
}

data, err = json.Marshal(updateInfo)
if err != nil {
return err
}

if err := os.WriteFile(UpdatesFilePath, data, 0644); err != nil {
return err
}

return nil
}

func getVersionToUpdate() (string, error) {
updateInfo, err := getUpdateState()
if err != nil {
return "", err
}

if updateInfo.Version == "" {
return "", nil
}

currentVersion, err := semver.NewVersion(VERSION)
if err != nil {
return "", err
}

latestVersion, err := semver.NewVersion(updateInfo.Version)
if err != nil {
return "", err
}

if currentVersion.LessThan(latestVersion) {
return updateInfo.Version, nil
}

return "", nil
}
3 changes: 2 additions & 1 deletion tunnel/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/amalshaji/portr
go 1.22.0

require (
github.com/Masterminds/semver v1.5.0
github.com/charmbracelet/log v0.4.0
github.com/glebarez/sqlite v1.11.0
github.com/gliderlabs/ssh v0.3.7
Expand Down Expand Up @@ -69,7 +70,7 @@ require (
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.14.0 // indirect
gorm.io/driver/mysql v1.5.6 // indirect
modernc.org/libc v1.49.3 // indirect
Expand Down
6 changes: 4 additions & 2 deletions tunnel/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
Expand Down Expand Up @@ -172,8 +174,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
Expand Down

0 comments on commit 2e30f9f

Please sign in to comment.