diff --git a/cmd/gh-aw/main.go b/cmd/gh-aw/main.go index 794cbe619d..e8576e3307 100644 --- a/cmd/gh-aw/main.go +++ b/cmd/gh-aw/main.go @@ -97,7 +97,7 @@ Examples: workflowName = args[0] } - return cli.CreateWorkflowInteractively(workflowName, verbose, forceFlag) + return cli.CreateWorkflowInteractively(cmd.Context(), workflowName, verbose, forceFlag) } // Template mode with workflow name diff --git a/pkg/cli/add_command.go b/pkg/cli/add_command.go index 63931725d9..f9a320deb4 100644 --- a/pkg/cli/add_command.go +++ b/pkg/cli/add_command.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "os" "path/filepath" @@ -113,8 +112,7 @@ Note: To create a new workflow from scratch, use the 'new' command instead.`, if useInteractive { addLog.Print("Using interactive mode") - ctx := context.Background() - return RunAddInteractive(ctx, workflows, verbose, engineOverride, noGitattributes, workflowDir, noStopAfter, stopAfter) + return RunAddInteractive(cmd.Context(), workflows, verbose, engineOverride, noGitattributes, workflowDir, noStopAfter, stopAfter) } // Handle normal (non-interactive) mode diff --git a/pkg/cli/interactive.go b/pkg/cli/interactive.go index 77d882042c..13a3fb75e1 100644 --- a/pkg/cli/interactive.go +++ b/pkg/cli/interactive.go @@ -43,7 +43,7 @@ type InteractiveWorkflowBuilder struct { } // CreateWorkflowInteractively prompts the user to build a workflow interactively -func CreateWorkflowInteractively(workflowName string, verbose bool, force bool) error { +func CreateWorkflowInteractively(ctx context.Context, workflowName string, verbose bool, force bool) error { interactiveLog.Printf("Starting interactive workflow creation: workflowName=%s, force=%v", workflowName, force) // Assert this function is not running in automated unit tests @@ -77,7 +77,7 @@ func CreateWorkflowInteractively(workflowName string, verbose bool, force bool) } // Compile the workflow - if err := builder.compileWorkflow(verbose); err != nil { + if err := builder.compileWorkflow(ctx, verbose); err != nil { return fmt.Errorf("failed to compile workflow: %w", err) } @@ -472,7 +472,7 @@ func (b *InteractiveWorkflowBuilder) describeTrigger() string { } // compileWorkflow automatically compiles the generated workflow -func (b *InteractiveWorkflowBuilder) compileWorkflow(verbose bool) error { +func (b *InteractiveWorkflowBuilder) compileWorkflow(ctx context.Context, verbose bool) error { interactiveLog.Printf("Starting workflow compilation: name=%s, verbose=%v", b.WorkflowName, verbose) // Create spinner for compilation progress @@ -494,7 +494,7 @@ func (b *InteractiveWorkflowBuilder) compileWorkflow(verbose bool) error { TrialLogicalRepoSlug: "", } - _, err := CompileWorkflows(context.Background(), config) + _, err := CompileWorkflows(ctx, config) if err != nil { spinner.Stop() diff --git a/pkg/cli/interactive_test.go b/pkg/cli/interactive_test.go index 7abca5b276..287c090a67 100644 --- a/pkg/cli/interactive_test.go +++ b/pkg/cli/interactive_test.go @@ -3,6 +3,7 @@ package cli import ( + "context" "os" "strings" "testing" @@ -420,7 +421,7 @@ func TestCreateWorkflowInteractively_InAutomatedEnvironment(t *testing.T) { }) // Test should fail in automated environment - err := CreateWorkflowInteractively("test-workflow", false, false) + err := CreateWorkflowInteractively(context.Background(), "test-workflow", false, false) if err == nil { t.Error("Expected error in automated environment, got nil") } @@ -455,8 +456,8 @@ func TestCreateWorkflowInteractively_WithForceFlag(t *testing.T) { }) // Both with and without force should fail in CI - err1 := CreateWorkflowInteractively("test-workflow", false, false) - err2 := CreateWorkflowInteractively("test-workflow", false, true) + err1 := CreateWorkflowInteractively(context.Background(), "test-workflow", false, false) + err2 := CreateWorkflowInteractively(context.Background(), "test-workflow", false, true) if err1 == nil || err2 == nil { t.Error("Expected errors in CI environment") @@ -479,7 +480,7 @@ func TestInteractiveWorkflowBuilder_compileWorkflow_SpinnerIntegration(t *testin // Test with invalid workflow (should handle error correctly) // This will fail compilation but should not panic - err := builder.compileWorkflow(false) + err := builder.compileWorkflow(context.Background(), false) // We expect an error since the workflow doesn't exist if err == nil { diff --git a/pkg/cli/run_push.go b/pkg/cli/run_push.go index 755ab2861d..e964586cd4 100644 --- a/pkg/cli/run_push.go +++ b/pkg/cli/run_push.go @@ -22,7 +22,7 @@ var runPushLog = logger.New("cli:run_push") // and the transitive closure of all imported files. // Note: This function always recompiles the workflow to ensure the lock file is up-to-date, // regardless of the frontmatter hash status. -func collectWorkflowFiles(workflowPath string, verbose bool) ([]string, error) { +func collectWorkflowFiles(ctx context.Context, workflowPath string, verbose bool) ([]string, error) { runPushLog.Printf("Collecting files for workflow: %s", workflowPath) files := make(map[string]bool) // Use map to avoid duplicates @@ -78,7 +78,7 @@ func collectWorkflowFiles(workflowPath string, verbose bool) ([]string, error) { // Always recompile (hash check is for observability only) runPushLog.Printf("Always recompiling workflow: %s", absWorkflowPath) - if err := recompileWorkflow(absWorkflowPath, verbose); err != nil { + if err := recompileWorkflow(ctx, absWorkflowPath, verbose); err != nil { runPushLog.Printf("Failed to recompile workflow: %v", err) return nil, fmt.Errorf("failed to recompile workflow: %w", err) } @@ -119,7 +119,7 @@ func collectWorkflowFiles(workflowPath string, verbose bool) ([]string, error) { } // recompileWorkflow compiles a workflow using CompileWorkflows -func recompileWorkflow(workflowPath string, verbose bool) error { +func recompileWorkflow(ctx context.Context, workflowPath string, verbose bool) error { runPushLog.Printf("Recompiling workflow: %s", workflowPath) config := CompileConfig{ @@ -139,8 +139,6 @@ func recompileWorkflow(workflowPath string, verbose bool) error { runPushLog.Printf("Compilation config: Validate=%v, NoEmit=%v", config.Validate, config.NoEmit) - // Use background context for compilation - ctx := context.Background() runPushLog.Printf("Starting compilation with CompileWorkflows") if _, err := CompileWorkflows(ctx, config); err != nil { runPushLog.Printf("Compilation failed: %v", err) diff --git a/pkg/cli/run_push_integration_test.go b/pkg/cli/run_push_integration_test.go index 819a6d4a45..7e148f3ec9 100644 --- a/pkg/cli/run_push_integration_test.go +++ b/pkg/cli/run_push_integration_test.go @@ -3,6 +3,7 @@ package cli import ( + "context" "os" "path/filepath" "testing" @@ -33,7 +34,7 @@ This is a test workflow without a lock file. require.NoError(t, err) // Test collecting files - should now compile the workflow and create lock file - files, err := collectWorkflowFiles(workflowPath, false) + files, err := collectWorkflowFiles(context.Background(), workflowPath, false) require.NoError(t, err) assert.Len(t, files, 2, "Should collect workflow .md file and auto-generate lock file") diff --git a/pkg/cli/run_push_test.go b/pkg/cli/run_push_test.go index f5f258d2ea..79d28d9db6 100644 --- a/pkg/cli/run_push_test.go +++ b/pkg/cli/run_push_test.go @@ -3,6 +3,7 @@ package cli import ( + "context" "fmt" "os" "os/exec" @@ -40,7 +41,7 @@ on: workflow_dispatch require.NoError(t, err) // Test collecting files - files, err := collectWorkflowFiles(workflowPath, false) + files, err := collectWorkflowFiles(context.Background(), workflowPath, false) require.NoError(t, err) assert.Len(t, files, 2, "Should collect workflow .md and .lock.yml files") @@ -88,7 +89,7 @@ on: workflow_dispatch require.NoError(t, err) // Test collecting files - files, err := collectWorkflowFiles(workflowPath, false) + files, err := collectWorkflowFiles(context.Background(), workflowPath, false) require.NoError(t, err) assert.Len(t, files, 3, "Should collect workflow, lock, and imported files") @@ -149,7 +150,7 @@ on: workflow_dispatch require.NoError(t, err) // Test collecting files - files, err := collectWorkflowFiles(workflowPath, false) + files, err := collectWorkflowFiles(context.Background(), workflowPath, false) require.NoError(t, err) assert.Len(t, files, 4, "Should collect workflow, lock, and all transitive imports") @@ -483,7 +484,7 @@ jobs: time.Sleep(100 * time.Millisecond) // Collect workflow files (which should always trigger recompilation) - files, err := collectWorkflowFiles(workflowPath, false) + files, err := collectWorkflowFiles(context.Background(), workflowPath, false) require.NoError(t, err) assert.Len(t, files, 2, "Should collect workflow .md and .lock.yml files") diff --git a/pkg/cli/run_workflow_execution.go b/pkg/cli/run_workflow_execution.go index 9fa8062bc6..7a0d78deba 100644 --- a/pkg/cli/run_workflow_execution.go +++ b/pkg/cli/run_workflow_execution.go @@ -248,7 +248,7 @@ func RunWorkflowOnGitHub(ctx context.Context, workflowIdOrName string, enable bo // Collect the workflow .md file, .lock.yml file, and transitive imports workflowMarkdownPath := stringutil.LockFileToMarkdown(lockFilePath) - files, err := collectWorkflowFiles(workflowMarkdownPath, verbose) + files, err := collectWorkflowFiles(ctx, workflowMarkdownPath, verbose) if err != nil { return fmt.Errorf("failed to collect workflow files: %w", err) } diff --git a/pkg/cli/trial_command.go b/pkg/cli/trial_command.go index e86819c3ef..b975df41ae 100644 --- a/pkg/cli/trial_command.go +++ b/pkg/cli/trial_command.go @@ -1,6 +1,7 @@ package cli import ( + "context" "encoding/json" "fmt" "os" @@ -156,7 +157,7 @@ Trial results are saved both locally (in trials/ directory) and in the host repo Verbose: verbose, } - if err := RunWorkflowTrials(workflowSpecs, opts); err != nil { + if err := RunWorkflowTrials(cmd.Context(), workflowSpecs, opts); err != nil { return err } return nil @@ -193,7 +194,7 @@ Trial results are saved both locally (in trials/ directory) and in the host repo } // RunWorkflowTrials executes the main logic for trialing one or more workflows -func RunWorkflowTrials(workflowSpecs []string, opts TrialOptions) error { +func RunWorkflowTrials(ctx context.Context, workflowSpecs []string, opts TrialOptions) error { trialLog.Printf("Starting trial execution: specs=%v, logicalRepo=%s, cloneRepo=%s, hostRepo=%s, repeat=%d", workflowSpecs, opts.Repos.LogicalRepo, opts.Repos.CloneRepo, opts.Repos.HostRepo, opts.RepeatCount) // Parse all workflow specifications @@ -424,7 +425,7 @@ func RunWorkflowTrials(workflowSpecs []string, opts TrialOptions) error { fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("=== Running trial for workflow: %s ===", parsedSpec.WorkflowName))) // Install workflow with trial mode compilation - if err := installWorkflowInTrialMode(tempDir, parsedSpec, logicalRepoSlug, cloneRepoSlug, hostRepoSlug, secretTracker, opts.EngineOverride, opts.AppendText, opts.PushSecrets, directTrialMode, opts.Verbose); err != nil { + if err := installWorkflowInTrialMode(ctx, tempDir, parsedSpec, logicalRepoSlug, cloneRepoSlug, hostRepoSlug, secretTracker, opts.EngineOverride, opts.AppendText, opts.PushSecrets, directTrialMode, opts.Verbose); err != nil { return fmt.Errorf("failed to install workflow '%s' in trial mode: %w", parsedSpec.WorkflowName, err) } diff --git a/pkg/cli/trial_repository.go b/pkg/cli/trial_repository.go index b9bde84610..50bb32feaf 100644 --- a/pkg/cli/trial_repository.go +++ b/pkg/cli/trial_repository.go @@ -163,7 +163,7 @@ func cloneTrialHostRepository(repoSlug string, verbose bool) (string, error) { } // installWorkflowInTrialMode installs a workflow in trial mode using a parsed spec -func installWorkflowInTrialMode(tempDir string, parsedSpec *WorkflowSpec, logicalRepoSlug, cloneRepoSlug, hostRepoSlug string, secretTracker *TrialSecretTracker, engineOverride string, appendText string, pushSecrets bool, directTrialMode bool, verbose bool) error { +func installWorkflowInTrialMode(ctx context.Context, tempDir string, parsedSpec *WorkflowSpec, logicalRepoSlug, cloneRepoSlug, hostRepoSlug string, secretTracker *TrialSecretTracker, engineOverride string, appendText string, pushSecrets bool, directTrialMode bool, verbose bool) error { trialRepoLog.Printf("Installing workflow in trial mode: workflow=%s, hostRepo=%s, directMode=%v", parsedSpec.WorkflowName, hostRepoSlug, directTrialMode) // Change to temp directory @@ -226,7 +226,7 @@ func installWorkflowInTrialMode(tempDir string, parsedSpec *WorkflowSpec, logica TrialMode: !directTrialMode && (cloneRepoSlug == ""), // Enable trial mode in compiler unless in direct mode or clone-repo mode TrialLogicalRepoSlug: logicalRepoSlug, } - workflowDataList, err := CompileWorkflows(context.Background(), config) + workflowDataList, err := CompileWorkflows(ctx, config) if err != nil { return fmt.Errorf("failed to compile workflow: %w", err) }