Skip to content

fix: auto-upgrade gh-aw extension during gh aw upgrade to prevent stale version in lock files#20300

Merged
pelikhan merged 5 commits intomainfrom
copilot/fix-lock-file-version-after-upgrade
Mar 10, 2026
Merged

fix: auto-upgrade gh-aw extension during gh aw upgrade to prevent stale version in lock files#20300
pelikhan merged 5 commits intomainfrom
copilot/fix-lock-file-version-after-upgrade

Conversation

Copy link
Contributor

Copilot AI commented Mar 10, 2026

gh aw upgrade detected outdated extension versions but only warned, then continued compiling lock files with the old version string baked into the running process. Lock file headers (GH_AW_INFO_CLI_VERSION) and generated YAML ended up referencing the previous version.

Changes

  • update_extension_check.go — New upgradeExtensionIfOutdated(verbose bool) (bool, error) that:

    • Automatically runs gh extension upgrade github/gh-aw when a newer release is detected
    • Uses golang.org/x/mod/semver.Compare instead of string comparison (fixes incorrect ordering for versions like 0.9.0 vs 0.10.0)
    • Returns (true, nil) on successful upgrade; silently ignores API/network errors; skips dev builds
  • upgrade_command.go — Replaces the warn-only ensureLatestExtensionVersion call with upgradeExtensionIfOutdated. When an upgrade is performed, the command automatically re-launches the freshly-installed binary with the same flags plus a hidden --skip-extension-upgrade flag that prevents infinite recursion. This ensures all subsequent steps (codemods, lock-file compilation) run under the new binary and embed the correct version string. The relaunchWithSameArgs helper re-execs the binary with forwarded stdin/stdout/stderr and preserves the child exit code.

  • update_extension_check_test.go — Tests for upgradeExtensionIfOutdated covering dev build skip and silent API failure.

Behaviour

Scenario Before After
Newer version available Warn only; compile with old version Auto-upgrade; relaunch new binary transparently
Already up to date Silent / verbose message Continue upgrade normally
API unreachable Continue silently Continue silently (unchanged)
Dev build Skip check Skip check (unchanged)

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@pelikhan
Copy link
Contributor

@copilot if upgrade occurred, relaunch cli with same flags (and a special flag to prevent recursion hidden)

…run with new version

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix lock files to reference correct version after gh aw upgrade fix: auto-upgrade gh-aw extension during gh aw upgrade to prevent stale version in lock files Mar 10, 2026
…e version in lock files

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

Copilot AI commented Mar 10, 2026

@copilot if upgrade occurred, relaunch cli with same flags (and a special flag to prevent recursion hidden)

Done in be37b31. After the extension is upgraded, the CLI now re-launches the freshly-installed binary automatically with the same flags plus a hidden --skip-extension-upgrade flag that prevents the re-launched process from entering the upgrade branch again (recursion guard).

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c &#34;prettier&#34; --check &#39;**/*.cjs&#39; &#39;*GOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go go (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan pelikhan marked this pull request as ready for review March 10, 2026 04:19
Copilot AI review requested due to automatic review settings March 10, 2026 04:19
Copy link
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 fixes a bug where gh aw upgrade would detect an outdated extension version but only warn, then continue compiling lock files with the old version string baked into the running process. The fix introduces automatic self-upgrade via gh extension upgrade and re-launching the freshly-installed binary with a hidden --skip-extension-upgrade flag to prevent recursion, ensuring all subsequent steps use the correct version string. Additionally, it replaces string-based version comparison with proper semver comparison via golang.org/x/mod/semver.

Changes:

  • Added upgradeExtensionIfOutdated() in update_extension_check.go that auto-upgrades the extension and uses proper semver comparison
  • Modified upgrade_command.go to relaunch the new binary after upgrade via relaunchWithSameArgs(), with a hidden --skip-extension-upgrade flag to prevent infinite recursion
  • Added tests for dev build skip and silent API failure scenarios

Reviewed changes

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

File Description
pkg/cli/update_extension_check.go New upgradeExtensionIfOutdated function with semver-based comparison and automatic gh extension upgrade
pkg/cli/upgrade_command.go Replaced warn-only check with auto-upgrade + relaunch mechanism; added relaunchWithSameArgs helper and --skip-extension-upgrade flag
pkg/cli/update_extension_check_test.go Tests for dev build skip and silent API failure in the new function

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

You can also share your feedback on Copilot code review. Take the survey.

if upgraded {
upgradeLog.Print("Extension was upgraded; re-launching with new binary")
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Continuing upgrade with newly installed version..."))
return relaunchWithSameArgs("--skip-extension-upgrade")
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

Bug: When --create-pull-request (or --pr) is passed and the extension is upgraded, the child process relaunched via relaunchWithSameArgs receives all original arguments including --create-pull-request. The child process performs the full upgrade and creates the PR. After the child exits successfully, relaunchWithSameArgs returns nil, which propagates back to RunE. The code at line 100 then checks createPR again and attempts to create a second PR.

To fix this, runUpgradeCommand should signal to the caller that a relaunch occurred (e.g., by returning a sentinel error or a boolean), so that RunE can skip the PR creation step. Alternatively, the relaunch path could call os.Exit(0) after the child succeeds (similar to how it handles child failures), since the child has already done all the work.

Suggested change
return relaunchWithSameArgs("--skip-extension-upgrade")
if err := relaunchWithSameArgs("--skip-extension-upgrade"); err != nil {
// If the child process failed, propagate the error to the caller.
return err
}
// The child process completed successfully and has already performed the upgrade
// (including any side effects such as creating pull requests). Exit the parent
// process so we do not repeat the remaining steps.
os.Exit(0)
return nil

Copilot uses AI. Check for mistakes.
Comment on lines +147 to +156
// Fall back to normalised string comparison when versions are not valid semver.
currentNorm := strings.TrimPrefix(currentVersion, "v")
latestNorm := strings.TrimPrefix(latestVersion, "v")
if currentNorm >= latestNorm {
updateExtensionCheckLog.Print("Extension is already up to date (string comparison fallback)")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("✓ gh-aw extension is up to date"))
}
return false, nil
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

Bug: The string comparison fallback (currentNorm >= latestNorm) suffers from the exact same lexicographic ordering problem the PR claims to fix. For example, "0.9.0" >= "0.10.0" evaluates to true lexicographically (since "9" > "1"), which would incorrectly report the extension as up-to-date when it's actually outdated. This would prevent the upgrade from happening, which is the opposite of what the PR intends.

While this fallback is only reached for non-semver version strings, it would be safer to log a warning and proceed with the upgrade attempt rather than relying on broken string comparison. Or simply remove this fallback and always require valid semver.

Suggested change
// Fall back to normalised string comparison when versions are not valid semver.
currentNorm := strings.TrimPrefix(currentVersion, "v")
latestNorm := strings.TrimPrefix(latestVersion, "v")
if currentNorm >= latestNorm {
updateExtensionCheckLog.Print("Extension is already up to date (string comparison fallback)")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("✓ gh-aw extension is up to date"))
}
return false, nil
}
// Versions are not valid semver; skip unreliable string comparison and
// proceed with upgrade to avoid incorrectly treating an outdated version
// as up to date.
updateExtensionCheckLog.Printf("Non-semver versions detected (current=%q, latest=%q); proceeding with upgrade", currentVersion, latestVersion)

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Contributor

@coplot review and apply comments

@pelikhan
Copy link
Contributor

@copilot review and apply comments

…ove broken string-comparison fallback

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

Copilot AI commented Mar 10, 2026

@copilot review and apply comments

Both review comments addressed in 011edea:

  1. Duplicate PR creationrelaunchWithSameArgs now calls os.Exit(0) on success so the parent process terminates immediately after the child finishes, preventing a second CreatePRWithChanges call.

  2. Broken string-comparison fallback — removed the currentNorm >= latestNorm branch entirely. For non-semver versions we now log a debug message and fall through to the upgrade, avoiding the "0.9.0" >= "0.10.0" false-positive.

@pelikhan
Copy link
Contributor

@copilot review and simplify updates

… dead ensureLatestExtensionVersion

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

Copilot AI commented Mar 10, 2026

@copilot review and simplify updates

Done in 518c7e4. Simplifications applied:

  • v-prefix normalization condensed from 4-line if !strings.HasPrefix blocks to single-line "v" + strings.TrimPrefix(..., "v") expressions
  • Arg-copy in relaunchWithSameArgs collapsed from 4 lines to one append(append([]string(nil), os.Args[1:]...), extraFlag)
  • Removed the dead ensureLatestExtensionVersion function (no production callers since upgradeExtensionIfOutdated replaced it) and its two now-redundant tests

@pelikhan pelikhan merged commit 746d9ab into main Mar 10, 2026
51 checks passed
@pelikhan pelikhan deleted the copilot/fix-lock-file-version-after-upgrade branch March 10, 2026 05:48
github-actions bot added a commit that referenced this pull request Mar 21, 2026
Adds the 🌍 Community Contributions table with 5 confirmed attributions
linking community-labeled issues to their resolving PRs:

- #21630 (@Mossaka) → #21655 sparse-checkout support docs
- #21243 (@holwerda) → #21286 github-app auth in dependencies
- #20299 (@grahame-white) → #20300 fix gh aw upgrade lock files
- #20249 (@mvdbos) → #20301 cross-repo workflow_call validation
- #18480 (@JoshGreenslade) → #21993 GHE Cloud data residency docs

Also flags 241 community-labeled issues as attribution candidates
needing manual review.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

Bug: gh aw upgrade generates lock files with previous version after upgrade

3 participants