Skip to content

Ignore prerelease releases when fetching GitHub releases#23810

Merged
pelikhan merged 2 commits intomainfrom
copilot/update-fetch-handling-releases
Apr 1, 2026
Merged

Ignore prerelease releases when fetching GitHub releases#23810
pelikhan merged 2 commits intomainfrom
copilot/update-fetch-handling-releases

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

Release-fetching code in resolveLatestRelease (update_workflows.go) did not filter out prerelease tags, meaning a release like v1.1.0-beta.1 could be incorrectly selected over the latest stable v1.0.0 (per semver, v1.1.0-beta.1 > v1.0.0).

Changes

  • update_workflows.goresolveLatestRelease (primary fix): Added releaseVer.Pre != "" skip in both the main selection loop and the currentVer == nil fallback path. The fallback previously returned releases[0] blindly, which could be a prerelease. Extracted the API call into injectable runWorkflowReleasesAPIFn (consistent with runGHReleasesAPIFn in update_actions.go) to enable unit testing.

  • update_check.gogetLatestRelease (defensive): Added Prerelease bool to the Release struct and a guard that returns "" if the response is marked as a prerelease. The /releases/latest endpoint already excludes prereleases by contract, but this protects against regressions.

  • update_actions.go — already correct; both getLatestActionRelease and getLatestActionReleaseViaGit filtered with releaseVer.Pre == "".

Tests

New update_workflows_test.go covers: prerelease skipped when newer than stable, prerelease skipped when currentVer is invalid, error when only prereleases exist, stable selection with no prereleases, mixed prerelease/stable across major versions.

@pelikhan pelikhan marked this pull request as ready for review April 1, 2026 03:05
Copilot AI review requested due to automatic review settings April 1, 2026 03:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ensures prerelease GitHub tags (e.g., v1.1.0-beta.1) are not selected as “latest” when resolving workflow/action release upgrades, preventing prereleases from being chosen over the newest stable release.

Changes:

  • Filter out prerelease semver tags in resolveLatestRelease and make the releases API call injectable for unit testing.
  • Add unit tests covering prerelease-skipping scenarios for workflow release resolution.
  • Add a defensive prerelease guard to the update-check /releases/latest client response.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
pkg/cli/update_workflows.go Skips prerelease tags during release selection; introduces injectable releases API function for testing.
pkg/cli/update_workflows_test.go Adds tests validating prerelease tags are ignored and correct stable tags are selected.
pkg/cli/update_check.go Extends Release with Prerelease and defensively ignores prerelease responses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +308 to +312
// If current version is not a valid semantic version, return the latest stable release
for _, release := range releases {
releaseVer := parseVersion(release)
if releaseVer == nil || releaseVer.Pre != "" {
continue
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the currentVer == nil fallback, this returns the first stable tag in the API output order rather than computing the highest stable semantic version. That can pick an older version if GitHub returns releases sorted by publish time (or any order not correlated with semver), which is inconsistent with the semver-based selection used in the main path. Consider scanning all stable semver tags and selecting the newest by semver (or adjust the comment/message to reflect that this is “most recent by API order”).

See below for a potential fix:

		// If current version is not a valid semantic version, select the latest stable release by semantic version.
		var latestStable string
		var latestStableVersion *semverutil.SemanticVersion

		for _, release := range releases {
			releaseVer := parseVersion(release)
			if releaseVer == nil || releaseVer.Pre != "" {
				continue
			}

			if latestStableVersion == nil || releaseVer.IsNewer(latestStableVersion) {
				latestStable = release
				latestStableVersion = releaseVer
			}
		}

		if latestStable == "" {
			return "", errors.New("no stable releases found")
		}

		if verbose {
			fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Current version is not valid, using latest stable release: "+latestStable))
		}

		return latestStable, nil

Copilot uses AI. Check for mistakes.
return release, nil
}
return latestRelease, nil
return "", errors.New("no stable releases found")
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new error "no stable releases found" loses context about which repository/ref was being resolved, and it will surface to users wrapped only as failed to resolve latest ref: .... Consider including the repo (and possibly currentRef/allowMajor) in the error to make failures actionable (e.g., no stable releases found for <repo>).

Suggested change
return "", errors.New("no stable releases found")
return "", fmt.Errorf("no stable releases found for %s (current ref: %s)", repo, currentRef)

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 1, 2026

@copilot review comments

…testRelease

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/99b19872-48e9-42c7-a1b6-2798045efd66

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 1, 2026

@copilot review comments

Addressed both reviewer comments in 76345a6:

  1. The currentVer == nil fallback now scans all stable releases and picks the highest by semver (instead of returning the first in API order), making it consistent with the main selection path.
  2. The "no stable releases found" error now includes the repo name: "no stable releases found for %s".

Tests updated to assert semver-based ordering in the currentVer == nil path.

Copilot AI requested a review from pelikhan April 1, 2026 03:16
@pelikhan pelikhan merged commit 6187853 into main Apr 1, 2026
57 checks passed
@pelikhan pelikhan deleted the copilot/update-fetch-handling-releases branch April 1, 2026 03:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants