Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions pkg/cli/update_extension_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,70 @@ 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.
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()
outputStr := strings.TrimSpace(string(output))

// Check for authentication errors (missing or invalid token)
if err != nil || isAuthenticationError(outputStr) {
if verbose {
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 due to auth issues, allow the upgrade to proceed
return nil
}

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
}
58 changes: 58 additions & 0 deletions pkg/cli/update_extension_check_test.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
}
7 changes: 7 additions & 0 deletions pkg/cli/upgrade_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Loading