Ignore prerelease releases when fetching GitHub releases#23810
Ignore prerelease releases when fetching GitHub releases#23810
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/ffd92df3-bb79-4b1a-ace8-216299456138 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
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
resolveLatestReleaseand 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/latestclient 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.
pkg/cli/update_workflows.go
Outdated
| // 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 |
There was a problem hiding this comment.
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
pkg/cli/update_workflows.go
Outdated
| return release, nil | ||
| } | ||
| return latestRelease, nil | ||
| return "", errors.New("no stable releases found") |
There was a problem hiding this comment.
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>).
| return "", errors.New("no stable releases found") | |
| return "", fmt.Errorf("no stable releases found for %s (current ref: %s)", repo, currentRef) |
|
@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>
Addressed both reviewer comments in 76345a6:
Tests updated to assert semver-based ordering in the |
Release-fetching code in
resolveLatestRelease(update_workflows.go) did not filter out prerelease tags, meaning a release likev1.1.0-beta.1could be incorrectly selected over the latest stablev1.0.0(per semver,v1.1.0-beta.1 > v1.0.0).Changes
update_workflows.go—resolveLatestRelease(primary fix): AddedreleaseVer.Pre != ""skip in both the main selection loop and thecurrentVer == nilfallback path. The fallback previously returnedreleases[0]blindly, which could be a prerelease. Extracted the API call into injectablerunWorkflowReleasesAPIFn(consistent withrunGHReleasesAPIFninupdate_actions.go) to enable unit testing.update_check.go—getLatestRelease(defensive): AddedPrerelease boolto theReleasestruct and a guard that returns""if the response is marked as a prerelease. The/releases/latestendpoint already excludes prereleases by contract, but this protects against regressions.update_actions.go— already correct; bothgetLatestActionReleaseandgetLatestActionReleaseViaGitfiltered withreleaseVer.Pre == "".Tests
New
update_workflows_test.gocovers: prerelease skipped when newer than stable, prerelease skipped whencurrentVeris invalid, error when only prereleases exist, stable selection with no prereleases, mixed prerelease/stable across major versions.