@@ -1361,14 +1361,37 @@ func SlimUnsupported(w io.Writer, cmd string) {
13611361os .Exit (1 )
13621362}
13631363
1364- func defaultUpgradeMessage (version string )string {
1365- // Our installation script doesn't work on Windows, so instead we direct the user
1366- // to the GitHub release page to download the latest installer.
1367- version = strings .TrimPrefix (version ,"v" )
1368- if runtime .GOOS == "windows" {
1369- return fmt .Sprintf ("download the server version from: https://github.com/coder/coder/releases/v%s" ,version )
1370- }
1371- return fmt .Sprintf ("download the server version with: 'curl -L https://coder.com/install.sh | sh -s -- --version %s'" ,version )
1364+ // defaultUpgradeMessage builds an appropriate upgrade message for the platform.
1365+ // Precedence:
1366+ // 1) If a custom upgrade message is provided by the server, use it.
1367+ // 2) If the server provides a dashboard URL (v2.19+) and the platform is not Windows,
1368+ // recommend the site-local install.sh.
1369+ // 3) On Windows, point to the tagged GitHub release page where binaries are published.
1370+ // 4) Otherwise, recommend the global install.sh with explicit version.
1371+ func defaultUpgradeMessage (version ,dashboardURL ,customUpgradeMessage string )string {
1372+ if customUpgradeMessage != "" {
1373+ return customUpgradeMessage
1374+ }
1375+
1376+ // Ensure canonical semver for comparisons and display
1377+ canonical := semver .Canonical (version )
1378+ trimmed := strings .TrimPrefix (canonical ,"v" )
1379+
1380+ // The site-local `install.sh` was introduced in v2.19.0.
1381+ if dashboardURL != "" && semver .Compare (semver .MajorMinor (canonical ),"v2.19" )>= 0 {
1382+ // The site-local install.sh is only valid for macOS and Linux.
1383+ if runtime .GOOS != "windows" {
1384+ return fmt .Sprintf ("download %s with: 'curl -fsSL %s/install.sh | sh'" ,canonical ,dashboardURL )
1385+ }
1386+ // Fall through to Windows-specific suggestion below.
1387+ }
1388+
1389+ if runtime .GOOS == "windows" {
1390+ // Link directly to the release page; Windows binaries are published there.
1391+ return fmt .Sprintf ("download the server version from: https://github.com/coder/coder/releases/v%s" ,trimmed )
1392+ }
1393+
1394+ return fmt .Sprintf ("download the server version with: 'curl -L https://coder.com/install.sh | sh -s -- --version %s'" ,trimmed )
13721395}
13731396
13741397// wrapTransportWithEntitlementsCheck adds a middleware to the HTTP transport
@@ -1407,19 +1430,19 @@ func wrapTransportWithVersionMismatchCheck(rt http.RoundTripper, inv *serpent.In
14071430if buildinfo .VersionsMatch (clientVersion ,serverVersion ) {
14081431return
14091432}
1410- upgradeMessage := defaultUpgradeMessage ( semver . Canonical ( serverVersion ))
1411- if serverInfo ,err := getBuildInfo (inv .Context ());err == nil {
1412- switch {
1413- case serverInfo . UpgradeMessage != "" :
1414- upgradeMessage = serverInfo . UpgradeMessage
1415- // The site-local `install.sh` was introduced in v2.19.0
1416- case serverInfo . DashboardURL != "" && semver . Compare ( semver . MajorMinor ( serverVersion ), "v2.19" ) >= 0 :
1417- upgradeMessage = fmt . Sprintf ( "download %s with: 'curl -fsSL %s/install.sh | sh'" , serverVersion , serverInfo . DashboardURL )
1418- }
1419- }
1420- fmtWarningText := "version mismatch: client %s, server %s \n %s"
1421- fmtWarn := pretty . Sprint ( cliui . DefaultStyles . Warn , fmtWarningText )
1422- warning := fmt . Sprintf ( fmtWarn , clientVersion , serverVersion , upgradeMessage )
1433+ var dashboardURL , customUpgradeMessage string
1434+ if serverInfo ,err := getBuildInfo (inv .Context ());err == nil {
1435+ dashboardURL = serverInfo . DashboardURL
1436+ customUpgradeMessage = serverInfo . UpgradeMessage
1437+ }
1438+ upgradeMessage := defaultUpgradeMessage ( serverVersion , dashboardURL , customUpgradeMessage )
1439+ warning := pretty . Sprintf (
1440+ cliui . DefaultStyles . Warn ,
1441+ "version mismatch: client %s, server %s \n %s" ,
1442+ clientVersion ,
1443+ serverVersion ,
1444+ upgradeMessage ,
1445+ )
14231446
14241447_ ,_ = fmt .Fprintln (inv .Stderr ,warning )
14251448})