Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 34d96a1

Browse files
authored
fix: tolerate leading v in semantic versions from coder version API (#449)
* fix: tolerate leading v in semantic versions from coder version API * fix: quote reported version strings and only print Major.Minor.Patch
1 parent 7d34771 commit 34d96a1

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

internal/cmd/update.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ func (u *updater) Run(ctx context.Context, force bool, coderURLArg string, versi
129129
return clog.Fatal("preflight: missing write permission on current binary")
130130
}
131131

132-
clog.LogInfo(fmt.Sprintf("Current version of coder-cli is %s", version.Version))
132+
clog.LogInfo(fmt.Sprintf("Current version of coder-cli is %q", version.Version))
133133

134134
desiredVersion, err := getDesiredVersion(u.httpClient, coderURLArg, versionArg)
135135
if err != nil {
136136
return clog.Fatal("failed to determine desired version of coder", clog.Causef(err.Error()))
137137
}
138138

139-
currentVersion, err := semver.StrictNewVersion(u.versionF())
139+
currentVersion, err := semver.NewVersion(u.versionF())
140140
if err != nil {
141141
clog.LogWarn("failed to determine current version of coder-cli", clog.Causef(err.Error()))
142142
} else if currentVersion.Compare(desiredVersion) == 0 {
@@ -145,7 +145,11 @@ func (u *updater) Run(ctx context.Context, force bool, coderURLArg string, versi
145145
}
146146

147147
if !force {
148-
label := fmt.Sprintf("Do you want to download version %s instead", desiredVersion)
148+
label := fmt.Sprintf("Do you want to download version %d.%d.%d instead",
149+
desiredVersion.Major(),
150+
desiredVersion.Minor(),
151+
desiredVersion.Patch(),
152+
)
149153
if _, err := u.confirmF(label); err != nil {
150154
return clog.Fatal("user cancelled operation", clog.Tipf(`use "--force" to update without confirmation`))
151155
}
@@ -240,7 +244,7 @@ func (u *updater) doUpdate(ctx context.Context, updatedCoderBinaryPath string) e
240244
if err != nil {
241245
return xerrors.Errorf("check version of updated coder binary: %w", err)
242246
}
243-
clog.LogInfo(fmt.Sprintf("updated binary reports %s", bytes.TrimSpace(updatedVersionOutput)))
247+
clog.LogInfo(fmt.Sprintf("updated binary reports %q", bytes.TrimSpace(updatedVersionOutput)))
244248

245249
if err = u.fs.Rename(updatedCoderBinaryPath, u.executablePath); err != nil {
246250
return xerrors.Errorf("update coder binary in-place: %w", err)
@@ -283,7 +287,7 @@ func getDesiredVersion(httpClient getter, coderURLArg string, versionArg string)
283287
return &semver.Version{}, xerrors.Errorf("query coder version: %w", err)
284288
}
285289

286-
clog.LogInfo(fmt.Sprintf("Coder instance at %q reports version %s", coderURL.String(), desiredVersion.String()))
290+
clog.LogInfo(fmt.Sprintf("Coder instance at %q reports version %q", coderURL.String(), desiredVersion.String()))
287291

288292
return desiredVersion, nil
289293
}
@@ -452,7 +456,7 @@ func getAPIVersionUnauthed(client getter, baseURL url.URL) (*semver.Version, err
452456
return nil, xerrors.Errorf("parse version response: %w", err)
453457
}
454458

455-
version, err := semver.StrictNewVersion(ver.Version)
459+
version, err := semver.NewVersion(ver.Version)
456460
if err != nil {
457461
return nil, xerrors.Errorf("parsing coder version: %w", err)
458462
}

internal/cmd/update_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ func Test_updater_run(t *testing.T) {
106106
}
107107

108108
run(t, "update coder - noop", func(t *testing.T, p *params) {
109+
fakeNewVersion := "v" + fakeNewVersion
110+
fakeFile(t, p.Fakefs, fakeExePathLinux, 0755, fakeNewVersion)
111+
p.HTTPClient.M[apiPrivateVersionURL] = newFakeGetterResponse([]byte(fakeNewVersionJSON), 200, variadicS(), nil)
112+
p.VersionF = func() string { return fakeNewVersion }
113+
u := fromParams(p)
114+
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeNewVersion)
115+
err := u.Run(p.Ctx, false, fakeCoderURL, "")
116+
assert.Success(t, "update coder - noop", err)
117+
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeNewVersion)
118+
})
119+
120+
run(t, "update coder - should be noop but versions have leading v", func(t *testing.T, p *params) {
121+
fakeNewVersion := "v" + fakeNewVersion
109122
fakeFile(t, p.Fakefs, fakeExePathLinux, 0755, fakeNewVersion)
110123
p.HTTPClient.M[apiPrivateVersionURL] = newFakeGetterResponse([]byte(fakeNewVersionJSON), 200, variadicS(), nil)
111124
p.VersionF = func() string { return fakeNewVersion }
@@ -131,6 +144,23 @@ func Test_updater_run(t *testing.T) {
131144
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeNewVersion)
132145
})
133146

147+
run(t, "update coder - explicit version - leading v", func(t *testing.T, p *params) {
148+
fakeNewVersion := "v" + fakeNewVersion
149+
fakeOldVersion := "v" + fakeOldVersion
150+
fakeFile(t, p.Fakefs, fakeExePathLinux, 0755, fakeOldVersion)
151+
p.HTTPClient.M[apiPrivateVersionURL] = newFakeGetterResponse([]byte(fakeOldVersionJSON), 200, variadicS(), nil)
152+
p.HTTPClient.M[fakeGithubReleaseURL] = newFakeGetterResponse([]byte(fakeGithubReleaseJSON), 200, variadicS(), nil)
153+
p.HTTPClient.M[fakeAssetURLLinux] = newFakeGetterResponse(fakeValidTgzBytes, 200, variadicS(), nil)
154+
p.VersionF = func() string { return fakeOldVersion }
155+
p.ConfirmF = fakeConfirmYes
156+
p.Execer.M[p.ExecutablePath+".new --version"] = fakeExecerResult{[]byte(fakeNewVersion), nil}
157+
u := fromParams(p)
158+
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeOldVersion)
159+
err := u.Run(p.Ctx, false, fakeCoderURL, fakeNewVersion)
160+
assert.Success(t, "update coder - explicit version specified", err)
161+
assertFileContent(t, p.Fakefs, fakeExePathLinux, strings.TrimPrefix(fakeNewVersion, "v")) // TODO: stop hard-coding this
162+
})
163+
134164
run(t, "update coder - old to new", func(t *testing.T, p *params) {
135165
fakeFile(t, p.Fakefs, fakeExePathLinux, 0755, fakeOldVersion)
136166
p.HTTPClient.M[apiPrivateVersionURL] = newFakeGetterResponse([]byte(fakeNewVersionJSON), 200, variadicS(), nil)
@@ -146,6 +176,23 @@ func Test_updater_run(t *testing.T) {
146176
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeNewVersion)
147177
})
148178

179+
run(t, "update coder - old to new - leading v", func(t *testing.T, p *params) {
180+
fakeNewVersion := "v" + fakeNewVersion
181+
fakeOldVersion := "v" + fakeOldVersion
182+
fakeFile(t, p.Fakefs, fakeExePathLinux, 0755, fakeOldVersion)
183+
p.HTTPClient.M[apiPrivateVersionURL] = newFakeGetterResponse([]byte(fakeNewVersionJSON), 200, variadicS(), nil)
184+
p.HTTPClient.M[fakeGithubReleaseURL] = newFakeGetterResponse([]byte(fakeGithubReleaseJSON), 200, variadicS(), nil)
185+
p.HTTPClient.M[fakeAssetURLLinux] = newFakeGetterResponse(fakeValidTgzBytes, 200, variadicS(), nil)
186+
p.VersionF = func() string { return fakeOldVersion }
187+
p.ConfirmF = fakeConfirmYes
188+
p.Execer.M[p.ExecutablePath+".new --version"] = fakeExecerResult{[]byte(fakeNewVersion), nil}
189+
u := fromParams(p)
190+
assertFileContent(t, p.Fakefs, fakeExePathLinux, fakeOldVersion)
191+
err := u.Run(p.Ctx, false, fakeCoderURL, "")
192+
assert.Success(t, "update coder - old to new", err)
193+
assertFileContent(t, p.Fakefs, fakeExePathLinux, strings.TrimPrefix(fakeNewVersion, "v")) // TODO: stop hard-coding this
194+
})
195+
149196
run(t, "update coder - old to new - binary renamed", func(t *testing.T, p *params) {
150197
p.ExecutablePath = "/home/user/bin/coder-cli"
151198
fakeFile(t, p.Fakefs, p.ExecutablePath, 0755, fakeOldVersion)

0 commit comments

Comments
 (0)