From cb064ea421bbee73e529dd7db7b4d7fd58833f32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:00:10 +0000 Subject: [PATCH] fix: force extension upgrade for pinned gh-aw installs Agent-Logs-Url: https://github.com/github/gh-aw/sessions/898d3fb1-b027-479b-ae46-75cacc956ea8 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/upgrade-test.yml | 2 +- pkg/cli/update_extension_check.go | 13 +++++++++++-- pkg/cli/update_extension_check_test.go | 5 +++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/upgrade-test.yml b/.github/workflows/upgrade-test.yml index d4d39a6f9a0..2de6c4657e4 100644 --- a/.github/workflows/upgrade-test.yml +++ b/.github/workflows/upgrade-test.yml @@ -81,7 +81,7 @@ jobs: run: | # gh aw upgrade calls upgradeExtensionIfOutdated which: # 1. Detects current ($PREVIOUS) < latest ($LATEST) - # 2. Runs `gh extension upgrade github/gh-aw` + # 2. Runs `gh extension upgrade github/gh-aw --force` # 3. On Windows: binary is in use → rename+retry workaround is triggered # 4. Re-launches the freshly installed binary with --skip-extension-upgrade # --pre-releases ensures the upgrade check considers prereleases. diff --git a/pkg/cli/update_extension_check.go b/pkg/cli/update_extension_check.go index ec940c193e9..667ca6b6bfa 100644 --- a/pkg/cli/update_extension_check.go +++ b/pkg/cli/update_extension_check.go @@ -102,7 +102,7 @@ func upgradeExtensionIfOutdated(verbose bool, includePrereleases bool) (bool, st // rename+retry path succeeds and the user is not shown a confusing failure. var firstAttemptBuf bytes.Buffer firstAttemptOut := firstAttemptWriter(os.Stderr, &firstAttemptBuf) - firstCmd := exec.Command("gh", "extension", "upgrade", "github/gh-aw") + firstCmd := exec.Command("gh", extensionUpgradeArgs()...) firstCmd.Stdout = firstAttemptOut firstCmd.Stderr = firstAttemptOut firstErr := firstCmd.Run() @@ -146,7 +146,7 @@ func upgradeExtensionIfOutdated(verbose bool, includePrereleases bool) (bool, st } } - retryCmd := exec.Command("gh", "extension", "upgrade", "github/gh-aw") + retryCmd := exec.Command("gh", extensionUpgradeArgs()...) retryCmd.Stdout = os.Stderr retryCmd.Stderr = os.Stderr if retryErr := retryCmd.Run(); retryErr != nil { @@ -255,3 +255,12 @@ func isWindowsLockError(output string, err error) bool { } return false } + +// extensionUpgradeArgs returns the gh extension upgrade invocation used by +// self-upgrade checks. +// +// --force is required so pinned installs (e.g. `gh extension install ... --pin`) +// can be upgraded in-place. +func extensionUpgradeArgs() []string { + return []string{"extension", "upgrade", "github/gh-aw", "--force"} +} diff --git a/pkg/cli/update_extension_check_test.go b/pkg/cli/update_extension_check_test.go index 76e2313b123..0cf8c8672fe 100644 --- a/pkg/cli/update_extension_check_test.go +++ b/pkg/cli/update_extension_check_test.go @@ -224,3 +224,8 @@ func TestIsWindowsLockError(t *testing.T) { }) } } + +func TestExtensionUpgradeArgs(t *testing.T) { + args := extensionUpgradeArgs() + assert.Equal(t, []string{"extension", "upgrade", "github/gh-aw", "--force"}, args, "upgrade command must force upgrades for pinned extensions") +}