feat: enhance version comparison logic in update check and refactor tunnel command functions
Kim committed
Jun 1, 2026 at 13:45 UTC
552fc4fc12038637ba2f27f8e73b6f734f133395
4 files changed
+12
-27
cmd/portal-tunnel/installer/update.go
+8
-1
@@ -14,6 +14,8 @@ import (
14
"strings"
15
"time"
16
17
+ "golang.org/x/mod/semver"
18
+
19
"github.com/gosuda/portal-tunnel/v2/types"
20
"github.com/gosuda/portal-tunnel/v2/utils"
21
)
@@ -48,7 +50,12 @@ func StartUpdateCheck(currentVersion string) {
50
segments := strings.Split(strings.TrimPrefix(parsed.Path, "/"), "/")
51
if len(segments) >= 5 {
52
version := segments[4]
51
- if strings.HasPrefix(version, "v") && version != currentVersion {
53
+ current := strings.TrimSpace(currentVersion)
54
+ if current != "" && !strings.HasPrefix(current, "v") {
55
+ current = "v" + current
56
+ }
57
+ latestValid := strings.HasPrefix(version, "v") && semver.IsValid(version)
58
+ if latestValid && semver.IsValid(current) && semver.Compare(version, current) > 0 {
59
fmt.Fprintf(os.Stderr, "\nA new version is available: %s. Run 'portal update' to upgrade.\n", version)
60
}
61
}
frontend/src/lib/tunnelCommand.test.ts
+2
-3
@@ -31,7 +31,7 @@ describe("tunnelCommand", () => {
31
expect(command).not.toContain("\n --name");
32
});
33
34
- it("wraps display commands before relays while keeping copied commands flat", () => {
34
+ it("keeps display and copied commands flat", () => {
35
const options = {
36
currentOrigin: "https://relay.example.com",
37
target: "localhost:3000",
@@ -54,8 +54,7 @@ describe("tunnelCommand", () => {
54
[
55
`$ProgressPreference = 'SilentlyContinue'`,
56
`irm https://relay.example.com/api/install.ps1 | iex`,
57
- `portal expose localhost:3000 --name my-app`,
58
- `--relays https://relay.example.com --discovery=false --thumbnail https://example.com/thumb.png`,
57
+ `portal expose localhost:3000 --name my-app --relays https://relay.example.com --discovery=false --thumbnail https://example.com/thumb.png`,
58
].join("\n")
59
);
60
});
frontend/src/lib/tunnelCommand.ts
+1
-22
@@ -70,7 +70,7 @@ export function buildTunnelDisplayCommand({
70
udpPort,
71
});
72
73
- return joinTunnelDisplayCommand(installLine, exposeHead, exposeOptions);
73
+ return joinTunnelCommand(installLine, exposeHead, exposeOptions);
74
}
75
76
function buildTunnelCommandParts({
@@ -234,24 +234,3 @@ function joinTunnelCommand(
234
): string {
235
return [installLine, [exposeHead, ...exposeOptions].join(" ")].join("\n");
236
}
237
-
238
-function joinTunnelDisplayCommand(
239
- installLine: string,
240
- exposeHead: string,
241
- exposeOptions: string[]
242
-): string {
243
- const relayIndex = exposeOptions.findIndex((option) =>
244
- option.startsWith("--relays ")
245
- );
246
-
247
- if (relayIndex < 0) {
248
- return joinTunnelCommand(installLine, exposeHead, exposeOptions);
249
- }
250
-
251
- const exposeLines = [
252
- [exposeHead, ...exposeOptions.slice(0, relayIndex)].join(" "),
253
- exposeOptions.slice(relayIndex).join(" "),
254
- ];
255
-
256
- return [installLine, exposeLines.join("\n")].join("\n");
257
-}
go.mod
+1
-1
@@ -33,6 +33,7 @@ require (
33
github.com/vultr/govultr/v3 v3.30.0
34
github.com/x402-foundation/x402/go v0.0.0-20260526081544-8cf020c5335e
35
golang.org/x/crypto v0.51.0
36
+ golang.org/x/mod v0.35.0
37
golang.org/x/net v0.55.0
38
golang.org/x/oauth2 v0.36.0
39
golang.org/x/sync v0.20.0
@@ -145,7 +146,6 @@ require (
146
go.opentelemetry.io/otel/metric v1.43.0 // indirect
147
go.opentelemetry.io/otel/trace v1.43.0 // indirect
148
go.yaml.in/yaml/v2 v2.4.2 // indirect
148
- golang.org/x/mod v0.35.0 // indirect
149
golang.org/x/text v0.37.0 // indirect
150
golang.org/x/time v0.15.0 // indirect
151
golang.org/x/tools v0.44.0 // indirect