Skip to content

Fix: fallback to git tags when GitHub Releases API returns empty for gh aw upgrade#23147

Merged
pelikhan merged 5 commits intomainfrom
copilot/improve-gh-aw-upgrade-warning
Mar 26, 2026
Merged

Fix: fallback to git tags when GitHub Releases API returns empty for gh aw upgrade#23147
pelikhan merged 5 commits intomainfrom
copilot/improve-gh-aw-upgrade-warning

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 26, 2026

gh aw upgrade emitted github/gh-aw-actions/setup: no releases found for repos that publish tags without creating GitHub Releases (including github/gh-aw-actions itself). The auth-error fallback to git ls-remote existed but was never triggered for an empty-but-successful API response.

Changes

  • pkg/cli/update_actions.go: When the Releases API returns empty (no error), fall back to getLatestActionReleaseViaGitFn (tag scanning) instead of returning an error. Only surfaces an error if both sources find nothing. Emits a verbose-only info message when the fallback is used.

    Extracted the API call into runGHReleasesAPIFn, added getLatestActionReleaseViaGitFn and getActionSHAForTagFn as replaceable function variables (mirrors the existing getLatestActionReleaseFn pattern).

    Both getLatestActionRelease (GitHub Releases API path) and getLatestActionReleaseViaGit (git tag fallback) now filter out prerelease versions (e.g. v1.1.0-beta.1) when selecting the upgrade target. Per semver rules, a prerelease of a higher base version is considered "newer" than a stable release of a lower version, so without this filter a prerelease tag could be incorrectly selected. The git ls-remote --tags fallback path is especially exposed since it returns every tag.

  • pkg/cli/update_actions_test.go: Three new tests exercising the real getLatestActionRelease code path via runGHReleasesAPIFn stub — fallback succeeds when tags exist, error propagates when both sources fail, and prerelease tags are skipped in favour of stable releases.

  • docs/src/content/docs/reference/faq.md: Added FAQ entry documenting the two-step resolution (Releases API → git tag fallback) and clarifying that the previously-seen warning is fixed.


⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

When the GitHub Releases API returns an empty list for a repository,
getLatestActionRelease now falls back to git ls-remote tag scanning
(getLatestActionReleaseViaGitFn) instead of returning an error.

This fixes the spurious 'github/gh-aw-actions/setup: no releases found'
warning during 'gh aw upgrade' for repos that publish tags without
GitHub Releases.

- Add runGHReleasesAPIFn variable to make API call testable
- Add getLatestActionReleaseViaGitFn variable for testability
- Emit verbose info message when tag fallback is used
- Only error when both sources find nothing
- Add unit tests exercising the real fallback code path
- Add FAQ entry documenting the Releases vs tags resolution logic

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/793935d9-1e6b-4fee-97bc-5ce82a95bb0d

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve gh aw upgrade warning for no GitHub releases Fix: fallback to git tags when GitHub Releases API returns empty for gh aw upgrade Mar 26, 2026
Copilot AI requested a review from pelikhan March 26, 2026 17:23
@pelikhan pelikhan marked this pull request as ready for review March 26, 2026 19:36
Copilot AI review requested due to automatic review settings March 26, 2026 19:36
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot make sure to filter tags according to semver rules.

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

Fixes gh aw upgrade / gh aw update-actions behavior when the GitHub Releases API returns a successful but empty result by falling back to resolving versions from git tags.

Changes:

  • Add a “no releases returned” fallback to git ls-remote tag scanning when the Releases API response is empty.
  • Introduce injectable function variables for the Releases API call and git-tag fallback to enable deterministic unit tests.
  • Add tests and document the two-step resolution behavior in the FAQ.

Reviewed changes

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

File Description
pkg/cli/update_actions.go Adds empty-success Releases API fallback to git tag scanning; introduces injectable function variables.
pkg/cli/update_actions_test.go Adds tests covering empty API response fallback success and failure cases.
docs/src/content/docs/reference/faq.md Documents the two-step resolution (Releases API → git tag scan fallback).

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

Comment on lines +196 to +204
// to use and the warning below is informational only.
updateLog.Printf("No releases found via GitHub API for %s, falling back to git ls-remote tag scan", baseRepo)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(baseRepo+": no GitHub Releases found, falling back to tag scanning (safe to ignore)"))
}
latestRelease, latestSHA, gitErr := getLatestActionReleaseViaGitFn(repo, currentVersion, allowMajor, verbose)
if gitErr != nil {
return "", "", fmt.Errorf("no releases or tags found for %s: %w", baseRepo, gitErr)
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The verbose info message says the tag-scan fallback is “safe to ignore” before the git fallback has actually succeeded. If the subsequent git ls-remote call fails, users will see a reassuring message immediately followed by an error, which is misleading. Consider moving the info message until after a successful git fallback, or reword it to something like “attempting tag scan fallback…” and only state it’s safe once a tag was found.

Suggested change
// to use and the warning below is informational only.
updateLog.Printf("No releases found via GitHub API for %s, falling back to git ls-remote tag scan", baseRepo)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(baseRepo+": no GitHub Releases found, falling back to tag scanning (safe to ignore)"))
}
latestRelease, latestSHA, gitErr := getLatestActionReleaseViaGitFn(repo, currentVersion, allowMajor, verbose)
if gitErr != nil {
return "", "", fmt.Errorf("no releases or tags found for %s: %w", baseRepo, gitErr)
}
// to use when the tag-scan fallback succeeds; the messages below are informational.
updateLog.Printf("No releases found via GitHub API for %s, falling back to git ls-remote tag scan", baseRepo)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(baseRepo+": no GitHub Releases found, attempting tag scan fallback via git ls-remote"))
}
latestRelease, latestSHA, gitErr := getLatestActionReleaseViaGitFn(repo, currentVersion, allowMajor, verbose)
if gitErr != nil {
return "", "", fmt.Errorf("no releases or tags found for %s: %w", baseRepo, gitErr)
}
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(baseRepo+": tag scan fallback succeeded; using latest tag-based version (safe to ignore missing GitHub Releases)"))
}

Copilot uses AI. Check for mistakes.
Comment on lines +443 to +451
// getLatestActionReleaseViaGitFn is the function used to fetch the latest release via git
// ls-remote as a fallback. It can be replaced in tests to avoid network calls.
var getLatestActionReleaseViaGitFn = getLatestActionReleaseViaGit

// runGHReleasesAPIFn calls the GitHub Releases API for the given base repository and
// returns the raw output. It can be replaced in tests to avoid network calls.
var runGHReleasesAPIFn = func(baseRepo string) ([]byte, error) {
return workflow.RunGHCombined("Fetching releases...", "api", fmt.Sprintf("/repos/%s/releases", baseRepo), "--jq", ".[].tag_name")
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

getLatestActionReleaseViaGitFn is introduced as an injectable wrapper for the git ls-remote fallback, but getLatestActionRelease still calls getLatestActionReleaseViaGit directly in the auth-error fallback path. This makes the injection incomplete and prevents tests from stubbing the git fallback consistently. Consider routing all git fallback call sites through getLatestActionReleaseViaGitFn.

Copilot uses AI. Check for mistakes.
…selection

Both getLatestActionRelease (GitHub API path) and getLatestActionReleaseViaGit
(git tag fallback) now skip prerelease versions (e.g. v1.1.0-beta.1) when
building the valid-releases list.

Per semver rules, v1.1.0-beta.1 > v1.0.0 (the base version is higher), so
without this filter a prerelease tag could be incorrectly selected as the
upgrade target. git ls-remote --tags returns every tag, making the fallback
path particularly exposed to this.

Also add getActionSHAForTagFn as a replaceable function variable (mirrors
the existing pattern) to enable end-to-end testing without network calls.

Adds TestGetLatestActionRelease_PrereleaseTagsSkipped to assert that
v1.1.0-beta.1 is skipped in favour of the stable v1.0.0.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/02389988-6d87-487d-a93f-e4a06189744d

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

Copilot AI commented Mar 26, 2026

@copilot make sure to filter tags according to semver rules.

Done in commit 411fa0b. Both getLatestActionRelease (GitHub Releases API path) and getLatestActionReleaseViaGit (git tag fallback) now skip prerelease versions (releaseVer.pre == "" check). Per semver rules, v1.1.0-beta.1 > v1.0.0 because the base version is higher, so without this filter a prerelease tag of a higher version could be incorrectly selected. The git ls-remote --tags path is especially exposed since it returns every tag. A new test TestGetLatestActionRelease_PrereleaseTagsSkipped asserts that v1.1.0-beta.1 is skipped in favour of the stable v1.0.0.

@pelikhan pelikhan merged commit e3484fe into main Mar 26, 2026
49 checks passed
@pelikhan pelikhan deleted the copilot/improve-gh-aw-upgrade-warning branch March 26, 2026 20:15
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.

Agentic Plan: Improve gh aw upgrade warning for github/gh-aw-actions/setup when no GitHub Releases exist

3 participants