Skip to content

Commit 0d9a940

Browse files
Copilotpelikhan
andcommitted
Fix campaign workflow compilation in watch mode
- Add campaign package import to compile_helpers.go - Update compileSingleFile to handle .campaign.md files specially - Validates campaign spec and referenced workflows - Generates and compiles campaign orchestrator workflow (.campaign.g.md) - Update handleFileDeleted to clean up campaign orchestrator files - Update compile_watch.go to use compileSingleFile for initial compilation - Ensures watch mode matches main compile orchestrator behavior Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent ff5bc22 commit 0d9a940

File tree

2 files changed

+97
-7
lines changed

2 files changed

+97
-7
lines changed

pkg/cli/compile_helpers.go

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"strings"
88

9+
"github.com/githubnext/gh-aw/pkg/campaign"
910
"github.com/githubnext/gh-aw/pkg/console"
1011
"github.com/githubnext/gh-aw/pkg/logger"
1112
"github.com/githubnext/gh-aw/pkg/workflow"
@@ -27,6 +28,65 @@ func compileSingleFile(compiler *workflow.Compiler, file string, stats *Compilat
2728

2829
stats.Total++
2930

31+
// Handle campaign spec files separately from regular workflows
32+
if strings.HasSuffix(file, ".campaign.md") {
33+
compileHelpersLog.Printf("Processing campaign spec file: %s", file)
34+
if verbose {
35+
fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Validating campaign spec: %s", file)))
36+
}
37+
38+
// Validate the campaign spec file and referenced workflows
39+
spec, problems, vErr := campaign.ValidateSpecFromFile(file)
40+
if vErr != nil {
41+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("failed to validate campaign spec %s: %v", file, vErr)))
42+
stats.Errors++
43+
stats.FailedWorkflows = append(stats.FailedWorkflows, filepath.Base(file))
44+
return true
45+
}
46+
47+
// Also ensure that workflows referenced by the campaign spec exist
48+
workflowsDir := filepath.Dir(file)
49+
workflowProblems := campaign.ValidateWorkflowsExist(spec, workflowsDir)
50+
problems = append(problems, workflowProblems...)
51+
52+
if len(problems) > 0 {
53+
for _, p := range problems {
54+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(p))
55+
}
56+
stats.Errors++
57+
stats.FailedWorkflows = append(stats.FailedWorkflows, filepath.Base(file))
58+
return true
59+
}
60+
61+
// Generate and compile the campaign orchestrator workflow
62+
if verbose {
63+
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Validated campaign spec %s", filepath.Base(file))))
64+
}
65+
66+
_, genErr := generateAndCompileCampaignOrchestrator(
67+
compiler,
68+
spec,
69+
file,
70+
verbose,
71+
false, // noEmit
72+
false, // zizmor
73+
false, // poutine
74+
false, // actionlint
75+
false, // strict
76+
false, // validateActionSHAs
77+
)
78+
if genErr != nil {
79+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(fmt.Sprintf("failed to compile campaign orchestrator for %s: %v", filepath.Base(file), genErr)))
80+
stats.Errors++
81+
stats.FailedWorkflows = append(stats.FailedWorkflows, filepath.Base(file))
82+
} else {
83+
compileHelpersLog.Printf("Successfully compiled campaign orchestrator for: %s", file)
84+
}
85+
86+
return true
87+
}
88+
89+
// Regular workflow file - compile normally
3090
compileHelpersLog.Printf("Compiling: %s", file)
3191
if verbose {
3292
fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Compiling: %s", file)))
@@ -256,7 +316,39 @@ func compileModifiedFilesWithDependencies(compiler *workflow.Compiler, depGraph
256316

257317
// handleFileDeleted handles the deletion of a markdown file by removing its corresponding lock file
258318
func handleFileDeleted(mdFile string, verbose bool) {
259-
// Generate the corresponding lock file path
319+
// For campaign spec files, remove both the generated orchestrator and its lock file
320+
if strings.HasSuffix(mdFile, ".campaign.md") {
321+
// Remove the generated .campaign.g.md file
322+
orchestratorFile := strings.TrimSuffix(mdFile, ".campaign.md") + ".campaign.g.md"
323+
if _, err := os.Stat(orchestratorFile); err == nil {
324+
if err := os.Remove(orchestratorFile); err != nil {
325+
if verbose {
326+
fmt.Printf("⚠️ Failed to remove orchestrator file %s: %v\n", orchestratorFile, err)
327+
}
328+
} else {
329+
if verbose {
330+
fmt.Printf("🗑️ Removed generated orchestrator: %s\n", orchestratorFile)
331+
}
332+
}
333+
}
334+
335+
// Remove the orchestrator's lock file
336+
orchestratorLockFile := strings.TrimSuffix(mdFile, ".campaign.md") + ".campaign.g.lock.yml"
337+
if _, err := os.Stat(orchestratorLockFile); err == nil {
338+
if err := os.Remove(orchestratorLockFile); err != nil {
339+
if verbose {
340+
fmt.Printf("⚠️ Failed to remove orchestrator lock file %s: %v\n", orchestratorLockFile, err)
341+
}
342+
} else {
343+
if verbose {
344+
fmt.Printf("🗑️ Removed orchestrator lock file: %s\n", orchestratorLockFile)
345+
}
346+
}
347+
}
348+
return
349+
}
350+
351+
// Regular workflow file - generate the corresponding lock file path
260352
lockFile := strings.TrimSuffix(mdFile, ".md") + ".lock.yml"
261353

262354
// Check if the lock file exists and remove it

pkg/cli/compile_watch.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,15 @@ func watchAndCompileWorkflows(markdownFile string, compiler *workflow.Compiler,
132132
compiler.ResetWarningCount()
133133

134134
// Track compilation statistics for single file
135-
stats := &CompilationStats{Total: 1}
135+
stats := &CompilationStats{}
136136

137137
fmt.Fprintln(os.Stderr, "Watching for file changes")
138138
if verbose {
139139
fmt.Fprintln(os.Stderr, console.FormatProgressMessage(fmt.Sprintf("Initial compilation of %s...", markdownFile)))
140140
}
141-
if err := CompileWorkflowWithValidation(compiler, markdownFile, verbose, false, false, false, false, false); err != nil {
142-
// Always show initial compilation errors on new line without wrapping
143-
fmt.Fprintln(os.Stderr, err.Error())
144-
stats.Errors++
145-
}
141+
142+
// Use compileSingleFile to handle both regular workflows and campaign files
143+
compileSingleFile(compiler, markdownFile, stats, verbose, false)
146144

147145
// Get warning count from compiler
148146
stats.Warnings = compiler.GetWarningCount()

0 commit comments

Comments
 (0)