wrapTransportWithVersionCheck adds a middleware to the HTTP transport that checks the server version and warns about development builds, release candidates, and client/server version mismatches.
(rt http.RoundTripper, inv *serpent.Invocation, clientVersion string, getBuildInfo func(ctx context.Context) (codersdk.BuildInfoResponse, error))
| 1593 | // that checks the server version and warns about development builds, |
| 1594 | // release candidates, and client/server version mismatches. |
| 1595 | func wrapTransportWithVersionCheck(rt http.RoundTripper, inv *serpent.Invocation, clientVersion string, getBuildInfo func(ctx context.Context) (codersdk.BuildInfoResponse, error)) http.RoundTripper { |
| 1596 | var once sync.Once |
| 1597 | return roundTripper(func(req *http.Request) (*http.Response, error) { |
| 1598 | res, err := rt.RoundTrip(req) |
| 1599 | if err != nil { |
| 1600 | return res, err |
| 1601 | } |
| 1602 | once.Do(func() { |
| 1603 | serverVersion := res.Header.Get(codersdk.BuildVersionHeader) |
| 1604 | if serverVersion == "" { |
| 1605 | return |
| 1606 | } |
| 1607 | // Warn about non-stable server versions. Skip |
| 1608 | // during tests to avoid polluting golden files. |
| 1609 | if msg := serverVersionMessage(serverVersion); msg != "" && flag.Lookup("test.v") == nil { |
| 1610 | warning := pretty.Sprint(cliui.DefaultStyles.Warn, msg) |
| 1611 | _, _ = fmt.Fprintln(inv.Stderr, warning) |
| 1612 | } |
| 1613 | if buildinfo.VersionsMatch(clientVersion, serverVersion) { |
| 1614 | return |
| 1615 | } |
| 1616 | |
| 1617 | upgradeMessage := defaultUpgradeMessage(semver.Canonical(serverVersion)) |
| 1618 | if serverInfo, err := getBuildInfo(inv.Context()); err == nil { |
| 1619 | switch { |
| 1620 | case serverInfo.UpgradeMessage != "": |
| 1621 | upgradeMessage = serverInfo.UpgradeMessage |
| 1622 | // The site-local `install.sh` was introduced in v2.19.0 |
| 1623 | case serverInfo.DashboardURL != "" && semver.Compare(semver.MajorMinor(serverVersion), "v2.19") >= 0: |
| 1624 | upgradeMessage = fmt.Sprintf("download %s with: 'curl -fsSL %s/install.sh | sh'", serverVersion, serverInfo.DashboardURL) |
| 1625 | } |
| 1626 | } |
| 1627 | fmtWarningText := "version mismatch: client %s, server %s\n%s" |
| 1628 | fmtWarn := pretty.Sprint(cliui.DefaultStyles.Warn, fmtWarningText) |
| 1629 | warning := fmt.Sprintf(fmtWarn, clientVersion, serverVersion, upgradeMessage) |
| 1630 | |
| 1631 | _, _ = fmt.Fprintln(inv.Stderr, warning) |
| 1632 | }) |
| 1633 | return res, err |
| 1634 | }) |
| 1635 | } |
| 1636 | |
| 1637 | // wrapTransportWithTelemetryHeader adds telemetry headers to report command usage |
| 1638 | // to an HTTP transport. |