Skip to content

Add missing flags to run, audit, new, and list commands for CLI consistency#20272

Merged
pelikhan merged 2 commits intomainfrom
copilot/fix-cli-consistency-issues
Mar 10, 2026
Merged

Add missing flags to run, audit, new, and list commands for CLI consistency#20272
pelikhan merged 2 commits intomainfrom
copilot/fix-cli-consistency-issues

Conversation

Copy link
Contributor

Copilot AI commented Mar 9, 2026

Four commands were missing flags available in similar commands, creating an inconsistent CLI experience.

Changes

run — add --json / -j

  • Added JSON bool to RunOptions and a WorkflowRunResult struct
  • RunWorkflowsOnGitHub wraps execution to collect and emit a JSON array of triggered workflow results to stdout when flag is set

audit — add --repo / -r

  • Allows specifying owner/repo when passing a bare numeric run ID (without a full URL)
  • Validates owner/repo format and returns a clear error on malformed input

new — add --engine / -e

  • Validates the engine via the existing validateEngine() before use
  • Injects engine: <value> into the generated frontmatter template
---
permissions:
  contents: read
engine: copilot        # <-- injected when --engine is specified
network: defaults
...

list — add --dir / -d

  • Consistent with validate, fix, update, and add commands which all use --dir for local workflow directory overrides
  • --dir applies only when --repo is not set; --path continues to serve remote repo path resolution
  • Updated getMarkdownWorkflowFiles to respect the path parameter for local repos (was previously ignoring it)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha Use:.*&#34;run&#34;\|Use:.*&#34;list&#34;\|Use:.*&#34;new&#34;\|Use:.*&#34;aOUTPUT d/gh-aw/main.go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha Use:.*&#34;run&#34;\|Use-errorsas /home/REDACTED/wor-ifaceassert 64/bin/bash udit&#34; tstrap.go ache/node/24.14.-bool bash --no�� --noprofile grep x_amd64/vet udit&#34; chestrator_stabi--norc /home/REDACTED/.lo--noprofile x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha Use:.*&#34;run&#34;\|Use-errorsas /home/REDACTED/wor-ifaceassert nfig/composer/ve-nilfunc udit&#34; (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 grep fb95de217c768eabd3877da3c5f7430e-d udit&#34; ge_test.go /home/REDACTED/.co/tmp/gh-aw-test-runs/20260309-225132-15892/test-326203262 64/pkg/tool/linustatus --no�� --noprofile .cfg 64/pkg/tool/linux_amd64/vet udit&#34; ow_execution.go 64/bin/grep 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 grep 64/pkg/tool/linux_amd64/vet udit&#34; p_scripts_test.gcommit cal/bin/grep 64/pkg/tool/linuAdd workflow --no�� --noprofile .cfg x_amd64/compile udit&#34; _operations_testrev-parse rgo/bin/grep x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE eL/mCCnHxkTI7AZ9remote.origin.url (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 grep 64/pkg/tool/linux_amd64/compile udit&#34; p_scripts_test.gmaintenance ep 64/pkg/tool/linu--auto --no�� g_.a grep x_amd64/asm udit&#34; ow_execution.go nfig/composer/ve--git-dir x_amd64/asm (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env y-test.md GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 grep 64/pkg/tool/linux_amd64/vet udit&#34; ge_test.go /usr/local/.ghcu/tmp/gh-aw-test-runs/20260309-225132-15892/test-326203262 64/pkg/tool/linurev-parse --no�� --noprofile .cfg 64/pkg/tool/linux_amd64/vet udit&#34; ow_execution.go 0/x64/bin/grep 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 grep 64/pkg/tool/linux_amd64/vet udit&#34; ge_test.go 64/bin/grep 64/pkg/tool/linux_amd64/vet --no�� --noprofile .cfg 64/pkg/tool/linux_amd64/vet udit&#34; ow_execution.go de/node/bin/grep--show-toplevel 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 grep 64/pkg/tool/linux_amd64/vet udit&#34; ge_test.go 0/x64/bin/grep 64/pkg/tool/linux_amd64/vet --no�� --noprofile .cfg Argument udit&#34; ow_execution.go bin/grep 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE 51RFpkM/58sERvdotCvyK1taGOl6 env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 grep x_amd64/compile udit&#34; ge_test.go de/node/bin/grep--git-dir x_amd64/compile --no�� --noprofile .cfg 64/pkg/tool/linux_amd64/vet udit&#34; ow_execution.go ache/go/1.25.0/x64/bin/grep 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path d -n 10 /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/trial_repository.go 64/bin/bash udit&#34; .go bin/grep grep -l Use:.*&#34;run&#34;\|Use-s /deps.go x_amd64/vet udit&#34; ge.go ache/node/24.14.--noprofile x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path &#34;prettier&#34; --wriGOINSECURE sh 64/bin/go &#34;prettier&#34; --chesh GOPROXY 64/bin/go sh -c npx prettier --wGOSUMDB /bin/sh 64/bin/go GOPATH=$(go env node node 64/bin/go go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha --noprofile grep x_amd64/vet udit&#34; st.go ache/node/24.14.--noprofile x_amd64/vet --no�� --noprofile grep x_amd64/vet udit&#34; _test.go /home/REDACTED/.lo/tmp/gh-aw-test-runs/20260309-225132-15892/test-3504948260/.github/workflows x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha prettier --write 64/bin/go !../../../pkg/wocp --ignore-path ../../../.prettiactions/setup-cli/install.sh go /pre�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha Use:.*&#34;init&#34;\|Us./pkg/cli/ /home/REDACTED/work/gh-aw/gh-aw/pk-j x_amd64/vet /home/REDACTED/worbash /home/REDACTED/wor--norc /home/REDACTED/wor--noprofile x_amd64/vet --no�� --noprofile /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/add_command.go x_amd64/vet /home/REDACTED/worgit /home/REDACTED/wor-C /home/REDACTED/wor/tmp/gh-aw-test-runs/20260309-225132-15892/test-3504948260/.github/workflows x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --noprofile grep x_amd64/vet udit&#34; o nfig/composer/ve--noprofile x_amd64/vet --no�� --noprofile grep x_amd64/vet udit&#34; atting_test.go n-dir/grep x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha --noprofile grep x_amd64/vet udit&#34; o n-dir/grep x_amd64/vet --no�� --noprofile grep x_amd64/vet udit&#34; atting_test.go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha --noprofile grep x_amd64/vet udit&#34; o ep x_amd64/vet --no�� --noprofile grep x_amd64/vet udit&#34; atting_test.go nfig/composer/ve/tmp/gh-aw-test-runs/20260309-225132-15892/test-3504948260/.github/workflows x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha prettier --write 64/bin/go !../../../pkg/wo/bin/sh --ignore-path ../../../.prettigo build -ldflags &#34;-s -w -X main.version=7199a4a-dirty&#34; -o gh-aw ./cmd/gh-aw go /pre�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion udit&#34; mand_test.go ndor/bin/grep 64/pkg/tool/linuTest User k/gh�� --noprofile .cfg 64/pkg/tool/linux_amd64/vet udit&#34; sign_to_agent_terev-parse ep 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE n-dir/sh GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo /home/REDACTED/go/bin/bash udit&#34; est.go /home/REDACTED/.lo--noprofile bash --no�� to pkg/workflow/data/action_pins.json...&#34; grep x_amd64/vet udit&#34; ge.go ep x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo g/cli/add_command_test.go g/cli/add_currenbash g/cli/add_descri--norc g/cli/add_gitatt--noprofile g/cli/add_integration_test.go g/cl�� g/cli/add_interactive_engine.go g/cli/add_interactive_git.go x_amd64/vet udit&#34; ge.go nfig/composer/vendor/bin/grep x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh workflow list --repo owner/repo --json name,path,state 64/bin/go GOINSECURE GOMOD GOMODCACHE go env ck &#39;**/*.cjs&#39; &#39;*GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build1785855504/b001/cli.test /tmp/go-build1785855504/b001/cli.test -test.testlogfile=/tmp/go-build1785855504/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s tter�� tter_hash_test.go tter_hash_test_main_test.go n-dir/bash udit&#34; servation_test.g-atomic rep grep -l Use:.*&#34;run&#34;\|Use-errorsas /home/REDACTED/wor-ifaceassert x_amd64/vet udit&#34; ctive_git.go 64/bin/grep x_amd64/vet (http block)
    • Triggering command: /tmp/go-build1488363571/b383/cli.test /tmp/go-build1488363571/b383/cli.test -test.testlogfile=/tmp/go-build1488363571/b383/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true ath /dev/null GOPROXY ild/node_modules-json sh -c &#34;prettier&#34; --wriGOINSECURE sh 64/bin/go tierignore node 64/bin/go node (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name d -n 10 /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/trial_repository.go ache/uv/0.10.9/x86_64/bash udit&#34; .go de/node/bin/grep-bool grep -l Use:.*&#34;run&#34;\|Use-errorsas /home/REDACTED/wor-ifaceassert x_amd64/vet udit&#34; .go bin/grep x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name prettier --write 64/bin/go **/*.ts **/*.json --ignore-path node /opt�� run format:pkg-json 64/bin/go --check scripts/**/*.js /node go (http block)

If you need me to access, download, or install something from one of these locations, you can either:


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

@villarrealcecilia2024-png
Copy link

…new, --dir to list

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CLI consistency issues and missing flags Add missing flags to run, audit, new, and list commands for CLI consistency Mar 9, 2026
@pelikhan pelikhan marked this pull request as ready for review March 10, 2026 01:19
Copilot AI review requested due to automatic review settings March 10, 2026 01:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves CLI consistency by adding missing flags to several commands (run, audit, new, list) and wiring them through to the underlying implementation.

Changes:

  • run: add --json/-j to emit a JSON summary of workflow triggers.
  • audit: add --repo/-r to support auditing bare numeric run IDs for a specified repo.
  • new / list: add --engine/-e for template frontmatter injection and --dir/-d for local workflow directory overrides (and fix local path handling).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/cli/run_workflow_execution.go Adds RunOptions.JSON and JSON summary emission for run.
pkg/cli/list_workflows_command.go Adds --dir flag and ensures local listing respects the provided path.
pkg/cli/commands_test.go Updates NewWorkflow test to match new function signature.
pkg/cli/commands.go Extends NewWorkflow/template generator to optionally inject engine: frontmatter.
pkg/cli/audit.go Adds --repo handling to apply owner/repo when auditing by numeric run ID.
cmd/gh-aw/main.go Wires new flags into the Cobra commands (new --engine, run --json).
Comments suppressed due to low confidence (3)

pkg/cli/run_workflow_execution.go:617

  • When opts.JSON is enabled, ExecuteWithRepeat will print its start/repeat informational messages to stdout because UseStderr is set to false. If a user combines --json with --repeat, those messages will corrupt the JSON output stream. Consider forcing repeat messages to stderr when JSON output is requested (or disallowing --json+--repeat).

This issue also appears in the following locations of the same file:

  • line 571
  • line 571
	// Execute workflows with optional repeat functionality
	return ExecuteWithRepeat(RepeatOptions{
		RepeatCount:   opts.RepeatCount,
		RepeatMessage: "Repeating workflow run",
		ExecuteFunc:   runAllWorkflows,
		UseStderr:     false, // Use stdout for run command
	})

pkg/cli/run_workflow_execution.go:608

  • The --json wrapper currently builds a pre-filled results array that never populates RunID / RunURL, and if any workflow fails it marks all entries as status=error even though earlier workflows may have successfully triggered. To make the JSON output accurate and match the documented intent, collect results during the per-workflow execution (capturing per-workflow errors and any run URL/ID you already parse in RunWorkflowOnGitHub).
	// When JSON output is requested, wrap runAllWorkflows to emit a JSON summary
	if opts.JSON {
		runAllWorkflowsInner := runAllWorkflows
		runAllWorkflows = func() error {
			// Build per-workflow results
			var results []WorkflowRunResult
			for _, workflowName := range workflowNames {
				normalizedID := normalizeWorkflowID(workflowName)
				lockFileName := normalizedID + ".lock.yml"
				status := "triggered"
				if opts.DryRun {
					status = "dry_run"
				}
				results = append(results, WorkflowRunResult{
					Workflow: normalizedID,
					LockFile: lockFileName,
					Status:   status,
				})
			}

			// Execute the actual runs (text output still goes to stderr)
			runErr := runAllWorkflowsInner()
			if runErr != nil {
				// Mark all as error when we can't distinguish which failed
				for i := range results {
					results[i].Status = "error"
					results[i].Error = runErr.Error()
				}
			}

			// Output JSON to stdout
			jsonBytes, err := json.MarshalIndent(results, "", "  ")
			if err != nil {
				return fmt.Errorf("failed to marshal JSON: %w", err)
			}
			fmt.Println(string(jsonBytes))
			return runErr
		}

pkg/cli/run_workflow_execution.go:609

  • New opts.JSON behavior in RunWorkflowsOnGitHub (wrapping execution and emitting JSON to stdout) doesn't appear to have test coverage. Since this file already has unit tests for other run behaviors, it would be good to add tests that assert the stdout JSON is valid (and that stderr messaging doesn’t leak into stdout), especially for multi-workflow and error cases.
	// When JSON output is requested, wrap runAllWorkflows to emit a JSON summary
	if opts.JSON {
		runAllWorkflowsInner := runAllWorkflows
		runAllWorkflows = func() error {
			// Build per-workflow results
			var results []WorkflowRunResult
			for _, workflowName := range workflowNames {
				normalizedID := normalizeWorkflowID(workflowName)
				lockFileName := normalizedID + ".lock.yml"
				status := "triggered"
				if opts.DryRun {
					status = "dry_run"
				}
				results = append(results, WorkflowRunResult{
					Workflow: normalizedID,
					LockFile: lockFileName,
					Status:   status,
				})
			}

			// Execute the actual runs (text output still goes to stderr)
			runErr := runAllWorkflowsInner()
			if runErr != nil {
				// Mark all as error when we can't distinguish which failed
				for i := range results {
					results[i].Status = "error"
					results[i].Error = runErr.Error()
				}
			}

			// Output JSON to stdout
			jsonBytes, err := json.MarshalIndent(results, "", "  ")
			if err != nil {
				return fmt.Errorf("failed to marshal JSON: %w", err)
			}
			fmt.Println(string(jsonBytes))
			return runErr
		}
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +82 to +89
if repoFlag != "" && components.Owner == "" {
parts := strings.SplitN(repoFlag, "/", 2)
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return fmt.Errorf("invalid repository format '%s': expected 'owner/repo'", repoFlag)
}
components.Owner = parts[0]
components.Repo = parts[1]
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

--repo parsing uses strings.SplitN(repoFlag, "/", 2), which will silently mis-handle values containing more than one / (e.g., host/owner/repo becomes owner=host, repo=owner/repo). Since the flag is meant to be owner/repo here, validate using an exact 2-part split (or a shared slug parser) so invalid inputs error instead of producing incorrect owner/repo values.

Copilot uses AI. Check for mistakes.
Comment on lines 74 to 76
cmd.Flags().String("path", ".github/workflows", "Path to workflows directory in the repository")
cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")

Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The --dir flag help says (default: .github/workflows), but the flag default is actually an empty string and the default behavior comes from --path. Consider updating the description to clarify that --dir is an override for local listing when --repo is not set (and that the default local directory is still .github/workflows).

Copilot uses AI. Check for mistakes.
@pelikhan pelikhan merged commit 05caaea into main Mar 10, 2026
137 checks passed
@pelikhan pelikhan deleted the copilot/fix-cli-consistency-issues branch March 10, 2026 01:36
github-actions bot added a commit that referenced this pull request Mar 10, 2026
Document new CLI flags added in #20272 (run --json, audit --repo, new
--engine, list --dir) and the report-failure-as-issue safe-outputs option
from #20266.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cli-consistency] CLI Consistency Issues and Missing Flags

4 participants