| 493 | } |
| 494 | |
| 495 | func resolveLatestReleaseWithDeps(ctx context.Context, deps workflowUpdateDeps, repo, currentRef string, allowMajor, verbose bool, coolDown time.Duration) (string, error) { |
| 496 | updateLog.Printf("Resolving latest release for repo %s (current: %s, allowMajor=%v)", repo, currentRef, allowMajor) |
| 497 | |
| 498 | if verbose { |
| 499 | fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Checking for latest release (current: %s, allow major: %v)", currentRef, allowMajor))) |
| 500 | } |
| 501 | |
| 502 | // Get all releases using gh CLI |
| 503 | output, err := deps.runReleasesAPI(ctx, repo) |
| 504 | if err != nil { |
| 505 | return "", fmt.Errorf("failed to fetch releases: %w", err) |
| 506 | } |
| 507 | |
| 508 | releases := strings.Split(strings.TrimSpace(string(output)), "\n") |
| 509 | if len(releases) == 0 || releases[0] == "" { |
| 510 | return "", errors.New("no releases found") |
| 511 | } |
| 512 | |
| 513 | // Parse current version |
| 514 | currentVer := parseVersion(currentRef) |
| 515 | if currentVer == nil { |
| 516 | // If current version is not a valid semantic version, select the latest stable release |
| 517 | // by semantic version so we are not sensitive to the ordering of the API response. |
| 518 | var latestStable string |
| 519 | var latestStableVersion *semverutil.SemanticVersion |
| 520 | |
| 521 | for _, release := range releases { |
| 522 | releaseVer := parseVersion(release) |
| 523 | if releaseVer == nil || releaseVer.Pre != "" { |
| 524 | continue |
| 525 | } |
| 526 | if latestStableVersion == nil || releaseVer.IsNewer(latestStableVersion) { |
| 527 | latestStable = release |
| 528 | latestStableVersion = releaseVer |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | if latestStable == "" { |
| 533 | return "", fmt.Errorf("no stable releases found for %s", repo) |
| 534 | } |
| 535 | |
| 536 | if verbose { |
| 537 | fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Current version is not valid, using latest stable release: "+latestStable)) |
| 538 | } |
| 539 | |
| 540 | return latestStable, nil |
| 541 | } |
| 542 | |
| 543 | // Find the latest compatible non-prerelease release. |
| 544 | // Per semver rules, v1.1.0-beta.1 > v1.0.0, so without this filter a prerelease |
| 545 | // of a higher base version could be incorrectly selected as the upgrade target. |
| 546 | var latestCompatible string |
| 547 | var latestCompatibleVersion *semverutil.SemanticVersion |
| 548 | |
| 549 | for _, release := range releases { |
| 550 | releaseVer := parseVersion(release) |
| 551 | if releaseVer == nil || releaseVer.Pre != "" { |
| 552 | continue |