From 3a6151ba0e9e4e5e8c96747438aae691968acb40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 05:18:42 +0000 Subject: [PATCH 1/3] Initial plan From a4de0f5dd33683c1671a85fa9b5b9c25d91fe5fe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 05:28:25 +0000 Subject: [PATCH 2/3] Add version check to upgrade command - Add ensureLatestExtensionVersion function to check if gh-aw is on latest version - Upgrade command now fails with clear message if extension needs updating - Show command to upgrade: gh extension upgrade githubnext/gh-aw - If version check fails, stop execution before performing upgrade steps Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/update_extension_check.go | 49 +++++++++++++++++++++++++++++++ pkg/cli/upgrade_command.go | 7 +++++ 2 files changed, 56 insertions(+) diff --git a/pkg/cli/update_extension_check.go b/pkg/cli/update_extension_check.go index 7d8635b68ed..722d7d8cca8 100644 --- a/pkg/cli/update_extension_check.go +++ b/pkg/cli/update_extension_check.go @@ -49,3 +49,52 @@ func checkExtensionUpdate(verbose bool) error { return nil } + +// ensureLatestExtensionVersion checks if a newer version of gh-aw is available +// and returns an error if an update is needed. This is used by the upgrade command +// to ensure users are on the latest version before upgrading workflows. +func ensureLatestExtensionVersion(verbose bool) error { + if verbose { + fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Checking for gh-aw extension updates...")) + } + + // Run gh extension upgrade --dry-run to check for updates + cmd := workflow.ExecGH("extension", "upgrade", "githubnext/gh-aw", "--dry-run") + output, err := cmd.CombinedOutput() + if err != nil { + if verbose { + fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to check for extension updates: %v", err))) + } + // If we can't check for updates, allow the upgrade to proceed + return nil + } + + outputStr := strings.TrimSpace(string(output)) + if verbose { + fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Extension update check output: %s", outputStr))) + } + + // Parse the output to see if an update is available + // Expected format: "[agentics]: would have upgraded from v0.14.0 to v0.18.1" + lines := strings.Split(outputStr, "\n") + for _, line := range lines { + if strings.Contains(line, "[agentics]: would have upgraded from") { + fmt.Fprintln(os.Stderr, "") + fmt.Fprintln(os.Stderr, console.FormatErrorMessage("gh-aw extension is not on the latest version")) + fmt.Fprintln(os.Stderr, console.FormatInfoMessage(line)) + fmt.Fprintln(os.Stderr, "") + fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Please upgrade the gh extension first:")) + fmt.Fprintln(os.Stderr, console.FormatCommandMessage(" gh extension upgrade githubnext/gh-aw")) + fmt.Fprintln(os.Stderr, "") + return fmt.Errorf("gh-aw extension must be upgraded before running this command") + } + } + + if strings.Contains(outputStr, "✓ Successfully checked extension upgrades") { + if verbose { + fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("✓ gh-aw extension is up to date")) + } + } + + return nil +} diff --git a/pkg/cli/upgrade_command.go b/pkg/cli/upgrade_command.go index 175f03849fc..9e289b861f1 100644 --- a/pkg/cli/upgrade_command.go +++ b/pkg/cli/upgrade_command.go @@ -74,6 +74,13 @@ func runUpgradeCommand(verbose bool, workflowDir string, noFix bool, noCompile b upgradeLog.Printf("Running upgrade command: verbose=%v, workflowDir=%s, noFix=%v, noCompile=%v", verbose, workflowDir, noFix, noCompile) + // Step 0: Ensure gh-aw extension is on the latest version + fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Checking gh-aw extension version...")) + if err := ensureLatestExtensionVersion(verbose); err != nil { + upgradeLog.Printf("Extension version check failed: %v", err) + return err + } + // Step 1: Update all agent and prompt files (like init command) fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Updating agent and prompt files...")) upgradeLog.Print("Updating agent and prompt files") From a815f48f4827d7f6d093148ad5d238095b510c0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 06:07:01 +0000 Subject: [PATCH 3/3] Handle authentication errors in version check - Add isAuthenticationError() helper to detect missing/invalid tokens - Update ensureLatestExtensionVersion() to ignore auth errors - Allow upgrade to proceed when version check fails due to auth issues - Add comprehensive tests for authentication error detection Addresses feedback: ignore version check when token is missing or invalid Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/update_extension_check.go | 26 ++++++++++-- pkg/cli/update_extension_check_test.go | 58 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 pkg/cli/update_extension_check_test.go diff --git a/pkg/cli/update_extension_check.go b/pkg/cli/update_extension_check.go index 722d7d8cca8..73393a218ba 100644 --- a/pkg/cli/update_extension_check.go +++ b/pkg/cli/update_extension_check.go @@ -50,6 +50,18 @@ func checkExtensionUpdate(verbose bool) error { return nil } +// isAuthenticationError checks if an error message indicates an authentication issue +func isAuthenticationError(output string) bool { + lowerOutput := strings.ToLower(output) + return strings.Contains(lowerOutput, "authentication required") || + strings.Contains(lowerOutput, "gh_token") || + strings.Contains(lowerOutput, "github_token") || + strings.Contains(output, "set the GH_TOKEN environment variable") || + strings.Contains(lowerOutput, "permission") || + strings.Contains(lowerOutput, "not authenticated") || + strings.Contains(lowerOutput, "invalid token") +} + // ensureLatestExtensionVersion checks if a newer version of gh-aw is available // and returns an error if an update is needed. This is used by the upgrade command // to ensure users are on the latest version before upgrading workflows. @@ -61,15 +73,21 @@ func ensureLatestExtensionVersion(verbose bool) error { // Run gh extension upgrade --dry-run to check for updates cmd := workflow.ExecGH("extension", "upgrade", "githubnext/gh-aw", "--dry-run") output, err := cmd.CombinedOutput() - if err != nil { + outputStr := strings.TrimSpace(string(output)) + + // Check for authentication errors (missing or invalid token) + if err != nil || isAuthenticationError(outputStr) { if verbose { - fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to check for extension updates: %v", err))) + if err != nil { + fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to check for extension updates: %v", err))) + } else { + fmt.Fprintln(os.Stderr, console.FormatWarningMessage("Authentication required to check for updates")) + } } - // If we can't check for updates, allow the upgrade to proceed + // If we can't check for updates due to auth issues, allow the upgrade to proceed return nil } - outputStr := strings.TrimSpace(string(output)) if verbose { fmt.Fprintln(os.Stderr, console.FormatVerboseMessage(fmt.Sprintf("Extension update check output: %s", outputStr))) } diff --git a/pkg/cli/update_extension_check_test.go b/pkg/cli/update_extension_check_test.go new file mode 100644 index 00000000000..1825565513e --- /dev/null +++ b/pkg/cli/update_extension_check_test.go @@ -0,0 +1,58 @@ +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsAuthenticationError(t *testing.T) { + tests := []struct { + name string + output string + expected bool + }{ + { + name: "GH_TOKEN environment variable error", + output: "gh: To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable", + expected: true, + }, + { + name: "authentication required", + output: "error: authentication required", + expected: true, + }, + { + name: "invalid token", + output: "error: invalid token provided", + expected: true, + }, + { + name: "not authenticated", + output: "You are not authenticated to GitHub", + expected: true, + }, + { + name: "permission denied", + output: "error: permission denied", + expected: true, + }, + { + name: "successful check", + output: "✓ Successfully checked extension upgrades", + expected: false, + }, + { + name: "upgrade available", + output: "[agentics]: would have upgraded from v0.14.0 to v0.18.1", + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := isAuthenticationError(tt.output) + assert.Equal(t, tt.expected, result, "isAuthenticationError() should return %v for: %s", tt.expected, tt.output) + }) + } +}