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
28 changes: 26 additions & 2 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ For detailed help on any command, use:
}

var newCmd = &cobra.Command{
Use: "new [workflow-base-name]",
Use: "new [workflow-id]",
Short: "Create a new workflow Markdown file with example configuration",
Long: `Create a new workflow Markdown file with commented examples and explanations of all available options.

Expand All @@ -63,10 +63,14 @@ When called with a workflow name, creates a template file with comprehensive exa
- Tools configuration (github, claude, mcps)
- All frontmatter options with explanations

The workflow-id is the basename of the markdown file without the .md extension.
You can provide either the workflow-id (e.g., 'my-workflow') or the full filename (e.g., 'my-workflow.md').

Examples:
` + constants.CLIExtensionPrefix + ` new # Interactive mode
` + constants.CLIExtensionPrefix + ` new --interactive # Interactive mode (explicit)
` + constants.CLIExtensionPrefix + ` new my-workflow # Create template file
` + constants.CLIExtensionPrefix + ` new my-workflow.md # Create template file (alternative format)
` + constants.CLIExtensionPrefix + ` new issue-handler --force`,
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -105,8 +109,16 @@ Examples:
}

var removeCmd = &cobra.Command{
Use: "remove [pattern]",
Use: "remove [workflow-id-pattern]",
Short: "Remove workflow files matching the given name prefix",
Long: `Remove workflow files matching the given workflow-id pattern.

The workflow-id is the basename of the markdown file without the .md extension.
You can provide a workflow-id prefix to remove multiple workflows, or a specific workflow-id.

Examples:
` + constants.CLIExtensionPrefix + ` remove my-workflow # Remove specific workflow
` + constants.CLIExtensionPrefix + ` remove test- # Remove all workflows starting with 'test-'`,
Run: func(cmd *cobra.Command, args []string) {
var pattern string
if len(args) > 0 {
Expand All @@ -125,9 +137,13 @@ var enableCmd = &cobra.Command{
Short: "Enable agentic workflows",
Long: `Enable one or more workflows by ID, or all workflows if no IDs are provided.

The workflow-id is the basename of the markdown file without the .md extension.
You can provide either the workflow-id (e.g., 'ci-doctor') or the full filename (e.g., 'ci-doctor.md').

Examples:
` + constants.CLIExtensionPrefix + ` enable # Enable all workflows
` + constants.CLIExtensionPrefix + ` enable ci-doctor # Enable specific workflow
` + constants.CLIExtensionPrefix + ` enable ci-doctor.md # Enable specific workflow (alternative format)
` + constants.CLIExtensionPrefix + ` enable ci-doctor daily # Enable multiple workflows
` + constants.CLIExtensionPrefix + ` enable ci-doctor --repo owner/repo # Enable workflow in specific repository`,
Run: func(cmd *cobra.Command, args []string) {
Expand All @@ -144,9 +160,13 @@ var disableCmd = &cobra.Command{
Short: "Disable agentic workflows and cancel any in-progress runs",
Long: `Disable one or more workflows by ID, or all workflows if no IDs are provided.

The workflow-id is the basename of the markdown file without the .md extension.
You can provide either the workflow-id (e.g., 'ci-doctor') or the full filename (e.g., 'ci-doctor.md').

Examples:
` + constants.CLIExtensionPrefix + ` disable # Disable all workflows
` + constants.CLIExtensionPrefix + ` disable ci-doctor # Disable specific workflow
` + constants.CLIExtensionPrefix + ` disable ci-doctor.md # Disable specific workflow (alternative format)
` + constants.CLIExtensionPrefix + ` disable ci-doctor daily # Disable multiple workflows
` + constants.CLIExtensionPrefix + ` disable ci-doctor --repo owner/repo # Disable workflow in specific repository`,
Run: func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -262,8 +282,12 @@ The workflows must have been added as actions and compiled.
This command only works with workflows that have workflow_dispatch triggers.
It executes 'gh workflow run <workflow-lock-file>' to trigger each workflow on GitHub Actions.

The workflow-id is the basename of the markdown file without the .md extension.
You can provide either the workflow-id (e.g., 'daily-perf-improver') or the full filename (e.g., 'daily-perf-improver.md').

Examples:
gh aw run daily-perf-improver
gh aw run daily-perf-improver.md # Alternative format
gh aw run daily-perf-improver --repeat 3 # Run 3 times total
gh aw run daily-perf-improver --enable-if-needed # Enable if disabled, run, then restore state
gh aw run daily-perf-improver --auto-merge-prs # Auto-merge any PRs created during execution`,
Expand Down
5 changes: 5 additions & 0 deletions pkg/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func resolveWorkflowFile(fileOrWorkflowName string, verbose bool) (string, error
func NewWorkflow(workflowName string, verbose bool, force bool) error {
commandsLog.Printf("Creating new workflow: name=%s, force=%v", workflowName, force)

// Normalize the workflow name by removing .md extension if present
// This ensures consistent behavior whether user provides "my-workflow" or "my-workflow.md"
workflowName = strings.TrimSuffix(workflowName, ".md")
commandsLog.Printf("Normalized workflow name: %s", workflowName)

if verbose {
fmt.Printf("Creating new workflow: %s\n", workflowName)
}
Expand Down
12 changes: 10 additions & 2 deletions pkg/cli/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,12 @@ func TestNewWorkflow(t *testing.T) {
}
},
},
{
name: "create workflow with .md extension (should normalize)",
workflowName: "test-with-ext.md",
force: false,
expectedError: false,
},
}

for _, test := range tests {
Expand All @@ -590,7 +596,9 @@ func TestNewWorkflow(t *testing.T) {

// If no error expected, verify the file was created
if !test.expectedError {
filePath := ".github/workflows/" + test.workflowName + ".md"
// Normalize the workflow name for file path (remove .md if present)
normalizedName := strings.TrimSuffix(test.workflowName, ".md")
filePath := ".github/workflows/" + normalizedName + ".md"
if _, err := os.Stat(filePath); os.IsNotExist(err) {
t.Errorf("Expected workflow file was not created: %s", filePath)
}
Expand All @@ -607,7 +615,7 @@ func TestNewWorkflow(t *testing.T) {
"on:",
"permissions:",
"safe-outputs:",
"# " + test.workflowName,
"# " + normalizedName,
"workflow_dispatch:",
}
for _, element := range expectedElements {
Expand Down
3 changes: 2 additions & 1 deletion pkg/cli/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,12 @@ Downloaded artifacts include:
- workflow-logs/: GitHub Actions workflow run logs (job logs organized in subdirectory)

The workflow-id is the basename of the markdown file without the .md extension.
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removed line 'For example, for 'weekly-research.md', use 'weekly-research' as the workflow ID.' provided valuable clarification that's now missing. Consider preserving this explanatory example alongside the new dual-format information to maintain clarity about the relationship between filenames and workflow IDs.

Suggested change
The workflow-id is the basename of the markdown file without the .md extension.
The workflow-id is the basename of the markdown file without the .md extension.
For example, for 'weekly-research.md', use 'weekly-research' as the workflow ID.

Copilot uses AI. Check for mistakes.
For example, for 'weekly-research.md', use 'weekly-research' as the workflow ID.
You can provide either the workflow-id (e.g., 'weekly-research') or the full filename (e.g., 'weekly-research.md').

Examples:
` + constants.CLIExtensionPrefix + ` logs # Download logs for all workflows
` + constants.CLIExtensionPrefix + ` logs weekly-research # Download logs for specific workflow
` + constants.CLIExtensionPrefix + ` logs weekly-research.md # Download logs (alternative format)
` + constants.CLIExtensionPrefix + ` logs -c 10 # Download last 10 matching runs
` + constants.CLIExtensionPrefix + ` logs --start-date 2024-01-01 # Download all runs after date
` + constants.CLIExtensionPrefix + ` logs --end-date 2024-01-31 # Download all runs before date
Expand Down
4 changes: 4 additions & 0 deletions pkg/cli/update_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ For workflow updates, it fetches the latest version based on the current ref:
- If the ref is a branch, it fetches the latest commit from that branch
- Otherwise, it fetches the latest commit from the default branch

The workflow-id is the basename of the markdown file without the .md extension.
You can provide either the workflow-id (e.g., 'ci-doctor') or the full filename (e.g., 'ci-doctor.md').

Examples:
` + constants.CLIExtensionPrefix + ` update # Check gh-aw updates and update all workflows
` + constants.CLIExtensionPrefix + ` update ci-doctor # Check gh-aw updates and update specific workflow
` + constants.CLIExtensionPrefix + ` update ci-doctor.md # Check gh-aw updates and update specific workflow (alternative format)
` + constants.CLIExtensionPrefix + ` update ci-doctor --major # Allow major version updates
` + constants.CLIExtensionPrefix + ` update --pr # Create PR with changes
` + constants.CLIExtensionPrefix + ` update --force # Force update even if no changes
Expand Down
Loading