(parentCtx context.Context, res updatepolicy.Result, manual bool)
| 297 | } |
| 298 | |
| 299 | func handleMandatoryUpdate(parentCtx context.Context, res updatepolicy.Result, manual bool) { |
| 300 | displayCurrent := displayVersion(res.CurrentVersion) |
| 301 | displayMin := displayVersion(res.MinVersion) |
| 302 | fmt.Fprintf(os.Stderr, "⚠ Update required: current %s, minimum %s.\n", displayCurrent, displayMin) |
| 303 | |
| 304 | binPath, _ := getCurrentBinaryPath() |
| 305 | if binPath != "" && autoupdate.IsPMManaged(binPath) { |
| 306 | pm := detectPackageManager(binPath) |
| 307 | switch pm { |
| 308 | case "homebrew": |
| 309 | fmt.Fprintln(os.Stderr, "This installation is managed by Homebrew. Please run 'brew update' and then 'brew upgrade tnr' to update.") |
| 310 | case "scoop": |
| 311 | fmt.Fprintln(os.Stderr, "This installation is managed by Scoop. Please run 'scoop update tnr' to update.") |
| 312 | case "winget": |
| 313 | fmt.Fprintln(os.Stderr, "This installation is managed by Windows Package Manager. Please run 'winget upgrade Thunder.tnr' to update.") |
| 314 | default: |
| 315 | fmt.Fprintln(os.Stderr, "This installation is managed by a package manager. Please upgrade using brew/winget/scoop or reinstall the latest release.") |
| 316 | } |
| 317 | os.Exit(1) |
| 318 | } |
| 319 | |
| 320 | if manual { |
| 321 | fmt.Fprintln(os.Stderr, "Installing update...") |
| 322 | } else { |
| 323 | fmt.Fprintln(os.Stderr, "Attempting automatic update, you may be prompted for your system password...") |
| 324 | } |
| 325 | updateCtx, cancel := context.WithTimeout(parentCtx, 5*time.Minute) |
| 326 | defer cancel() |
| 327 | |
| 328 | if err := runSelfUpdate(updateCtx, res); err != nil { |
| 329 | // Capture update failures to Sentry |
| 330 | sentry.WithScope(func(scope *sentry.Scope) { |
| 331 | scope.SetTag("operation", "mandatory_update") |
| 332 | scope.SetTag("current_version", res.CurrentVersion) |
| 333 | scope.SetTag("target_version", res.LatestVersion) |
| 334 | scope.SetLevel(sentry.LevelError) |
| 335 | sentry.CaptureException(err) |
| 336 | }) |
| 337 | if manual { |
| 338 | fmt.Fprintf(os.Stderr, "Update failed: %v\n", err) |
| 339 | } else { |
| 340 | fmt.Fprintf(os.Stderr, "Automatic update failed: %v\n", err) |
| 341 | } |
| 342 | fmt.Fprintf(os.Stderr, "Download the latest version from GitHub: https://github.com/Thunder-Compute/thunder-cli/releases/tag/%s and reinstall the CLI.\n", releaseTag(res)) |
| 343 | os.Exit(1) |
| 344 | } |
| 345 | |
| 346 | // Try to finalize the update immediately if possible (Windows only, when already elevated or writable) |
| 347 | binPath, _ = getCurrentBinaryPath() |
| 348 | if binPath != "" { |
| 349 | shouldReexec, err := autoupdate.TryFinalizeStagedUpdateImmediately(parentCtx, binPath) |
| 350 | if err != nil { |
| 351 | fmt.Fprintln(os.Stderr, "Update staged successfully. Please re-run your command to complete the update.") |
| 352 | os.Exit(0) |
| 353 | } |
| 354 | if shouldReexec { |
| 355 | fmt.Fprintf(os.Stderr, "Updated tnr to %s.\n", displayVersion(res.LatestVersion)) |
| 356 | os.Exit(0) |
no test coverage detected