From 7130a7d0fc85572d6cc13d0ede7abc4354390f72 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:38:44 +0000 Subject: [PATCH 1/3] chore: outline plan for --actions-repo flag Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/7527c09a-4314-4fb2-b7cb-7880d6142096 --- .github/aw/actions-lock.json | 5 +++++ .github/workflows/smoke-claude.lock.yml | 4 ++-- pkg/workflow/data/action_pins.json | 11 +++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index b9e919b7cd5..81223426c5b 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -148,6 +148,11 @@ "version": "v4.34.1", "sha": "cb06a0a8527b2c6970741b3a0baa15231dc74a4c" }, + "github/gh-aw-actions/setup@v0": { + "repo": "github/gh-aw-actions/setup", + "version": "v0", + "sha": "50f4fc16883c6c6672d8879affa8fd15d5cc79a4" + }, "github/gh-aw-actions/setup@v0.62.5": { "repo": "github/gh-aw-actions/setup", "version": "v0.62.5", diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index b3380d0afd7..ff7ca62aae6 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -650,7 +650,7 @@ jobs: run: bash ${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh - name: Install and pack APM dependencies id: apm_pack - uses: microsoft/apm-action@83d54a6c7941049210433b16c8dfac573665b12a # v1.3.4 + uses: microsoft/apm-action@cc84c04bc73e19e35527f1efa34ea003be9f037f # v1.4.0 env: GITHUB_TOKEN: ${{ secrets.GH_AW_PLUGINS_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} with: @@ -819,7 +819,7 @@ jobs: name: apm path: /tmp/gh-aw/apm-bundle - name: Restore APM dependencies - uses: microsoft/apm-action@83d54a6c7941049210433b16c8dfac573665b12a # v1.3.4 + uses: microsoft/apm-action@cc84c04bc73e19e35527f1efa34ea003be9f037f # v1.4.0 with: bundle: /tmp/gh-aw/apm-bundle/*.tar.gz apm-version: ${{ env.GH_AW_INFO_APM_VERSION }} diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index 9056a621b72..b9e919b7cd5 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -148,11 +148,6 @@ "version": "v4.34.1", "sha": "cb06a0a8527b2c6970741b3a0baa15231dc74a4c" }, - "github/gh-aw-actions/setup@v0": { - "repo": "github/gh-aw-actions/setup", - "version": "v0", - "sha": "50f4fc16883c6c6672d8879affa8fd15d5cc79a4" - }, "github/gh-aw-actions/setup@v0.62.5": { "repo": "github/gh-aw-actions/setup", "version": "v0.62.5", @@ -168,10 +163,10 @@ "version": "v2.10.3", "sha": "9cd1b7bf3f36d5a3c3b17abc3545bfb5481912ea" }, - "microsoft/apm-action@v1.3.4": { + "microsoft/apm-action@v1.4.0": { "repo": "microsoft/apm-action", - "version": "v1.3.4", - "sha": "83d54a6c7941049210433b16c8dfac573665b12a" + "version": "v1.4.0", + "sha": "cc84c04bc73e19e35527f1efa34ea003be9f037f" }, "oven-sh/setup-bun@v2.2.0": { "repo": "oven-sh/setup-bun", From cf38b01985c533713b3548a84bbc470419895ff0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:47:03 +0000 Subject: [PATCH 2/3] feat(compile): add --actions-repo flag to override external actions repository Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/7527c09a-4314-4fb2-b7cb-7880d6142096 --- cmd/gh-aw/main.go | 3 +++ pkg/cli/compile_compiler_setup.go | 6 ++++++ pkg/cli/compile_config.go | 1 + pkg/workflow/action_reference.go | 25 ++++++++++++++++++------- pkg/workflow/compiler_types.go | 21 +++++++++++++++++++++ pkg/workflow/data/action_pins.json | 5 +++++ 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/cmd/gh-aw/main.go b/cmd/gh-aw/main.go index 579a83d0ab9..7c392de0fa6 100644 --- a/cmd/gh-aw/main.go +++ b/cmd/gh-aw/main.go @@ -259,6 +259,7 @@ Examples: engineOverride, _ := cmd.Flags().GetString("engine") actionMode, _ := cmd.Flags().GetString("action-mode") actionTag, _ := cmd.Flags().GetString("action-tag") + actionsRepo, _ := cmd.Flags().GetString("actions-repo") validate, _ := cmd.Flags().GetBool("validate") watch, _ := cmd.Flags().GetBool("watch") dir, _ := cmd.Flags().GetString("dir") @@ -312,6 +313,7 @@ Examples: EngineOverride: engineOverride, ActionMode: actionMode, ActionTag: actionTag, + ActionsRepo: actionsRepo, Validate: validate, Watch: watch, WorkflowDir: workflowDir, @@ -646,6 +648,7 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)") compileCmd.Flags().String("action-mode", "", "Action script inlining mode (inline, dev, release). Auto-detected if not specified") compileCmd.Flags().String("action-tag", "", "Override action SHA or tag for actions/setup (overrides action-mode to release). Accepts full SHA or tag name") + compileCmd.Flags().String("actions-repo", "", "Override the external actions repository used in action mode (default: github/gh-aw-actions). Example: --actions-repo myorg/my-aw-actions") compileCmd.Flags().Bool("validate", false, "Enable GitHub Actions workflow schema validation, container image validation, and action SHA validation") compileCmd.Flags().BoolP("watch", "w", false, "Watch for changes to workflow files and recompile automatically") compileCmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)") diff --git a/pkg/cli/compile_compiler_setup.go b/pkg/cli/compile_compiler_setup.go index 65da0399aa6..a9c1c5b93df 100644 --- a/pkg/cli/compile_compiler_setup.go +++ b/pkg/cli/compile_compiler_setup.go @@ -104,6 +104,12 @@ func createAndConfigureCompiler(config CompileConfig) *workflow.Compiler { // Set up action mode setupActionMode(compiler, config.ActionMode, config.ActionTag) + // Set up actions repository override if specified + if config.ActionsRepo != "" { + compiler.SetActionsRepo(config.ActionsRepo) + compileCompilerSetupLog.Printf("Actions repository overridden: %s (default: %s)", config.ActionsRepo, workflow.GitHubActionsOrgRepo) + } + // Set up repository context setupRepositoryContext(compiler) diff --git a/pkg/cli/compile_config.go b/pkg/cli/compile_config.go index 15888ae4283..a59382b81a5 100644 --- a/pkg/cli/compile_config.go +++ b/pkg/cli/compile_config.go @@ -32,6 +32,7 @@ type CompileConfig struct { JSONOutput bool // Output validation results as JSON ActionMode string // Action script inlining mode: inline, dev, or release ActionTag string // Override action SHA or tag for actions/setup (overrides action-mode to release) + ActionsRepo string // Override the external actions repository (default: github/gh-aw-actions) Stats bool // Display statistics table sorted by file size FailFast bool // Stop at first error instead of collecting all errors } diff --git a/pkg/workflow/action_reference.go b/pkg/workflow/action_reference.go index 74a13bd55bb..b6ad9b5bb18 100644 --- a/pkg/workflow/action_reference.go +++ b/pkg/workflow/action_reference.go @@ -35,6 +35,17 @@ const ( // - For action mode without resolver: "github/gh-aw-actions/setup@" (tag-based, SHA resolved later) // - Falls back to local path if version is invalid in release/action mode func ResolveSetupActionReference(actionMode ActionMode, version string, actionTag string, resolver ActionSHAResolver) string { + return resolveSetupActionRef(actionMode, version, actionTag, resolver, "") +} + +// resolveSetupActionRef is the internal implementation of ResolveSetupActionReference +// that accepts an optional actionsOrgRepo override. When actionsOrgRepo is empty, +// GitHubActionsOrgRepo is used. +func resolveSetupActionRef(actionMode ActionMode, version string, actionTag string, resolver ActionSHAResolver, actionsOrgRepo string) string { + if actionsOrgRepo == "" { + actionsOrgRepo = GitHubActionsOrgRepo + } + localPath := "./actions/setup" // Dev mode - return local path @@ -57,8 +68,8 @@ func ResolveSetupActionReference(actionMode ActionMode, version string, actionTa return localPath } - // Construct the remote reference: github/gh-aw-actions/setup@tag - actionRepo := GitHubActionsOrgRepo + "/setup" + // Construct the remote reference: /setup@tag + actionRepo := actionsOrgRepo + "/setup" remoteRef := fmt.Sprintf("%s@%s", actionRepo, tag) // If a resolver is available, try to resolve the SHA @@ -152,13 +163,13 @@ func (c *Compiler) resolveActionReference(localActionPath string, data *Workflow resolver = data.ActionResolver } if c.actionTag != "" { - return ResolveSetupActionReference(c.actionMode, c.version, c.actionTag, resolver) + return resolveSetupActionRef(c.actionMode, c.version, c.actionTag, resolver, c.effectiveActionsRepo()) } if !hasActionTag { - return ResolveSetupActionReference(c.actionMode, c.version, "", resolver) + return resolveSetupActionRef(c.actionMode, c.version, "", resolver, c.effectiveActionsRepo()) } // hasActionTag is true and no compiler actionTag: use action mode with the frontmatter tag - return ResolveSetupActionReference(ActionModeAction, c.version, frontmatterActionTag, resolver) + return resolveSetupActionRef(ActionModeAction, c.version, frontmatterActionTag, resolver, c.effectiveActionsRepo()) } // Action mode - use external gh-aw-actions repository @@ -292,8 +303,8 @@ func (c *Compiler) convertToExternalActionsRef(localPath string, data *WorkflowD } } - // Construct the external actions reference: github/gh-aw-actions/action-name@tag - actionRepo := fmt.Sprintf("%s/%s", GitHubActionsOrgRepo, actionName) + // Construct the external actions reference: /action-name@tag + actionRepo := fmt.Sprintf("%s/%s", c.effectiveActionsRepo(), actionName) remoteRef := fmt.Sprintf("%s@%s", actionRepo, tag) // Try to resolve the SHA using action pins diff --git a/pkg/workflow/compiler_types.go b/pkg/workflow/compiler_types.go index 7c78ee095fc..b9388f18888 100644 --- a/pkg/workflow/compiler_types.go +++ b/pkg/workflow/compiler_types.go @@ -81,6 +81,7 @@ type Compiler struct { markdownPath string // Path to the markdown file being compiled (for context in dynamic tool generation) actionMode ActionMode // Mode for generating JavaScript steps (inline vs custom actions) actionTag string // Override action SHA or tag for actions/setup (when set, overrides actionMode to release) + actionsRepo string // Override the external actions repository (default: github/gh-aw-actions) jobManager *JobManager // Manages jobs and dependencies engineRegistry *EngineRegistry // Registry of available agentic engines engineCatalog *EngineCatalog // Catalog of engine definitions backed by the registry @@ -216,6 +217,26 @@ func (c *Compiler) GetActionTag() string { return c.actionTag } +// SetActionsRepo sets the external actions repository override. +// When set, this overrides the default "github/gh-aw-actions" repository used in action mode. +func (c *Compiler) SetActionsRepo(repo string) { + c.actionsRepo = repo +} + +// GetActionsRepo returns the external actions repository override (empty if not set) +func (c *Compiler) GetActionsRepo() string { + return c.actionsRepo +} + +// effectiveActionsRepo returns the actions repository to use for action mode references. +// Returns the override if set, otherwise returns the default GitHubActionsOrgRepo constant. +func (c *Compiler) effectiveActionsRepo() string { + if c.actionsRepo != "" { + return c.actionsRepo + } + return GitHubActionsOrgRepo +} + // GetVersion returns the version string used by the compiler func (c *Compiler) GetVersion() string { return c.version diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index b9e919b7cd5..81223426c5b 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -148,6 +148,11 @@ "version": "v4.34.1", "sha": "cb06a0a8527b2c6970741b3a0baa15231dc74a4c" }, + "github/gh-aw-actions/setup@v0": { + "repo": "github/gh-aw-actions/setup", + "version": "v0", + "sha": "50f4fc16883c6c6672d8879affa8fd15d5cc79a4" + }, "github/gh-aw-actions/setup@v0.62.5": { "repo": "github/gh-aw-actions/setup", "version": "v0.62.5", From 99e168a38cffdce716a112c9bfafc5651ce33e4a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:14:29 +0000 Subject: [PATCH 3/3] test(compile): add integration tests for --actions-repo flag Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/1e3c241a-3103-4eeb-a668-afdb683e4c59 --- pkg/cli/compile_compiler_setup.go | 17 +++-- pkg/cli/compile_integration_test.go | 93 ++++++++++++++++++++++++++ pkg/cli/workflows/test-actions-repo.md | 16 +++++ 3 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 pkg/cli/workflows/test-actions-repo.md diff --git a/pkg/cli/compile_compiler_setup.go b/pkg/cli/compile_compiler_setup.go index a9c1c5b93df..3a18ae5f64f 100644 --- a/pkg/cli/compile_compiler_setup.go +++ b/pkg/cli/compile_compiler_setup.go @@ -159,12 +159,21 @@ func configureCompilerFlags(compiler *workflow.Compiler, config CompileConfig) { func setupActionMode(compiler *workflow.Compiler, actionMode string, actionTag string) { compileCompilerSetupLog.Printf("Setting up action mode: %s, actionTag: %s", actionMode, actionTag) - // If actionTag is specified, override to release mode + // If actionTag is specified, it pins the version used in action/release references. + // When --action-mode action is explicitly set alongside --action-tag, honour the explicit + // action mode so that the external actions repo (--actions-repo) is also respected. + // Without an explicit action mode, --action-tag still defaults to release mode (original behaviour). if actionTag != "" { - compileCompilerSetupLog.Printf("--action-tag specified (%s), overriding to release mode", actionTag) - compiler.SetActionMode(workflow.ActionModeRelease) compiler.SetActionTag(actionTag) - compileCompilerSetupLog.Printf("Action mode set to: release with tag/SHA: %s", actionTag) + if actionMode == string(workflow.ActionModeAction) { + compileCompilerSetupLog.Printf("--action-tag specified (%s) with --action-mode action, using action mode", actionTag) + compiler.SetActionMode(workflow.ActionModeAction) + compileCompilerSetupLog.Printf("Action mode set to: action with tag/SHA: %s", actionTag) + } else { + compileCompilerSetupLog.Printf("--action-tag specified (%s), overriding to release mode", actionTag) + compiler.SetActionMode(workflow.ActionModeRelease) + compileCompilerSetupLog.Printf("Action mode set to: release with tag/SHA: %s", actionTag) + } return } diff --git a/pkg/cli/compile_integration_test.go b/pkg/cli/compile_integration_test.go index 43e6738edda..8b4b891afba 100644 --- a/pkg/cli/compile_integration_test.go +++ b/pkg/cli/compile_integration_test.go @@ -1980,3 +1980,96 @@ Call notify_dynamic to send notifications. t.Errorf("Lock file should preserve the GitHub Actions expression in allowed_repositories\nLock file content:\n%s", lockContentStr) } } + +// TestCompileWithActionsRepoFlag verifies that the --actions-repo flag causes the +// custom repository to be used in action mode instead of the default github/gh-aw-actions. +func TestCompileWithActionsRepoFlag(t *testing.T) { + setup := setupIntegrationTest(t) + defer setup.cleanup() + + // Use the canonical test workflow fixture + srcPath := filepath.Join(projectRoot, "pkg/cli/workflows/test-actions-repo.md") + dstPath := filepath.Join(setup.workflowsDir, "test-actions-repo.md") + + srcContent, err := os.ReadFile(srcPath) + if err != nil { + t.Fatalf("Failed to read source workflow file %s: %v", srcPath, err) + } + if err := os.WriteFile(dstPath, srcContent, 0644); err != nil { + t.Fatalf("Failed to write workflow to test dir: %v", err) + } + + cmd := exec.Command(setup.binaryPath, "compile", + "--action-mode", "action", + "--actions-repo", "myorg/custom-aw-actions", + "--action-tag", "v9.9.9", + dstPath, + ) + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("CLI compile command failed: %v\nOutput: %s", err, string(output)) + } + + lockFilePath := filepath.Join(setup.workflowsDir, "test-actions-repo.lock.yml") + lockContent, err := os.ReadFile(lockFilePath) + if err != nil { + t.Fatalf("Failed to read lock file: %v", err) + } + lockContentStr := string(lockContent) + + // The custom repo should appear in the lock file + if !strings.Contains(lockContentStr, "myorg/custom-aw-actions") { + t.Errorf("Lock file should contain the custom actions repo 'myorg/custom-aw-actions'\nLock file content:\n%s", lockContentStr) + } + + // The default repo should NOT appear + if strings.Contains(lockContentStr, "github/gh-aw-actions") { + t.Errorf("Lock file should NOT contain the default 'github/gh-aw-actions' when overridden\nLock file content:\n%s", lockContentStr) + } + + t.Logf("Actions repo flag test passed - custom repo baked into lock file: %s", lockFilePath) +} + +// TestCompileWithActionsRepoDefaultFallback verifies that without --actions-repo, the default +// github/gh-aw-actions repository is used in the lock file when action mode is set. +func TestCompileWithActionsRepoDefaultFallback(t *testing.T) { + setup := setupIntegrationTest(t) + defer setup.cleanup() + + // Use the canonical test workflow fixture + srcPath := filepath.Join(projectRoot, "pkg/cli/workflows/test-actions-repo.md") + dstPath := filepath.Join(setup.workflowsDir, "test-actions-repo.md") + + srcContent, err := os.ReadFile(srcPath) + if err != nil { + t.Fatalf("Failed to read source workflow file %s: %v", srcPath, err) + } + if err := os.WriteFile(dstPath, srcContent, 0644); err != nil { + t.Fatalf("Failed to write workflow to test dir: %v", err) + } + + // No --actions-repo flag; action mode with a tag + cmd := exec.Command(setup.binaryPath, "compile", + "--action-mode", "action", + "--action-tag", "v9.9.9", + dstPath, + ) + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("CLI compile command failed: %v\nOutput: %s", err, string(output)) + } + + lockFilePath := filepath.Join(setup.workflowsDir, "test-actions-repo.lock.yml") + lockContent, err := os.ReadFile(lockFilePath) + if err != nil { + t.Fatalf("Failed to read lock file: %v", err) + } + lockContentStr := string(lockContent) + + // Default repo should appear in the lock file + if !strings.Contains(lockContentStr, "github/gh-aw-actions") { + t.Errorf("Lock file should contain the default 'github/gh-aw-actions' when no override is specified\nLock file content:\n%s", lockContentStr) + } + + t.Logf("Default actions repo test passed - default repo baked into lock file: %s", lockFilePath) +} diff --git a/pkg/cli/workflows/test-actions-repo.md b/pkg/cli/workflows/test-actions-repo.md new file mode 100644 index 00000000000..327f22f0350 --- /dev/null +++ b/pkg/cli/workflows/test-actions-repo.md @@ -0,0 +1,16 @@ +--- +name: Test Actions Repo Override +on: + workflow_dispatch: +permissions: + contents: read + issues: read +engine: copilot +safe-outputs: + create-issue: + max: 1 +--- + +# Test Actions Repo Override + +When instructed, create an issue summarizing the repository state.