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
17 changes: 5 additions & 12 deletions pkg/cli/mcp_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"time"

"github.com/githubnext/gh-aw/pkg/console"
"github.com/githubnext/gh-aw/pkg/constants"
"github.com/githubnext/gh-aw/pkg/parser"
"github.com/githubnext/gh-aw/pkg/workflow"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -356,14 +355,13 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e

// If workflow file is specified, extract MCP configurations and start servers
if workflowFile != "" {
workflowsDir := constants.GetWorkflowDir()

// Normalize the workflow file path
if !strings.HasSuffix(workflowFile, ".md") {
workflowFile += ".md"
// Resolve the workflow file path (supports shared workflows)
workflowPath, err := ResolveWorkflowPath(workflowFile)
if err != nil {
return err
}

workflowPath := filepath.Join(workflowsDir, workflowFile)
// Convert to absolute path if needed
if !filepath.IsAbs(workflowPath) {
cwd, err := os.Getwd()
if err != nil {
Expand All @@ -372,11 +370,6 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e
workflowPath = filepath.Join(cwd, workflowPath)
}

// Check if file exists
if _, err := os.Stat(workflowPath); os.IsNotExist(err) {
return fmt.Errorf("workflow file not found: %s", workflowPath)
}

// Parse the workflow file to extract MCP configurations
content, err := os.ReadFile(workflowPath)
if err != nil {
Expand Down
34 changes: 16 additions & 18 deletions pkg/cli/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,29 @@ import (
// ResolveWorkflowPath resolves a workflow file path from various formats:
// - Absolute path to .md file
// - Relative path to .md file
// - Workflow name (adds .md extension and looks in .github/workflows)
// - Workflow name with .md extension
// - Workflow name or subpath (e.g., "a.md" -> ".github/workflows/a.md", "shared/b.md" -> ".github/workflows/shared/b.md")
func ResolveWorkflowPath(workflowFile string) (string, error) {
workflowsDir := ".github/workflows"
var workflowPath string

if strings.HasSuffix(workflowFile, ".md") {
// If it's already a .md file, use it directly if it exists
if _, err := os.Stat(workflowFile); err == nil {
workflowPath = workflowFile
} else {
// Try in workflows directory
workflowPath = filepath.Join(workflowsDir, workflowFile)
}
} else {
// Add .md extension and look in workflows directory
workflowPath = filepath.Join(workflowsDir, workflowFile+".md")
// Add .md extension if not present
searchPath := workflowFile
if !strings.HasSuffix(searchPath, ".md") {
searchPath += ".md"
}

// Verify the workflow file exists
if _, err := os.Stat(workflowPath); os.IsNotExist(err) {
return "", fmt.Errorf("workflow file not found: %s", workflowPath)
// 1. If it's a path that exists as-is (absolute or relative), use it
if _, err := os.Stat(searchPath); err == nil {
return searchPath, nil
}

return workflowPath, nil
// 2. Try exact relative path under .github/workflows
workflowPath := filepath.Join(workflowsDir, searchPath)
if _, err := os.Stat(workflowPath); err == nil {
return workflowPath, nil
}

// No matches found
return "", fmt.Errorf("workflow file not found: %s", workflowPath)
}

// NormalizeWorkflowFile normalizes a workflow file name by adding .md extension if missing
Expand Down
58 changes: 54 additions & 4 deletions pkg/cli/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,84 @@ func TestResolveWorkflowPath(t *testing.T) {
t.Fatalf("Failed to change to temp directory: %v", err)
}

// Create .github/workflows directory
// Create .github/workflows directory structure
workflowsDir := filepath.Join(constants.GetWorkflowDir())
if err := os.MkdirAll(workflowsDir, 0755); err != nil {
t.Fatalf("Failed to create workflows directory: %v", err)
}

// Create test workflow files
sharedDir := filepath.Join(workflowsDir, "shared")
if err := os.MkdirAll(sharedDir, 0755); err != nil {
t.Fatalf("Failed to create shared directory: %v", err)
}

sharedMCPDir := filepath.Join(sharedDir, "mcp")
if err := os.MkdirAll(sharedMCPDir, 0755); err != nil {
t.Fatalf("Failed to create shared/mcp directory: %v", err)
}

// Create test workflow files in different locations
testWorkflow := filepath.Join(workflowsDir, "test-workflow.md")
if err := os.WriteFile(testWorkflow, []byte("# Test"), 0644); err != nil {
t.Fatalf("Failed to create test workflow: %v", err)
}

sharedWorkflow := filepath.Join(sharedDir, "shared-workflow.md")
if err := os.WriteFile(sharedWorkflow, []byte("# Shared"), 0644); err != nil {
t.Fatalf("Failed to create shared workflow: %v", err)
}

mcpWorkflow := filepath.Join(sharedMCPDir, "serena.md")
if err := os.WriteFile(mcpWorkflow, []byte("# MCP"), 0644); err != nil {
t.Fatalf("Failed to create MCP workflow: %v", err)
}

tests := []struct {
name string
input string
expected string
expectError bool
}{
{
name: "workflow name without extension",
name: "workflow name without extension in workflows dir",
input: "test-workflow",
expected: testWorkflow,
},
{
name: "workflow name with extension",
name: "workflow name with extension in workflows dir",
input: "test-workflow.md",
expected: testWorkflow,
},
{
name: "full relative path to shared workflow",
input: "shared/shared-workflow.md",
expected: sharedWorkflow,
},
{
name: "full relative path to shared workflow without extension",
input: "shared/shared-workflow",
expected: sharedWorkflow,
},
{
name: "full relative path to shared/mcp workflow",
input: "shared/mcp/serena.md",
expected: mcpWorkflow,
},
{
name: "full relative path to shared/mcp workflow without extension",
input: "shared/mcp/serena",
expected: mcpWorkflow,
},
{
name: "basename only (no recursive matching)",
input: "serena",
expectError: true,
},
{
name: "partial subpath (no recursive matching)",
input: "mcp/serena",
expectError: true,
},
{
name: "nonexistent workflow",
input: "nonexistent",
Expand Down
Loading