Independent client/engine versioning with compatibility check
Split release.sh into release-client.sh and release-engine.sh for independent release cadences. Client checks engine version on first API call and hard-fails if engine is below MinEngineVersion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSemverAtLeast(t *testing.T) {
|
||||
tests := []struct {
|
||||
version string
|
||||
minimum string
|
||||
expected bool
|
||||
}{
|
||||
{"2.1.0", "2.0.0", true},
|
||||
{"2.0.0", "2.0.0", true},
|
||||
{"2.0.5", "2.0.0", true},
|
||||
{"2.1.5", "2.1.0", true},
|
||||
{"2.0.9", "2.1.0", false},
|
||||
{"1.9.9", "2.0.0", false},
|
||||
{"3.0.0", "2.9.9", true},
|
||||
{"2.0.0", "2.0.1", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.version+">="+tt.minimum, func(t *testing.T) {
|
||||
got := semverAtLeast(tt.version, tt.minimum)
|
||||
if got != tt.expected {
|
||||
t.Errorf("semverAtLeast(%q, %q) = %v, want %v", tt.version, tt.minimum, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckEngineVersion_Compatible(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]string{"version": "2.1.0"})
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
clientVersion = "2.2.0"
|
||||
minEngineVersion = "2.1.0"
|
||||
defer func() { clientVersion = ""; minEngineVersion = "" }()
|
||||
|
||||
c := &Client{
|
||||
baseURL: srv.URL,
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
// Should not panic or exit
|
||||
c.checkEngineVersion()
|
||||
|
||||
if !c.versionChecked {
|
||||
t.Error("versionChecked should be true after check")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckEngineVersion_SkipsWhenDev(t *testing.T) {
|
||||
clientVersion = "dev"
|
||||
minEngineVersion = "dev"
|
||||
defer func() { clientVersion = ""; minEngineVersion = "" }()
|
||||
|
||||
c := &Client{
|
||||
baseURL: "http://localhost:99999",
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
// Should not attempt connection
|
||||
c.checkEngineVersion()
|
||||
|
||||
if !c.versionChecked {
|
||||
t.Error("versionChecked should be true after skipping")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckEngineVersion_SkipsWhenEmpty(t *testing.T) {
|
||||
clientVersion = "1.0.0"
|
||||
minEngineVersion = ""
|
||||
defer func() { clientVersion = ""; minEngineVersion = "" }()
|
||||
|
||||
c := &Client{
|
||||
baseURL: "http://localhost:99999",
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
c.checkEngineVersion()
|
||||
|
||||
if !c.versionChecked {
|
||||
t.Error("versionChecked should be true after skipping")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckEngineVersion_SkipsWhenUnreachable(t *testing.T) {
|
||||
clientVersion = "2.0.0"
|
||||
minEngineVersion = "2.0.0"
|
||||
defer func() { clientVersion = ""; minEngineVersion = "" }()
|
||||
|
||||
c := &Client{
|
||||
baseURL: "http://localhost:99999",
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
// Should not panic — just skip
|
||||
c.checkEngineVersion()
|
||||
|
||||
if !c.versionChecked {
|
||||
t.Error("versionChecked should be true even when unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckEngineVersion_CachedAfterFirstCall(t *testing.T) {
|
||||
callCount := 0
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
callCount++
|
||||
json.NewEncoder(w).Encode(map[string]string{"version": "2.1.0"})
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
clientVersion = "2.1.0"
|
||||
minEngineVersion = "2.0.0"
|
||||
defer func() { clientVersion = ""; minEngineVersion = "" }()
|
||||
|
||||
c := &Client{
|
||||
baseURL: srv.URL,
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
c.checkEngineVersion()
|
||||
c.checkEngineVersion()
|
||||
c.checkEngineVersion()
|
||||
|
||||
if callCount != 1 {
|
||||
t.Errorf("expected 1 status call, got %d", callCount)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user