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: 2 additions & 0 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ Action mode controls how gh-aw action scripts are referenced in compiled workflo
Three flags govern this. --gh-aw-ref is mutually exclusive with the other two;
--action-tag and --action-mode may be combined (e.g. --action-mode action --action-tag v1.2.3):

Unlike 'upgrade', compilation only applies codemods when you opt in with --fix.

--action-mode <mode>
Explicit mode selection. Values:
dev Local paths (./actions/...). For developing inside the gh-aw repo.
Expand Down
21 changes: 19 additions & 2 deletions docs/src/content/docs/setup/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ gh aw compile --purge # Remove orphaned .lock.yml files

If the repository root contains an [`aw.yml` manifest](/gh-aw/reference/aw-yml-package-manifest/), `gh aw compile` validates it before compiling workflows.

Unlike `gh aw upgrade`, `gh aw compile` does not run codemods unless you pass `--fix`.

**Options:** `--action-mode`, `--action-tag`, `--actionlint`, `--actions-repo`, `--allow-action-refs`, `--approve`, `--dependabot`, `--dir/-d`, `--engine/-e`, `--fail-fast`, `--fix`, `--force/-f`, `--force-refresh-action-pins`, `--gh-aw-ref`, `--ghes`, `--json/-j`, `--logical-repo/-l`, `--no-check-update`, `--no-emit`, `--no-models-dev-lookup`, `--poutine`, `--purge`, `--refresh-stop-time`, `--runner-guard`, `--schedule-seed`, `--show-all`, `--staged`, `--stats`, `--strict`, `--trial`, `--validate`, `--validate-images`, `--watch/-w`, `--zizmor`

**`--gh-aw-ref` flag:** Convenience alias for `--action-mode release --action-tag <ref>`. Accepts a branch name, tag, or commit SHA targeting the `github/gh-aw` repository. Branch and tag names are resolved to their full commit SHA at compile time, so the baked-in reference is immutable and reproducible. Useful for E2E-testing workflows compiled against a specific gh-aw revision.
Expand Down Expand Up @@ -417,7 +419,7 @@ Fast enumeration without GitHub API queries. For detailed status including enabl

#### `status`

List workflows with state, enabled/disabled status, schedules, and labels. With `--ref`, includes latest run status.
List workflows with state, enabled/disabled status, and labels. With `--ref`, includes latest run status. Use `--json` to inspect the raw `on` data, including schedules.

```bash wrap
gh aw status # All workflows
Expand Down Expand Up @@ -479,7 +481,7 @@ cat run-ids.txt | gh aw logs --stdin --repo owner/repo # required for bare num

#### `audit`

Analyze workflow runs with detailed reports. The `audit` command has three modes: a single-run audit (default), a cross-run diff, and a cross-run security report.
Analyze workflow runs with detailed reports. The `audit` command has two modes: a single-run audit (default) and a multi-run analysis.

##### `audit <run-id>`

Expand Down Expand Up @@ -621,6 +623,19 @@ gh aw forecast --eval # Backtest forecast quality against

The `--days` flag accepts only `7` or `30` (default: `30`). Other values produce an error.

#### `experiments`

Inspect experiment state tracked in `experiments/*` branches. The default command behavior matches `experiments list`; use `experiments analyze` for per-workflow statistics.

```bash wrap
gh aw experiments # List experiment workflow branches
gh aw experiments list --json # List all experiments in JSON format
gh aw experiments analyze my-workflow # Analyze one experiment workflow
gh aw experiments analyze my-workflow --repo owner/repo # Analyze experiments in another repository
```

**Options:** all `experiments` commands accept `--repo/-r`, `--json/-j`

### Management

#### `enable`
Expand Down Expand Up @@ -724,6 +739,8 @@ Org mode (`--org`) previews or creates upgrade pull requests across every reposi

Use `--disable-codemod` (repeatable) to skip specific codemod IDs during the embedded fix step. This flag is ignored when `--no-fix` is set.

Unlike `gh aw compile --fix`, `gh aw upgrade` runs codemods, action version updates, and workflow compilation by default and uses `--no-fix` to skip all three steps.

#### `env`

Manage compiler defaults as GitHub variables at repository, organization, or enterprise scope.
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/add_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ func registerAddCommandFlags(cmd *cobra.Command) {
// Add stop-after flag to add command
cmd.Flags().String("stop-after", "", "Override stop-after value in the workflow (e.g., '+48h', '2025-12-31 23:59:59')")

// Add no-security-scanner flag to add command (--disable-security-scanner is kept as an undocumented alias)
// Add no-security-scanner flag to add command (--disable-security-scanner is kept as a deprecated alias)
cmd.Flags().Bool("no-security-scanner", false, "Disable security scanning of workflow markdown content")
cmd.Flags().Bool("disable-security-scanner", false, "Disable security scanning of workflow markdown content")
_ = cmd.Flags().MarkHidden("disable-security-scanner")
_ = cmd.Flags().MarkDeprecated("disable-security-scanner", "use --no-security-scanner instead")

// Register completions for add command
RegisterEngineFlagCompletion(cmd)
Expand Down
9 changes: 9 additions & 0 deletions pkg/cli/add_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ func TestNewAddCommand_MentionsEnterpriseSourceResolution(t *testing.T) {
assert.Contains(t, cmd.Long, "Use full https://github.com/... source URLs for other public github.com workflows.")
}

func TestNewAddCommand_DeprecatesDisableSecurityScannerFlag(t *testing.T) {
cmd := NewAddCommand(validateEngineStub)
require.NotNil(t, cmd)

flag := cmd.Flags().Lookup("disable-security-scanner")
require.NotNil(t, flag, "add command should keep --disable-security-scanner as a deprecated alias")
assert.Equal(t, "use --no-security-scanner instead", flag.Deprecated)
}

func TestAddWorkflows(t *testing.T) {
tests := []struct {
name string
Expand Down
18 changes: 18 additions & 0 deletions pkg/cli/cli_consistency_help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func TestAuditCommandDescriptionsAreConsistent(t *testing.T) {

assert.Contains(t, cmd.Short, "workflow runs", "audit short description should describe multiple run inputs")
assert.Contains(t, cmd.Long, "Audit one or more workflow runs", "audit long description should describe multiple run inputs")
assert.Contains(t, cmd.Long, "remaining runs are compared against it", "audit help should document multi-run analysis mode")
}

func TestTrialCommandUsesStandardExamplesHeading(t *testing.T) {
Expand Down Expand Up @@ -63,6 +64,23 @@ func TestCompileDocsIncludeNoModelsDevLookupOption(t *testing.T) {

compileSection := text[compileIndex:]
assert.Contains(t, compileSection, "`--no-models-dev-lookup`", "compile docs options should include --no-models-dev-lookup")
assert.Contains(t, compileSection, "does not run codemods unless you pass `--fix`", "compile docs should explain --fix opt-in behavior")
}

func TestCLIDocsReflectStatusAuditAndExperimentsCommands(t *testing.T) {
_, currentFile, _, ok := runtime.Caller(0)
require.True(t, ok, "should resolve current test file path")

docsPath := filepath.Join(filepath.Dir(currentFile), "..", "..", "docs", "src", "content", "docs", "setup", "cli.md")
content, err := os.ReadFile(docsPath)
require.NoError(t, err, "should read CLI setup docs")

text := string(content)
assert.Contains(t, text, "#### `experiments`", "CLI setup docs should include the experiments command")
assert.Contains(t, text, "The `audit` command has two modes", "audit docs should describe the current two-mode behavior")
assert.NotContains(t, text, "enabled/disabled status, schedules, and labels", "status docs should not promise schedule output in console mode")
assert.Contains(t, text, "Use `--json` to inspect the raw `on` data, including schedules", "status docs should direct schedule inspection to JSON output")
assert.Contains(t, text, "runs codemods, action version updates, and workflow compilation by default and uses `--no-fix` to skip all three steps", "upgrade docs should explain the inverse --fix/--no-fix behavior")
}

func TestSubcommandListingsUseHyphenBullets(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/deploy_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func registerDeployFlags(cmd *cobra.Command) {
cmd.Flags().String("stop-after", "", "Override stop-after value in the workflow (e.g., '+48h', '2025-12-31 23:59:59')")
cmd.Flags().Bool("no-security-scanner", false, "Disable security scanning of workflow markdown content")
cmd.Flags().Bool("disable-security-scanner", false, "Disable security scanning of workflow markdown content")
_ = cmd.Flags().MarkHidden("disable-security-scanner")
_ = cmd.Flags().MarkDeprecated("disable-security-scanner", "use --no-security-scanner instead")
cmd.Flags().String("cool-down", defaultDeployCooldown, coolDownFlagUsage)
cmd.Flags().String("org", "", "Deploy workflows across repositories in an organization")
cmd.Flags().StringSlice("repos", nil, "Limit --org mode to repositories matching one or more glob patterns")
Expand Down
9 changes: 9 additions & 0 deletions pkg/cli/deploy_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ func TestNewDeployCommand_CoolDownFlagUsageMatchesUpdate(t *testing.T) {
assert.Equal(t, coolDownFlagUsage, coolDownFlag.Usage)
}

func TestNewDeployCommand_DeprecatesDisableSecurityScannerFlag(t *testing.T) {
cmd := NewDeployCommand(func(string) error { return nil })
require.NotNil(t, cmd)

flag := cmd.Flags().Lookup("disable-security-scanner")
require.NotNil(t, flag, "deploy command should keep --disable-security-scanner as a deprecated alias")
assert.Equal(t, "use --no-security-scanner instead", flag.Deprecated)
}

func TestNewDeployCommand_RequiresRepoFlag(t *testing.T) {
cmd := NewDeployCommand(func(string) error { return nil })
require.NotNil(t, cmd)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/trial_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Trial results are saved both locally (in trials/ directory) and in the host repo
cmd.Flags().String("append", "", "Append extra content to the end of agentic workflow on installation")
cmd.Flags().Bool("no-security-scanner", false, "Disable security scanning of workflow markdown content")
cmd.Flags().Bool("disable-security-scanner", false, "Disable security scanning of workflow markdown content")
_ = cmd.Flags().MarkHidden("disable-security-scanner")
_ = cmd.Flags().MarkDeprecated("disable-security-scanner", "use --no-security-scanner instead")
cmd.MarkFlagsMutuallyExclusive("logical-repo", "clone-repo")

return cmd
Expand Down
11 changes: 11 additions & 0 deletions pkg/cli/trial_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"testing"

"github.com/github/gh-aw/pkg/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewTrialCommandCloneRepoFlagDescription(t *testing.T) {
Expand Down Expand Up @@ -45,6 +47,15 @@ func TestNewTrialCommandNoArgsErrorIncludesExample(t *testing.T) {
}
}

func TestNewTrialCommand_DeprecatesDisableSecurityScannerFlag(t *testing.T) {
cmd := NewTrialCommand(func(string) error { return nil })
require.NotNil(t, cmd)

flag := cmd.Flags().Lookup("disable-security-scanner")
require.NotNil(t, flag, "trial command should keep --disable-security-scanner as a deprecated alias")
assert.Equal(t, "use --no-security-scanner instead", flag.Deprecated)
}

// Test the host repo slug processing logic with dot notation
func TestHostRepoSlugProcessing(t *testing.T) {
testCases := []struct {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/update_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ Note: In GitHub Enterprise repos, shorthand source specs resolve on your enterpr
cmd.Flags().Bool("no-merge", false, "Override local changes with upstream version instead of merging")
cmd.Flags().Bool("no-release-bump", false, "Disable automatic major version bumps for all actions (only core actions/* are force-updated)")
cmd.Flags().Bool("disable-release-bump", false, "Disable automatic major version bumps for all actions (only core actions/* are force-updated)")
_ = cmd.Flags().MarkHidden("disable-release-bump")
_ = cmd.Flags().MarkDeprecated("disable-release-bump", "use --no-release-bump instead")
cmd.Flags().Bool("no-security-scanner", false, "Disable security scanning of workflow markdown content")
cmd.Flags().Bool("disable-security-scanner", false, "Disable security scanning of workflow markdown content")
_ = cmd.Flags().MarkHidden("disable-security-scanner")
_ = cmd.Flags().MarkDeprecated("disable-security-scanner", "use --no-security-scanner instead")
cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files)")
cmd.Flags().Bool("no-redirect", false, "Refuse updates when redirect frontmatter is present")
cmd.Flags().String("org", "", "Preview or create workflow update pull requests across an organization")
Expand Down
14 changes: 12 additions & 2 deletions pkg/cli/update_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,19 @@ func TestNewUpdateCommand_HasDisableSecurityScannerFlag(t *testing.T) {
require.NotNil(t, flag, "update command should register --no-security-scanner")
assert.Equal(t, "Disable security scanning of workflow markdown content", flag.Usage, "flag help text should match add/trial wording")

// Undocumented alias should still be registered
// Deprecated alias should still be registered
deprecated := cmd.Flags().Lookup("disable-security-scanner")
require.NotNil(t, deprecated, "update command should keep --disable-security-scanner as undocumented alias")
require.NotNil(t, deprecated, "update command should keep --disable-security-scanner as a deprecated alias")
assert.Equal(t, "use --no-security-scanner instead", deprecated.Deprecated)
}

func TestNewUpdateCommand_DeprecatesDisableReleaseBumpFlag(t *testing.T) {
cmd := NewUpdateCommand(func(string) error { return nil })
require.NotNil(t, cmd)

flag := cmd.Flags().Lookup("disable-release-bump")
require.NotNil(t, flag, "update command should keep --disable-release-bump as a deprecated alias")
assert.Equal(t, "use --no-release-bump instead", flag.Deprecated)
}

func TestNewUpdateCommand_CoolDownFlagUsage(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/upgrade_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ This command:
4. Compiles all workflows to generate lock files (like 'compile' command)

Flag behavior:
- --no-fix skips codemods, action version updates, and workflow compilation
- upgrade runs codemods, action version updates, and workflow compilation by default; use --no-fix to skip all three steps
- --no-actions and --no-compile are only applied when --no-fix is not set
Comment on lines 46 to 48

DEPENDENCY HEALTH AUDIT:
Expand Down
Loading