Skip to content

Commit 57b6619

Browse files
authored
Add --dir flag and deprecate --workflows-dir in compile command (#3928)
1 parent f9caf64 commit 57b6619

7 files changed

Lines changed: 217 additions & 16 deletions

File tree

cmd/gh-aw/main.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,15 @@ The --dependabot flag generates dependency manifests when dependencies are detec
135135
- For Go: Creates go.mod for go install/get packages
136136
- Creates .github/dependabot.yml with all detected ecosystems
137137
- Use --force to overwrite existing dependabot.yml
138-
- Cannot be used with specific workflow files or custom --workflows-dir
138+
- Cannot be used with specific workflow files or custom --dir
139139
- Only processes workflows in the default .github/workflows directory
140140
141141
Examples:
142142
` + constants.CLIExtensionPrefix + ` compile # Compile all Markdown files
143143
` + constants.CLIExtensionPrefix + ` compile ci-doctor # Compile a specific workflow
144144
` + constants.CLIExtensionPrefix + ` compile ci-doctor daily-plan # Compile multiple workflows
145145
` + constants.CLIExtensionPrefix + ` compile workflow.md # Compile by file path
146-
` + constants.CLIExtensionPrefix + ` compile --workflows-dir custom/workflows # Compile from custom directory
146+
` + constants.CLIExtensionPrefix + ` compile --dir custom/workflows # Compile from custom directory
147147
` + constants.CLIExtensionPrefix + ` compile --watch ci-doctor # Watch and auto-compile
148148
` + constants.CLIExtensionPrefix + ` compile --trial --logical-repo owner/repo # Compile for trial mode
149149
` + constants.CLIExtensionPrefix + ` compile --dependabot # Generate Dependabot manifests
@@ -152,7 +152,8 @@ Examples:
152152
engineOverride, _ := cmd.Flags().GetString("engine")
153153
validate, _ := cmd.Flags().GetBool("validate")
154154
watch, _ := cmd.Flags().GetBool("watch")
155-
workflowDir, _ := cmd.Flags().GetString("workflows-dir")
155+
dir, _ := cmd.Flags().GetString("dir")
156+
workflowsDir, _ := cmd.Flags().GetString("workflows-dir")
156157
noEmit, _ := cmd.Flags().GetBool("no-emit")
157158
purge, _ := cmd.Flags().GetBool("purge")
158159
strict, _ := cmd.Flags().GetBool("strict")
@@ -169,6 +170,16 @@ Examples:
169170
fmt.Fprintln(os.Stderr, console.FormatErrorMessage(err.Error()))
170171
os.Exit(1)
171172
}
173+
174+
// Handle --workflows-dir deprecation
175+
workflowDir := dir
176+
if workflowsDir != "" {
177+
if dir != "" {
178+
fmt.Fprintln(os.Stderr, console.FormatErrorMessage("cannot use both --dir and --workflows-dir flags"))
179+
os.Exit(1)
180+
}
181+
workflowDir = workflowsDir
182+
}
172183
config := cli.CompileConfig{
173184
MarkdownFiles: args,
174185
Verbose: verbose,
@@ -347,7 +358,9 @@ Use "` + constants.CLIExtensionPrefix + ` help all" to show help for all command
347358
compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
348359
compileCmd.Flags().Bool("validate", false, "Enable GitHub Actions workflow schema validation, container image validation, and action SHA validation")
349360
compileCmd.Flags().BoolP("watch", "w", false, "Watch for changes to workflow files and recompile automatically")
350-
compileCmd.Flags().String("workflows-dir", "", "Relative directory containing workflows (default: .github/workflows)")
361+
compileCmd.Flags().String("dir", "", "Relative directory containing workflows (default: .github/workflows)")
362+
compileCmd.Flags().String("workflows-dir", "", "Deprecated: use --dir instead")
363+
_ = compileCmd.Flags().MarkDeprecated("workflows-dir", "use --dir instead")
351364
compileCmd.Flags().Bool("no-emit", false, "Validate workflow without generating lock files")
352365
compileCmd.Flags().Bool("purge", false, "Delete .lock.yml files that were not regenerated during compilation (only when no specific files are specified)")
353366
compileCmd.Flags().Bool("strict", false, "Enable strict mode: require timeout, refuse write permissions, require network configuration")

docs/src/content/docs/status.mdx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ Status of all agentic workflows. [Browse source files](https://github.com/github
1616
| [Blog Auditor](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/blog-auditor.md) | claude | [![Blog Auditor](https://github.com/githubnext/gh-aw/actions/workflows/blog-auditor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/blog-auditor.lock.yml) | `0 12 * * 3` | - |
1717
| [Brave Web Search Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/brave.md) | copilot | [![Brave Web Search Agent](https://github.com/githubnext/gh-aw/actions/workflows/brave.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/brave.lock.yml) | - | `/brave` |
1818
| [Changeset Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/changeset.md) | copilot | [![Changeset Generator](https://github.com/githubnext/gh-aw/actions/workflows/changeset.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/changeset.lock.yml) | `0 */2 * * *` | - |
19-
| [CI Failure Doctor](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/ci-doctor.md) | copilot | [![CI Failure Doctor](https://github.com/githubnext/gh-aw/actions/workflows/ci-doctor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/ci-doctor.lock.yml) | - | - |
2019
| [CLI Consistency Checker](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/cli-consistency-checker.md) | copilot | [![CLI Consistency Checker](https://github.com/githubnext/gh-aw/actions/workflows/cli-consistency-checker.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/cli-consistency-checker.lock.yml) | `0 13 * * 1-5` | - |
2120
| [CLI Version Checker](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/cli-version-checker.md) | copilot | [![CLI Version Checker](https://github.com/githubnext/gh-aw/actions/workflows/cli-version-checker.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/cli-version-checker.lock.yml) | `0 15 * * *` | - |
2221
| [Commit Changes Analyzer](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/commit-changes-analyzer.md) | claude | [![Commit Changes Analyzer](https://github.com/githubnext/gh-aw/actions/workflows/commit-changes-analyzer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/commit-changes-analyzer.lock.yml) | - | - |
@@ -29,8 +28,6 @@ Status of all agentic workflows. [Browse source files](https://github.com/github
2928
| [Daily Documentation Updater](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-doc-updater.md) | claude | [![Daily Documentation Updater](https://github.com/githubnext/gh-aw/actions/workflows/daily-doc-updater.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-doc-updater.lock.yml) | `0 6 * * *` | - |
3029
| [Daily Firewall Logs Collector and Reporter](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-firewall-report.md) | copilot | [![Daily Firewall Logs Collector and Reporter](https://github.com/githubnext/gh-aw/actions/workflows/daily-firewall-report.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-firewall-report.lock.yml) | `0 10 * * *` | - |
3130
| [Daily News](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-news.md) | copilot | [![Daily News](https://github.com/githubnext/gh-aw/actions/workflows/daily-news.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-news.lock.yml) | `0 9 * * 1-5` | - |
32-
| [Daily Perf Improver](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-perf-improver.md) | copilot | [![Daily Perf Improver](https://github.com/githubnext/gh-aw/actions/workflows/daily-perf-improver.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-perf-improver.lock.yml) | `0 2 * * 1-5` | - |
33-
| [Daily Test Coverage Improver](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-test-improver.md) | copilot | [![Daily Test Coverage Improver](https://github.com/githubnext/gh-aw/actions/workflows/daily-test-improver.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-test-improver.lock.yml) | `0 2 * * 1-5` | - |
3431
| [Dependabot Go Module Dependency Checker](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/dependabot-go-checker.md) | copilot | [![Dependabot Go Module Dependency Checker](https://github.com/githubnext/gh-aw/actions/workflows/dependabot-go-checker.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/dependabot-go-checker.lock.yml) | `0 9 * * 1,3,5` | - |
3532
| [Dev](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/dev.md) | copilot | [![Dev](https://github.com/githubnext/gh-aw/actions/workflows/dev.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/dev.lock.yml) | - | - |
3633
| [Dev Firewall](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/dev.firewall.md) | copilot | [![Dev Firewall](https://github.com/githubnext/gh-aw/actions/workflows/dev.firewall.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/dev.firewall.lock.yml) | - | - |

pkg/cli/compile_command.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func validateCompileConfig(config CompileConfig) error {
200200
return fmt.Errorf("--dependabot flag cannot be used with specific workflow files")
201201
}
202202
if config.WorkflowDir != "" && config.WorkflowDir != ".github/workflows" {
203-
return fmt.Errorf("--dependabot flag cannot be used with custom --workflows-dir")
203+
return fmt.Errorf("--dependabot flag cannot be used with custom --dir")
204204
}
205205
}
206206

@@ -211,7 +211,7 @@ func validateCompileConfig(config CompileConfig) error {
211211

212212
// Validate workflow directory path
213213
if config.WorkflowDir != "" && filepath.IsAbs(config.WorkflowDir) {
214-
return fmt.Errorf("workflows-dir must be a relative path, got: %s", config.WorkflowDir)
214+
return fmt.Errorf("--dir must be a relative path, got: %s", config.WorkflowDir)
215215
}
216216

217217
return nil

pkg/cli/compile_command_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func TestCompileWorkflows_DependabotValidation(t *testing.T) {
161161
WorkflowDir: "custom/workflows",
162162
},
163163
expectError: true,
164-
errorMsg: "cannot be used with custom --workflows-dir",
164+
errorMsg: "cannot be used with custom --dir",
165165
},
166166
{
167167
name: "dependabot with default settings",

pkg/cli/compile_dependabot_validation_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,24 @@ func TestCompileDependabotValidation(t *testing.T) {
2121
errorMsg: "--dependabot flag cannot be used with specific workflow files",
2222
},
2323
{
24-
name: "dependabot with custom workflows-dir",
24+
name: "dependabot with custom --dir",
2525
config: CompileConfig{
2626
WorkflowDir: "custom/workflows",
2727
Dependabot: true,
2828
},
2929
expectError: true,
30-
errorMsg: "--dependabot flag cannot be used with custom --workflows-dir",
30+
errorMsg: "--dependabot flag cannot be used with custom --dir",
3131
},
3232
{
33-
name: "dependabot with default workflows-dir is ok",
33+
name: "dependabot with default workflows dir is ok",
3434
config: CompileConfig{
3535
WorkflowDir: ".github/workflows",
3636
Dependabot: true,
3737
},
3838
expectError: false,
3939
},
4040
{
41-
name: "dependabot with empty workflows-dir is ok",
41+
name: "dependabot with empty workflows dir is ok",
4242
config: CompileConfig{
4343
WorkflowDir: "",
4444
Dependabot: true,

pkg/cli/compile_dir_flag_test.go

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package cli
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"path/filepath"
7+
"testing"
8+
)
9+
10+
// TestCompileWithDirFlag tests the --dir flag functionality
11+
func TestCompileWithDirFlag(t *testing.T) {
12+
// Save current directory and defer restoration
13+
originalWd, err := os.Getwd()
14+
if err != nil {
15+
t.Fatalf("Failed to get current working directory: %v", err)
16+
}
17+
defer func() {
18+
_ = os.Chdir(originalWd)
19+
}()
20+
21+
// Create a temporary git repository with custom workflow directory
22+
tmpDir, err := os.MkdirTemp("", "dir-flag-test")
23+
if err != nil {
24+
t.Fatalf("Failed to create temp directory: %v", err)
25+
}
26+
defer os.RemoveAll(tmpDir)
27+
28+
// Change to temp directory
29+
if err := os.Chdir(tmpDir); err != nil {
30+
t.Fatalf("Failed to change to temp directory: %v", err)
31+
}
32+
33+
// Initialize git repository properly
34+
cmd := exec.Command("git", "init")
35+
cmd.Dir = tmpDir
36+
if err := cmd.Run(); err != nil {
37+
t.Fatalf("Failed to initialize git repository: %v", err)
38+
}
39+
40+
// Create custom workflow directory
41+
customDir := "my-workflows"
42+
if err := os.MkdirAll(customDir, 0755); err != nil {
43+
t.Fatalf("Failed to create custom workflow directory: %v", err)
44+
}
45+
46+
// Create a test workflow file
47+
workflowContent := `---
48+
on: push
49+
---
50+
51+
# Test Workflow
52+
53+
This is a test workflow in a custom directory.
54+
`
55+
workflowFile := filepath.Join(customDir, "test.md")
56+
if err := os.WriteFile(workflowFile, []byte(workflowContent), 0644); err != nil {
57+
t.Fatalf("Failed to create test workflow file: %v", err)
58+
}
59+
60+
// Test: Compile with --dir flag should work
61+
config := CompileConfig{
62+
MarkdownFiles: []string{},
63+
Verbose: false,
64+
EngineOverride: "",
65+
Validate: false,
66+
Watch: false,
67+
WorkflowDir: customDir,
68+
SkipInstructions: false,
69+
NoEmit: false,
70+
Purge: false,
71+
TrialMode: false,
72+
TrialLogicalRepoSlug: "",
73+
}
74+
_, err = CompileWorkflows(config)
75+
if err != nil {
76+
t.Errorf("CompileWorkflows with --dir should succeed, got error: %v", err)
77+
}
78+
79+
// Verify the lock file was created
80+
lockFile := filepath.Join(customDir, "test.lock.yml")
81+
if _, err := os.Stat(lockFile); os.IsNotExist(err) {
82+
t.Error("Expected lock file to be created in custom directory")
83+
}
84+
}
85+
86+
// TestCompileDirFlagValidation tests the validation of --dir flag
87+
func TestCompileDirFlagValidation(t *testing.T) {
88+
tests := []struct {
89+
name string
90+
workflowDir string
91+
expectError bool
92+
errorMsg string
93+
}{
94+
{
95+
name: "relative path is valid",
96+
workflowDir: "custom/workflows",
97+
expectError: false,
98+
},
99+
{
100+
name: "absolute path is invalid",
101+
workflowDir: "/absolute/path",
102+
expectError: true,
103+
errorMsg: "--dir must be a relative path, got: /absolute/path",
104+
},
105+
{
106+
name: "empty string defaults to .github/workflows",
107+
workflowDir: "",
108+
expectError: false,
109+
},
110+
}
111+
112+
for _, tt := range tests {
113+
t.Run(tt.name, func(t *testing.T) {
114+
// Create a temporary directory for each test
115+
tmpDir, err := os.MkdirTemp("", "dir-flag-validation-test")
116+
if err != nil {
117+
t.Fatalf("Failed to create temp directory: %v", err)
118+
}
119+
defer os.RemoveAll(tmpDir)
120+
121+
originalWd, err := os.Getwd()
122+
if err != nil {
123+
t.Fatalf("Failed to get current working directory: %v", err)
124+
}
125+
defer func() {
126+
_ = os.Chdir(originalWd)
127+
}()
128+
129+
if err := os.Chdir(tmpDir); err != nil {
130+
t.Fatalf("Failed to change to temp directory: %v", err)
131+
}
132+
133+
// Initialize git repository properly
134+
cmd := exec.Command("git", "init")
135+
cmd.Dir = tmpDir
136+
if err := cmd.Run(); err != nil {
137+
t.Fatalf("Failed to initialize git repository: %v", err)
138+
}
139+
140+
// For non-error cases, create the expected directory
141+
if !tt.expectError {
142+
expectedDir := tt.workflowDir
143+
if expectedDir == "" {
144+
expectedDir = ".github/workflows"
145+
}
146+
if err := os.MkdirAll(expectedDir, 0755); err != nil {
147+
t.Fatalf("Failed to create workflow directory: %v", err)
148+
}
149+
// Create a dummy workflow file
150+
workflowFile := filepath.Join(expectedDir, "test.md")
151+
workflowContent := `---
152+
on: push
153+
---
154+
155+
# Test Workflow
156+
`
157+
if err := os.WriteFile(workflowFile, []byte(workflowContent), 0644); err != nil {
158+
t.Fatalf("Failed to create test workflow file: %v", err)
159+
}
160+
}
161+
162+
// Test the compilation
163+
config := CompileConfig{
164+
MarkdownFiles: []string{},
165+
Verbose: false,
166+
EngineOverride: "",
167+
Validate: false,
168+
Watch: false,
169+
WorkflowDir: tt.workflowDir,
170+
SkipInstructions: false,
171+
NoEmit: false,
172+
Purge: false,
173+
TrialMode: false,
174+
TrialLogicalRepoSlug: "",
175+
}
176+
_, err = CompileWorkflows(config)
177+
178+
if tt.expectError {
179+
if err == nil {
180+
t.Errorf("Expected error for --dir '%s', but got none", tt.workflowDir)
181+
} else if err.Error() != tt.errorMsg {
182+
t.Errorf("Expected error message '%s', got '%s'", tt.errorMsg, err.Error())
183+
}
184+
} else {
185+
if err != nil {
186+
t.Errorf("Expected no error for --dir '%s', but got: %v", tt.workflowDir, err)
187+
}
188+
}
189+
})
190+
}
191+
}

pkg/cli/workflow_dir_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ This is a test workflow in a custom directory.
100100
if err == nil {
101101
t.Error("CompileWorkflows with absolute workflows-dir should fail")
102102
}
103-
if err != nil && err.Error() != "workflows-dir must be a relative path, got: /absolute/path" {
103+
if err != nil && err.Error() != "--dir must be a relative path, got: /absolute/path" {
104104
t.Errorf("Expected specific error message for absolute path, got: %v", err)
105105
}
106106

@@ -162,7 +162,7 @@ func TestCompileWorkflowsCustomDirValidation(t *testing.T) {
162162
name: "absolute path is invalid",
163163
workflowDir: "/absolute/path",
164164
expectError: true,
165-
errorMsg: "workflows-dir must be a relative path, got: /absolute/path",
165+
errorMsg: "--dir must be a relative path, got: /absolute/path",
166166
},
167167
{
168168
name: "path with .. is cleaned but valid",

0 commit comments

Comments
 (0)