| 127 | } |
| 128 | |
| 129 | func checkVersionCompatibility(w *world.World, client *client, cliVersion string) error { |
| 130 | if cliVersion == "unknown" { |
| 131 | w.Logger.Warn("CLI version unknown, unable to check compatibility") |
| 132 | return nil |
| 133 | } |
| 134 | |
| 135 | actuatorInfo, err := client.getActuatorInfo(context.Background()) |
| 136 | if err != nil { |
| 137 | w.Logger.Warn("Unable to get server version for compatibility check", "error", err) |
| 138 | return nil |
| 139 | } |
| 140 | |
| 141 | serverVersion := actuatorInfo.Version |
| 142 | if serverVersion == "" { |
| 143 | w.Logger.Warn("Server version is empty, unable to check compatibility") |
| 144 | return nil |
| 145 | } |
| 146 | |
| 147 | serverParsedVersion, err := parseVersion(serverVersion) |
| 148 | if err != nil { |
| 149 | return errors.Errorf("unable to parse Bytebase server version %q for compatibility check: %v; expected a self-hosted version like 3.14.0 or a Cloud version like cloud-YYYYMMDD", serverVersion, err) |
| 150 | } |
| 151 | |
| 152 | if cliVersion == "latest" { |
| 153 | actionTag := recommendedActionTag(serverParsedVersion) |
| 154 | w.Logger.Warn("Using 'latest' CLI version. It is recommended to use a specific version like bytebase-action:" + actionTag + " to match your Bytebase server version " + serverVersion) |
| 155 | return nil |
| 156 | } |
| 157 | |
| 158 | cliParsedVersion, err := parseVersion(cliVersion) |
| 159 | if err != nil { |
| 160 | return errors.Errorf("unable to parse CLI version %q for compatibility check: %v; expected a self-hosted version like 3.14.0 or a Cloud version like cloud-YYYYMMDD", cliVersion, err) |
| 161 | } |
| 162 | if cliParsedVersion.kind != serverParsedVersion.kind { |
| 163 | return errors.Errorf("unable to compare CLI version %q and Bytebase server version %q for compatibility check; expected both versions to use self-hosted versions like 3.14.0 or Cloud versions like cloud-YYYYMMDD", cliVersion, serverVersion) |
| 164 | } |
| 165 | |
| 166 | if cliVersion == serverVersion { |
| 167 | w.Logger.Info("CLI version matches server version", "version", cliVersion) |
| 168 | return nil |
| 169 | } |
| 170 | |
| 171 | if cliParsedVersion.kind == versionKindCloud { |
| 172 | // Cloud action/server builds are date-qualified and compatible when the |
| 173 | // action build is from the server's latest 7 days. Newer action builds |
| 174 | // may call APIs that do not exist on older or rolled-back servers. |
| 175 | dateDiff := int(cliParsedVersion.date.Sub(serverParsedVersion.date).Hours() / 24) |
| 176 | if dateDiff < -7 || dateDiff > 0 { |
| 177 | actionTag := recommendedActionTag(serverParsedVersion) |
| 178 | return errors.Errorf("CLI version %q is outside the compatibility window for Bytebase server version %q. Cloud compatibility requires both versions to use cloud-YYYYMMDD and be within 7 days. Use bytebase-action:%s to match your Bytebase server", cliVersion, serverVersion, actionTag) |
| 179 | } |
| 180 | |
| 181 | actionTag := recommendedActionTag(serverParsedVersion) |
| 182 | w.Logger.Warn("CLI version is within the compatibility window but does not match server version", "cliVersion", cliVersion, "serverVersion", serverVersion, "recommendation", "use bytebase-action:"+actionTag+" to match your Bytebase server") |
| 183 | return nil |
| 184 | } |
| 185 | |
| 186 | // Self-hosted action/server releases are compatible when the action version |