8000
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
2 changes: 1 addition & 1 deletion docs/src/content/docs/setup/cli.md
Original file line number Diff line n 8000 umber Diff line change
Expand Up @@ -177,7 +177,7 @@ gh aw new my-workflow --force # Overwrite if exists
gh aw new my-workflow --engine claude # Inject engine into frontmatter
```

**Options:** `--force`, `--engine/-e`
**Options:** `--force`, `--engine/-e`, `--interactive/-i`

When `--engine` is specified, the engine is injected into the generated frontmatter template:

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/audit_diff_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
func NewAuditDiffSubcommand() *cobra.Command {
cmd := &cobra.Command{
Use: "diff <run-id-1> <run-id-2>",
Short: "Compare workflow run behavior across two workflow runs",
Short: "Compare behavior across two workflow runs",
Long: `Compare workflow run behavior between two workflow runs to detect policy regressions,
new unauthorized domains, behavioral drift, and changes in MCP tool usage or run metrics.

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/init_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ After running this command, you can:
- Add workflows from the catalog with: ` + string(constants.CLIExtensionPrefix) + ` add <workflow-name>
- Create new workflows from scratch with: ` + string(constants.CLIExtensionPrefix) + ` new <workflow-name>

To create, update or debug automated agentic actions using github, playwright, and other tools, load the .github/agents/agentic-workflows.agent.md (applies to .github/workflows/*.md)
To create, update or debug automated agentic actions using GitHub, playwright, and other tools, load the .github/agents/agentic-workflows.agent.md (applies to .github/workflows/*.md)

Examples:
` + string(constants.CLIExtensionPrefix) + ` init # Interactive mode
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/logs_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Examples:
logsCmd.Flags().Bool("filtered-integrity", false, "Filter to runs with DIFC (data integrity flow control) integrity-filtered items in the gateway logs")
logsCmd.Flags().Bool("parse", false, "Run JavaScript parsers on agent logs and firewall logs, writing Markdown to log.md and firewall.md")
addJSONFlag(logsCmd)
logsCmd.Flags().Int("timeout", 0, "Download timeout in seconds (0 = no timeout)")
logsCmd.Flags().Int("timeout", 0, "Download timeout in minutes (0 = no timeout)")
logsCmd.Flags().String("summary-file", "summary.json", "Path to write the summary JSON file relative to output directory (use empty string to disable)")
logsCmd.MarkFlagsMutuallyExclusive("firewall", "no-firewall")

Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/logs_orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func DownloadWorkflowLogs(ctx context.Context, workflowName string, count int, s
if timeout > 0 {
startTime = time.Now()
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Timeout set to %d seconds", timeout)))
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Timeout set to %d minutes", timeout)))
}
}

Expand All @@ -98,7 +98,7 @@ func DownloadWorkflowLogs(ctx context.Context, workflowName string, count int, s
// Check timeout if specified
if timeout > 0 {
elapsed := time.Since(startTime).Seconds()
if elapsed >= float64(timeout) {
if elapsed >= float64(timeout)*60 {
timeoutReached = true
if verbose {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Timeout reached after %.1f seconds, stopping download", elapsed)))
Expand Down
58 changes: 32 additions & 26 deletions pkg/cli/logs_timeout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,25 @@ func TestTimeoutFlagParsing(t *testing.T) {
name string
timeout int
expectTimeout bool
expectedSeconds int
expectedMinutes int
}{
{
name: "no timeout specified",
timeout: 0,
expectTimeout: false,
expectedSeconds: 0,
expectedMinutes: 0,
},
{
name: "timeout of 50 seconds",
timeout: 50,
name: "timeout of 5 minutes",
timeout: 5,
expectTimeout: true,
expectedSeconds: 50,
expectedMinutes: 5,
},
{
name: "timeout of 120 seconds",
timeout: 120,
name: "timeout of 30 minutes",
timeout: 30,
expectTimeout: true,
expectedSeconds: 120,
expectedMinutes: 30,
},
}

Expand All @@ -44,8 +44,8 @@ func TestTimeoutFlagParsing(t *testing.T) {
if !tt.expectTimeout && tt.timeout != 0 {
t.Errorf("Expected no timeout but got %d", tt.timeout)
}
if tt.expectTimeout && tt.timeout != tt.expectedSeconds {
t.Errorf("Expected timeout of %d seconds but got %d", tt.expectedSeconds, tt.timeout)
if tt.expectTimeout && tt.timeout != tt.expectedMinutes {
t.Errorf("Expected timeout of %d minutes but got %d", tt.expectedMinutes, tt.timeout)
}
})
}
Expand All @@ -62,41 +62,47 @@ func TestTimeoutLogic(t *testing.T) {
{
name: "no timeout set",
timeout: 0,
elapsed: 100 * time.Second,
elapsed: 100 * time.Minute,
shouldTimeout: false,
},
{
name: "timeout not reached",
timeout: 60,
elapsed: 30 * time.Second,
elapsed: 30 * time.Minute,
shouldTimeout: false,
},
{
name: "just under boundary",
timeout: 1,
elapsed: 59 * time.Second,
shouldTimeout: false,
},
{
name: "timeout exactly reached",
timeout: 50,
elapsed: 50 * time.Second,
timeout: 1,
elapsed: 60 * time.Second,
shouldTimeout: true,
},
{
name: "timeout exceeded",
timeout: 30,
elapsed: 45 * time.Second,
timeout: 1,
elapsed: 90 * time.Second,
shouldTimeout: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Simulate the timeout check logic
// Simulate the timeout check logic (timeout is in minutes, elapsed in seconds)
var timeoutReached bool
if tt.timeout > 0 {
if tt.elapsed.Seconds() >= float64(tt.timeout) {
if tt.elapsed.Seconds() >= float64(tt.timeout)*60 {
timeoutReached = true
}
}

if timeoutReached != tt.shouldTimeout {
t.Errorf("Expected timeout reached=%v but got %v (timeout=%d, elapsed=%.1fs)",
t.Errorf("Expected timeout reached=%v but got %v (timeout=%d min, elapsed=%.1fs)",
tt.shouldTimeout, timeoutReached, tt.timeout, tt.elapsed.Seconds())
}
})
Expand All @@ -105,23 +111,23 @@ func TestTimeoutLogic(t *testing.T) {

// TestMCPServerDefaultTimeout tests that the MCP server sets a default timeout
func TestMCPServerDefaultTimeout(t *testing.T) {
// Test that when no timeout is specified, MCP server uses 50 seconds
// Test that when no timeout is specified, MCP server uses 1 minute
timeoutValue := 0
if timeoutValue == 0 {
timeoutValue = 50
timeoutValue = 1
}

if timeoutValue != 50 {
t.Errorf("Expected MCP server default timeout to be 50 but got %d", timeoutValue)
if timeoutValue != 1 {
t.Errorf("Expected MCP server default timeout to be 1 but got %d", timeoutValue)
}

// Test that explicit timeout overrides the default
timeoutValue = 120
timeoutValue = 5
if timeoutValue == 0 {
timeoutValue = 50
timeoutValue = 1
}

if timeoutValue != 120 {
if timeoutValue != 5 {
t.Errorf("Expected explicit timeout to be preserved but got %d", timeoutValue)
}
}
8 changes: 4 additions & 4 deletions pkg/cli/mcp_tools_privileged.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func registerLogsTool(server *mcp.Server, execCmd execCmdFunc, actor string, val
Branch string `json:"branch,omitempty" jsonschema:"Filter runs by branch name"`
AfterRunID int64 `json:"after_run_id,omitempty" jsonschema:"Filter runs with database ID after this value (exclusive)"`
BeforeRunID int64 `json:"before_run_id,omitempty" jsonschema:"Filter runs with database ID before this value (exclusive)"`
Timeout int `json:"timeout,omitempty" jsonschema:"Maximum time in seconds to spend downloading logs (default: 50 for MCP server)"`
Timeout int `json:"timeout,omitempty" jsonschema:"Maximum time in minutes to spend downloading logs (default: 1 for MCP server)"`
MaxTokens int `json:"max_tokens,omitempty" jsonschema:"Maximum number of tokens in output before triggering guardrail (default: 12000)"`
}

Expand All @@ -42,7 +42,7 @@ func registerLogsTool(server *mcp.Server, execCmd execCmdFunc, actor string, val
if err := AddSchemaDefault(logsSchema, "count", 100); err != nil {
mcpLog.Printf("Failed to add default for count: %v", err)
}
if err := AddSchemaDefault(logsSchema, "timeout", 50); err != nil {
if err := AddSchemaDefault(logsSchema, "timeout", 1); err != nil {
mcpLog.Printf("Failed to add default for timeout: %v", err)
}
if err := AddSchemaDefault(logsSchema, "max_tokens", 12000); err != nil {
Expand Down Expand Up @@ -150,10 +150,10 @@ return a schema description instead of the full output. Adjust the 'max_tokens'
cmdArgs = append(cmdArgs, "--before-run-id", strconv.FormatInt(args.BeforeRunID, 10))
}

// Set timeout to 50 seconds for MCP server if not explicitly specified
// Set timeout to 1 minute for MCP server if not explicitly specified
timeoutValue := args.Timeout
if timeoutValue == 0 {
timeoutValue = 50
timeoutValue = 1
}
cmdArgs = append(cmdArgs, "--timeout", strconv.Itoa(timeoutValue))

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/project_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ The project can optionally be linked to a specific repository.

Authentication Requirements:
The default GITHUB_TOKEN cannot create projects. You must use additional authentication.
See https://github.github.com/gh-aw/reference/auth-projects/.
See https://github.github.io/gh-aw/reference/auth-projects/.

Project Setup:
Use --with-project-setup to automatically create:
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/tokens_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ This command:
Only required secrets are prompted for. Optional secrets are not shown.

For full details, including precedence rules, see the GitHub Tokens
reference in the documentation.
reference at https://github.github.io/gh-aw/reference/tokens/.

Examples:
gh aw secrets bootstrap # Check and set up all required secrets
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/validate_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ Examples:

cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")
cmd.Flags().Bool("strict", false, "Enforce strict mode validation for all workflows")
cmd.Flags().Bool("strict", false, "Override frontmatter to enforce strict mode validation for all workflows (enforces action pinning, network config, safe-outputs, refuses write permissions and deprecated fields). Note: Workflows default to strict mode unless frontmatter sets strict: false")
cmd.Flags().BoolP("json", "j", false, "Output results in JSON format")
cmd.Flags().Bool("fail-fast", false, "Stop at the first validation error instead of collecting all errors")
cmd.Flags().Bool("stats", false, "Display statistics table sorted by file size")
cmd.Flags().Bool("stats", false, "Display statistics table sorted by file size (shows jobs, steps, scripts, and shells)")
cmd.Flags().Bool("no-check-update", false, "Skip checking for gh-aw updates")

// Register completions
Expand Down
Loading
0