Skip to content

Commit ade01eb

Browse files
fullstackjamclaude
andauthored
refactor(updater): default auto-update to notify-only (#35)
Auto-upgrades are a piece of remote-driven control state: they can silently change what `openboot <same command>` does from one run to the next. For a tool that people run occasionally rather than daily, that tradeoff isn't worth it — a visible "new version available" notice is enough. LoadUserConfig now defaults to AutoUpdateNotify. Users who want the previous silent self-upgrade behavior can still opt in by setting "autoupdate": "true" in ~/.openboot/config.json; "false" still fully silences the check. Tests updated to match the new default. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7a34362 commit ade01eb

File tree

4 files changed

+18
-12
lines changed

4 files changed

+18
-12
lines changed

internal/updater/updater.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,13 @@ type UserConfig struct {
5252
AutoUpdate AutoUpdateMode `json:"autoupdate"`
5353
}
5454

55+
// LoadUserConfig returns the user's update preference from
56+
// ~/.openboot/config.json. The default is AutoUpdateNotify: we surface a
57+
// one-line "new version available" message but never auto-upgrade the binary
58+
// during a normal command. Users who want silent upgrades can opt in by
59+
// setting "autoupdate": "true"; users who want silence can set "false".
5560
func LoadUserConfig() UserConfig {
56-
cfg := UserConfig{AutoUpdate: AutoUpdateEnabled}
61+
cfg := UserConfig{AutoUpdate: AutoUpdateNotify}
5762
path, err := getUserConfigPath()
5863
if err != nil {
5964
return cfg
@@ -66,7 +71,7 @@ func LoadUserConfig() UserConfig {
6671
return cfg
6772
}
6873
if cfg.AutoUpdate == "" {
69-
cfg.AutoUpdate = AutoUpdateEnabled
74+
cfg.AutoUpdate = AutoUpdateNotify
7075
}
7176
return cfg
7277
}
@@ -98,15 +103,16 @@ func IsHomebrewInstall() bool {
98103
return isHomebrewPath(exe)
99104
}
100105

101-
// AutoUpgrade checks for a newer version and upgrades if appropriate.
106+
// AutoUpgrade checks for a newer version and, by default, only prints a notice.
107+
// Silent self-upgrades are opt-in via ~/.openboot/config.json.
102108
//
103109
// Flow:
104110
// 1. Kill switch: OPENBOOT_DISABLE_AUTOUPDATE=1
105111
// 2. Dev guard: currentVersion == "dev"
106112
// 3. UserConfig (applies to ALL install methods):
107-
// disabled → exit, notify → show message, enabled → upgrade
113+
// disabled → exit, notify (default) → show message, enabled → upgrade
108114
// 4. resolveLatestVersion: uses 24h cache, falls back to sync GitHub API
109-
// 5. Upgrade method: Homebrew → brew upgrade, Direct → download binary
115+
// 5. Upgrade method (enabled mode only): Homebrew → brew upgrade, Direct → download binary
110116
func AutoUpgrade(currentVersion string) {
111117
if os.Getenv("OPENBOOT_DISABLE_AUTOUPDATE") == "1" {
112118
return

internal/updater/updater_extra_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ func TestIsNewerVersion_ExtendedCases(t *testing.T) {
250250
}
251251

252252
// ---------------------------------------------------------------------------
253-
// LoadUserConfig — AutoUpdate empty field defaults to Enabled
253+
// LoadUserConfig — AutoUpdate empty field defaults to Notify
254254
// ---------------------------------------------------------------------------
255255

256256
func TestLoadUserConfig_DefaultWhenMissing(t *testing.T) {
257257
t.Setenv("HOME", t.TempDir())
258258
cfg := LoadUserConfig()
259-
assert.Equal(t, AutoUpdateEnabled, cfg.AutoUpdate)
259+
assert.Equal(t, AutoUpdateNotify, cfg.AutoUpdate)
260260
}
261261

262262
// ---------------------------------------------------------------------------

internal/updater/updater_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func TestGetUserConfigPath(t *testing.T) {
212212
func TestLoadUserConfig_Default_NoFile(t *testing.T) {
213213
t.Setenv("HOME", t.TempDir())
214214
cfg := LoadUserConfig()
215-
assert.Equal(t, AutoUpdateEnabled, cfg.AutoUpdate)
215+
assert.Equal(t, AutoUpdateNotify, cfg.AutoUpdate)
216216
}
217217

218218
func TestLoadUserConfig_FromFile(t *testing.T) {
@@ -236,7 +236,7 @@ func TestLoadUserConfig_InvalidJSON(t *testing.T) {
236236
require.NoError(t, os.WriteFile(filepath.Join(cfgDir, "config.json"), []byte("{bad json"), 0644))
237237

238238
cfg := LoadUserConfig()
239-
assert.Equal(t, AutoUpdateEnabled, cfg.AutoUpdate)
239+
assert.Equal(t, AutoUpdateNotify, cfg.AutoUpdate)
240240
}
241241

242242
func TestLoadUserConfig_EmptyAutoUpdate(t *testing.T) {
@@ -247,7 +247,7 @@ func TestLoadUserConfig_EmptyAutoUpdate(t *testing.T) {
247247
require.NoError(t, os.WriteFile(filepath.Join(cfgDir, "config.json"), []byte(`{"autoupdate":""}`), 0644))
248248

249249
cfg := LoadUserConfig()
250-
assert.Equal(t, AutoUpdateEnabled, cfg.AutoUpdate)
250+
assert.Equal(t, AutoUpdateNotify, cfg.AutoUpdate)
251251
}
252252

253253
func TestLoadUserConfig_DisabledMode(t *testing.T) {

test/integration/updater_integration_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ func TestIntegration_Updater_LoadUserConfig_Default(t *testing.T) {
8383
// When: we load user config
8484
cfg := updater.LoadUserConfig()
8585

86-
// Then: defaults to auto-update enabled
87-
assert.Equal(t, updater.AutoUpdateEnabled, cfg.AutoUpdate)
86+
// Then: defaults to notify-only (no silent self-upgrades).
87+
assert.Equal(t, updater.AutoUpdateNotify, cfg.AutoUpdate)
8888
}
8989

9090
func TestIntegration_Updater_LoadUserConfig_AllModes(t *testing.T) {

0 commit comments

Comments
 (0)