Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Bring your own proxy. Route a command or the interactive shell through a proxy y
- A wrong password or three consecutive connection failures mark an own route dead and, in `run`, kill the command, as with a hosted route
- Own routes work with no login and with the Shellroute API unreachable; the version check is skipped for them
- Hosted routes are unchanged
- A build whose version is not a release number (a developer build) is no longer blocked by the minimum version check

## v0.1.0

Expand Down
25 changes: 24 additions & 1 deletion internal/cli/versioncheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"time"

"github.com/shellroute/shellroute-cli/internal/api"
Expand All @@ -23,9 +24,12 @@ type versionCache struct {

// checkVersion checks if the CLI version is up to date.
// Returns true if the CLI should proceed, false if blocked (version too old).
// Only a release number (X.Y.Z) is compared; "dev" and any other build label
// (a git describe of a non-release tag, "(devel)") cannot be older than a
// release and skip the check.
func checkVersion(cfg *config.Config) bool {
v := Version()
if flagSkipVersionCheck || v == "dev" {
if flagSkipVersionCheck || !isReleaseVersion(v) {
return true
}

Expand All @@ -50,6 +54,25 @@ func checkVersion(cfg *config.Config) bool {
return true
}

// isReleaseVersion reports whether v is a plain release number such as "0.2.0".
func isReleaseVersion(v string) bool {
parts := strings.Split(v, ".")
if len(parts) != 3 {
return false
}
for _, p := range parts {
if p == "" {
return false
}
for _, r := range p {
if r < '0' || r > '9' {
return false
}
}
}
return true
}

func getCachedOrFetchVersion(cfg *config.Config) (*versionCache, error) {
cacheFile := versionCacheFile()

Expand Down
21 changes: 21 additions & 0 deletions internal/cli/versioncheck_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ func TestVersionFunctionReturnsClean(t *testing.T) {
}
}

func TestIsReleaseVersion(t *testing.T) {
for v, want := range map[string]bool{"0.2.0": true, "10.0.3": true, "dev": false, "skills": false, "(devel)": false, "0.2": false, "0.2.0-rc1": false, "": false} {
if got := isReleaseVersion(v); got != want {
t.Errorf("isReleaseVersion(%q) = %v, want %v", v, got, want)
}
}
}

// A build labelled from a non-release tag ("skills-v1.0.0-1-gabcdef" cleans to
// "skills") used to compare as 0.0.0 and be blocked by the minimum version.
func TestCheckVersionNonReleaseLabelSkips(t *testing.T) {
old := rawVersion
defer func() { rawVersion = old }()
for _, label := range []string{"skills-v1.0.0-1-gabcdef", "(devel)", "snapshot"} {
rawVersion = label
if !checkVersion(nil) {
t.Errorf("version label %q must not be blocked", label)
}
}
}

func TestCheckVersionDevSkips(t *testing.T) {
old := rawVersion
rawVersion = "dev"
Expand Down
Loading