Skip to content

Commit c2c096b

Browse files
authored
fix: improve version handling in update command hints to avoid stale resolutions with go install update (#47)
1 parent ff8ec6b commit c2c096b

3 files changed

Lines changed: 29 additions & 17 deletions

File tree

internal/selfupdate.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,12 @@ func RunUpdate(ctx context.Context, currentVersion string, opts UpdateOptions) e
240240
[]string{"upgrade", "tdl"})
241241

242242
case InstallMethodGoInstall:
243-
ref := "latest"
244-
if opts.TargetVersion != "" {
245-
ref = "v" + strings.TrimPrefix(opts.TargetVersion, "v")
246-
}
243+
// Pin to the explicit version we just resolved via the GitHub API
244+
// rather than letting `go install` resolve "@latest" itself. The Go
245+
// module proxy caches "@latest" and can serve a stale version right
246+
// after a release, which would silently re-install the current
247+
// version and cause the update prompt to loop.
248+
ref := "v" + strings.TrimPrefix(targetVersion, "v")
247249
return updateViaCommand(ctx, "go", opts, currentVersion, targetVersion,
248250
[]string{"install", "github.com/ThreeDotsLabs/cli/tdl@" + ref})
249251

internal/update.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func showBlockingUpdatePrompt(updateInfo UpdateInfo, currentVersion string) {
184184
}
185185
}
186186

187-
hint := updateCommandHint(method)
187+
hint := updateCommandHint(method, updateInfo.AvailableVersion)
188188
action := "update now"
189189
if hint != "" {
190190
action = fmt.Sprintf("run %s", SprintCommand(hint))
@@ -225,12 +225,18 @@ func showBlockingUpdatePrompt(updateInfo UpdateInfo, currentVersion string) {
225225
os.Exit(0)
226226
}
227227

228-
func updateCommandHint(method InstallMethod) string {
228+
func updateCommandHint(method InstallMethod, availableVersion string) string {
229229
switch method {
230230
case InstallMethodHomebrew:
231231
return "brew upgrade tdl"
232232
case InstallMethodGoInstall:
233-
return "go install github.com/ThreeDotsLabs/cli/tdl@latest"
233+
// Pin to the explicit version when we know it so copy-pasting the
234+
// hint does not hit a stale "@latest" resolution in the Go proxy.
235+
ref := "latest"
236+
if availableVersion != "" {
237+
ref = "v" + strings.TrimPrefix(availableVersion, "v")
238+
}
239+
return "go install github.com/ThreeDotsLabs/cli/tdl@" + ref
234240
case InstallMethodNix:
235241
return "nix profile upgrade --flake github:ThreeDotsLabs/cli"
236242
case InstallMethodScoop:

internal/update_test.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,24 @@ func TestShouldShowBlockingPrompt(t *testing.T) {
4747

4848
func TestUpdateCommandHint(t *testing.T) {
4949
tests := []struct {
50-
method InstallMethod
51-
expected string
50+
name string
51+
method InstallMethod
52+
availableVersion string
53+
expected string
5254
}{
53-
{InstallMethodHomebrew, "brew upgrade tdl"},
54-
{InstallMethodGoInstall, "go install github.com/ThreeDotsLabs/cli/tdl@latest"},
55-
{InstallMethodNix, "nix profile upgrade --flake github:ThreeDotsLabs/cli"},
56-
{InstallMethodScoop, "scoop update tdl"},
57-
{InstallMethodDirectBinary, ""},
58-
{InstallMethodUnknown, ""},
55+
{"homebrew", InstallMethodHomebrew, "1.2.0", "brew upgrade tdl"},
56+
{"go install with version", InstallMethodGoInstall, "1.2.0", "go install github.com/ThreeDotsLabs/cli/tdl@v1.2.0"},
57+
{"go install with v-prefixed version", InstallMethodGoInstall, "v1.2.0", "go install github.com/ThreeDotsLabs/cli/tdl@v1.2.0"},
58+
{"go install without version falls back to latest", InstallMethodGoInstall, "", "go install github.com/ThreeDotsLabs/cli/tdl@latest"},
59+
{"nix", InstallMethodNix, "1.2.0", "nix profile upgrade --flake github:ThreeDotsLabs/cli"},
60+
{"scoop", InstallMethodScoop, "1.2.0", "scoop update tdl"},
61+
{"direct binary", InstallMethodDirectBinary, "1.2.0", ""},
62+
{"unknown", InstallMethodUnknown, "1.2.0", ""},
5963
}
6064

6165
for _, tt := range tests {
62-
t.Run(tt.method.String(), func(t *testing.T) {
63-
assert.Equal(t, tt.expected, updateCommandHint(tt.method))
66+
t.Run(tt.name, func(t *testing.T) {
67+
assert.Equal(t, tt.expected, updateCommandHint(tt.method, tt.availableVersion))
6468
})
6569
}
6670
}

0 commit comments

Comments
 (0)