Skip to content

Commit c622b58

Browse files
authored
feat: auto update (#118)
1 parent 9ee1ef9 commit c622b58

File tree

6 files changed

+371
-16
lines changed

6 files changed

+371
-16
lines changed

cmd/config.go

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ var configCmd = &cobra.Command{
1717
Configuration is stored in ~/.config/tusk/cli.json
1818
1919
Available configuration keys:
20-
analytics Enable or disable usage analytics (true/false)
21-
darkMode Dark mode for terminal output (true/false)
20+
analytics Enable or disable usage analytics (true/false)
21+
darkMode Dark mode for terminal output (true/false)
22+
autoUpdate Automatically update without prompting (true/false)
23+
autoCheckUpdates Check for updates on startup (true/false, default: true)
2224
2325
Examples:
24-
tusk config get analytics # Show current analytics setting
25-
tusk config set analytics false # Disable analytics
26-
tusk config get darkMode # Show current dark mode setting
27-
tusk config set darkMode true # Enable dark mode
28-
tusk config set darkMode false # Disable dark mode`,
26+
tusk config get analytics # Show current analytics setting
27+
tusk config set analytics false # Disable analytics
28+
tusk config set autoUpdate true # Enable automatic updates
29+
tusk config set autoCheckUpdates false # Disable update checking`,
2930
Run: func(cmd *cobra.Command, args []string) {
3031
_ = cmd.Help()
3132
},
@@ -37,8 +38,10 @@ var configGetCmd = &cobra.Command{
3738
Long: `Get the current value of a configuration key.
3839
3940
Available keys:
40-
analytics Usage analytics setting
41-
darkMode Dark mode setting`,
41+
analytics Usage analytics setting
42+
darkMode Dark mode setting
43+
autoUpdate Automatic update setting
44+
autoCheckUpdates Update checking setting`,
4245
Args: cobra.ExactArgs(1),
4346
RunE: func(cmd *cobra.Command, args []string) error {
4447
key := args[0]
@@ -53,8 +56,17 @@ Available keys:
5356
} else {
5457
fmt.Println("unset")
5558
}
59+
case "autoupdate":
60+
fmt.Println(cfg.AutoUpdate)
61+
case "autocheckupdates":
62+
// nil means true (default)
63+
if cfg.AutoCheckUpdates != nil {
64+
fmt.Println(*cfg.AutoCheckUpdates)
65+
} else {
66+
fmt.Println(true)
67+
}
5668
default:
57-
return fmt.Errorf("unknown config key: %s\n\nAvailable keys: analytics, darkMode", key)
69+
return fmt.Errorf("unknown config key: %s\n\nAvailable keys: analytics, darkMode, autoUpdate, autoCheckUpdates", key)
5870
}
5971

6072
return nil
@@ -67,12 +79,14 @@ var configSetCmd = &cobra.Command{
6779
Long: `Set the value of a configuration key.
6880
6981
Available keys and values:
70-
analytics true/false Enable or disable usage analytics
71-
darkMode true/false Dark mode for terminal output
82+
analytics true/false Enable or disable usage analytics
83+
darkMode true/false Dark mode for terminal output
84+
autoUpdate true/false Automatically update without prompting
85+
autoCheckUpdates true/false Check for updates on startup (default: true)
7286
7387
Examples:
7488
tusk config set analytics false
75-
tusk config set darkMode true`,
89+
tusk config set autoUpdate true`,
7690
Args: cobra.ExactArgs(2),
7791
RunE: func(cmd *cobra.Command, args []string) error {
7892
key := args[0]
@@ -96,8 +110,20 @@ Examples:
96110
return fmt.Errorf("invalid value for darkMode: %s (expected true/false)", value)
97111
}
98112
cfg.DarkMode = &boolVal
113+
case "autoupdate":
114+
boolVal, err := parseBool(value)
115+
if err != nil {
116+
return fmt.Errorf("invalid value for autoUpdate: %s (expected true/false)", value)
117+
}
118+
cfg.AutoUpdate = boolVal
119+
case "autocheckupdates":
120+
boolVal, err := parseBool(value)
121+
if err != nil {
122+
return fmt.Errorf("invalid value for autoCheckUpdates: %s (expected true/false)", value)
123+
}
124+
cfg.AutoCheckUpdates = &boolVal
99125
default:
100-
return fmt.Errorf("unknown config key: %s\n\nAvailable keys: analytics, darkMode", key)
126+
return fmt.Errorf("unknown config key: %s\n\nAvailable keys: analytics, darkMode, autoUpdate, autoCheckUpdates", key)
101127
}
102128

103129
if err := cfg.Save(); err != nil {

cmd/root.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"context"
45
_ "embed"
56
"fmt"
67
"log/slog"
@@ -10,6 +11,7 @@ import (
1011
"syscall"
1112

1213
"github.com/Use-Tusk/tusk-drift-cli/internal/analytics"
14+
"github.com/Use-Tusk/tusk-drift-cli/internal/cliconfig"
1315
"github.com/Use-Tusk/tusk-drift-cli/internal/log"
1416
"github.com/Use-Tusk/tusk-drift-cli/internal/tui/styles"
1517
"github.com/Use-Tusk/tusk-drift-cli/internal/utils"
@@ -130,6 +132,23 @@ func showASCIIArt() {
130132
fmt.Print("\n\n")
131133

132134
fmt.Println("Use \"tusk --help\" for more information about available commands.")
135+
136+
cfg := cliconfig.CLIConfig
137+
autoCheck := cfg.AutoCheckUpdates == nil || *cfg.AutoCheckUpdates
138+
if !autoCheck && !cfg.AutoUpdate {
139+
return
140+
}
141+
142+
release, err := version.CheckForUpdate(context.Background())
143+
if err != nil || release == nil {
144+
return
145+
}
146+
147+
if cfg.AutoUpdate {
148+
version.AutoUpdate(release)
149+
} else {
150+
version.PromptAndUpdate(release)
151+
}
133152
}
134153

135154
func init() {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ require (
2525
github.com/spf13/cobra v1.10.1
2626
github.com/spf13/pflag v1.0.10
2727
github.com/stretchr/testify v1.11.1
28+
golang.org/x/mod v0.27.0
2829
golang.org/x/term v0.31.0
2930
google.golang.org/protobuf v1.36.9
3031
gopkg.in/yaml.v3 v3.0.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
155155
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
156156
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
157157
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
158+
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
159+
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
158160
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
159161
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
160162
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

internal/cliconfig/config.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ var CLIConfig *Config
4141
// Config represents the user-level CLI configuration stored at ~/.config/tusk/cli.json
4242
type Config struct {
4343
// User settings (configurable via `tusk config`)
44-
AnalyticsEnabled bool `json:"analytics_enabled"` // Default true, enable usage analytics
45-
DarkMode *bool `json:"dark_mode"` // nil = auto-detect, true/false = forced
44+
AnalyticsEnabled bool `json:"analytics_enabled"` // Default true, enable usage analytics
45+
DarkMode *bool `json:"dark_mode"` // nil = auto-detect, true/false = forced
46+
AutoUpdate bool `json:"auto_update"` // Default false, auto-update without prompting
47+
AutoCheckUpdates *bool `json:"auto_check_updates"` // Default true (nil = true), check for updates on startup
4648

4749
// Analytics internals
4850
AnonymousID string `json:"anonymous_id"` // "cli-anon-<uuid>" generated on first run

0 commit comments

Comments
 (0)