From 207d548fe100f6356b02abddfe61cbd0b1e6ea8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 06:49:55 +0000 Subject: [PATCH 1/3] Initial plan From 9a3a5879c1925da2fd374ab2e2cfe784979e5b95 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:04:19 +0000 Subject: [PATCH 2/3] fix: run shared APM restore as pre-agent steps in PR context Agent-Logs-Url: https://github.com/github/gh-aw/sessions/996372ce-f6b2-4c3b-b9b0-aa2ad0ecf200 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/shared/apm.md | 8 +-- .github/workflows/smoke-claude.lock.yml | 26 +++---- pkg/workflow/compiler_pre_agent_steps_test.go | 68 +++++++++++++++++++ 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/.github/workflows/shared/apm.md b/.github/workflows/shared/apm.md index b505ce5ab17..35cc64097e2 100644 --- a/.github/workflows/shared/apm.md +++ b/.github/workflows/shared/apm.md @@ -4,7 +4,7 @@ # # This shared workflow creates a dedicated "apm" job (depending on activation) that # packs packages using microsoft/apm-action and uploads the bundle as an artifact. -# The agent job then downloads and unpacks the bundle as pre-steps. +# The agent job then downloads and unpacks the bundle as pre-agent-steps. # # Documentation: https://github.com/microsoft/APM # @@ -64,7 +64,7 @@ jobs: path: ${{ steps.apm_pack.outputs.bundle-path }} retention-days: '1' -steps: +pre-agent-steps: - name: Download APM bundle artifact uses: actions/download-artifact@v8.0.1 with: @@ -83,13 +83,13 @@ steps: ## APM Packages These packages are installed via a dedicated "apm" job that packs and uploads a bundle, -which the agent job then downloads and unpacks as pre-steps. +which the agent job then downloads and unpacks as pre-agent-steps. ### How it works 1. **Pack** (`apm` job): `microsoft/apm-action` installs packages and creates a bundle archive, uploaded as a GitHub Actions artifact. -2. **Unpack** (agent job pre-steps): the bundle is downloaded and unpacked via +2. **Unpack** (agent job pre-agent-steps): the bundle is downloaded and unpacked via `microsoft/apm-action` in restore mode, making all skills and tools available to the AI agent. ### Package format diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 6b9defa6dd8..431f9acfe05 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -870,19 +870,6 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" env: GH_TOKEN: ${{ github.token }} - - name: Download APM bundle artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: ${{ needs.activation.outputs.artifact_prefix }}apm - path: /tmp/gh-aw/apm-bundle - - id: apm_bundle - name: Find APM bundle path - run: echo "path=$(find /tmp/gh-aw/apm-bundle -name '*.tar.gz' | head -1)" >> "$GITHUB_OUTPUT" - - name: Restore APM packages - uses: microsoft/apm-action@a190b0b1a91031057144dc136acf9757a59c9e4d # v1.4.1 - with: - bundle: ${{ steps.apm_bundle.outputs.path }} - # Cache memory file share configuration from frontmatter processed below - name: Create cache-memory directory run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh" @@ -2173,6 +2160,19 @@ jobs: - name: Clean git credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Download APM bundle artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ needs.activation.outputs.artifact_prefix }}apm + path: /tmp/gh-aw/apm-bundle + - id: apm_bundle + name: Find APM bundle path + run: echo "path=$(find /tmp/gh-aw/apm-bundle -name '*.tar.gz' | head -1)" >> "$GITHUB_OUTPUT" + - name: Restore APM packages + uses: microsoft/apm-action@a190b0b1a91031057144dc136acf9757a59c9e4d # v1.4.1 + with: + bundle: ${{ steps.apm_bundle.outputs.path }} + - name: Execute Claude Code CLI id: agentic_execution # Allowed tools (sorted): diff --git a/pkg/workflow/compiler_pre_agent_steps_test.go b/pkg/workflow/compiler_pre_agent_steps_test.go index b571f8249d8..2cd126053a7 100644 --- a/pkg/workflow/compiler_pre_agent_steps_test.go +++ b/pkg/workflow/compiler_pre_agent_steps_test.go @@ -124,3 +124,71 @@ Main workflow. t.Errorf("Main pre-agent-step (%d) should appear before AI execution step (%d)", mainIdx, aiStepIdx) } } + +func TestImportedPreAgentStepRunsAfterPRBaseRestore(t *testing.T) { + tmpDir := testutil.TempDir(t, "pre-agent-steps-pr-restore-test") + + sharedDir := filepath.Join(tmpDir, "shared") + if err := os.MkdirAll(sharedDir, 0755); err != nil { + t.Fatal(err) + } + + sharedContent := `--- +pre-agent-steps: + - name: Restore APM packages + run: echo "restore apm" +--- + +Shared APM-style steps. +` + sharedFile := filepath.Join(sharedDir, "apm.md") + if err := os.WriteFile(sharedFile, []byte(sharedContent), 0644); err != nil { + t.Fatal(err) + } + + mainContent := `--- +on: + pull_request: + types: [opened] +permissions: + contents: read + issues: read + pull-requests: read +imports: + - ./shared/apm.md +engine: claude +strict: false +--- + +Main workflow. +` + mainFile := filepath.Join(tmpDir, "main.md") + if err := os.WriteFile(mainFile, []byte(mainContent), 0644); err != nil { + t.Fatal(err) + } + + compiler := NewCompiler() + if err := compiler.CompileWorkflow(mainFile); err != nil { + t.Fatalf("Unexpected error compiling workflow with imported pre-agent-steps in PR context: %v", err) + } + + lockFile := filepath.Join(tmpDir, "main.lock.yml") + content, err := os.ReadFile(lockFile) + if err != nil { + t.Fatalf("Failed to read generated lock file: %v", err) + } + lockContent := string(content) + + restoreBaseIdx := indexInNonCommentLines(lockContent, "- name: Restore agent config folders from base branch") + restoreAPMIdx := indexInNonCommentLines(lockContent, "- name: Restore APM packages") + aiStepIdx := indexInNonCommentLines(lockContent, "- name: Execute Claude Code CLI") + if restoreBaseIdx == -1 || restoreAPMIdx == -1 || aiStepIdx == -1 { + t.Fatal("Could not find expected PR restore, pre-agent, and AI steps in generated workflow") + } + if restoreBaseIdx >= restoreAPMIdx { + t.Errorf("PR base restore step (%d) should appear before imported pre-agent step (%d)", restoreBaseIdx, restoreAPMIdx) + } + if restoreAPMIdx >= aiStepIdx { + t.Errorf("Imported pre-agent step (%d) should appear before AI execution step (%d)", restoreAPMIdx, aiStepIdx) + } +} From 6da38095d8622599778022822dd98b8535c2c88f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:10:50 +0000 Subject: [PATCH 3/3] test: clarify pre-agent restore ordering test name Agent-Logs-Url: https://github.com/github/gh-aw/sessions/996372ce-f6b2-4c3b-b9b0-aa2ad0ecf200 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/compiler_pre_agent_steps_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/workflow/compiler_pre_agent_steps_test.go b/pkg/workflow/compiler_pre_agent_steps_test.go index 2cd126053a7..b8bb38789bf 100644 --- a/pkg/workflow/compiler_pre_agent_steps_test.go +++ b/pkg/workflow/compiler_pre_agent_steps_test.go @@ -125,7 +125,7 @@ Main workflow. } } -func TestImportedPreAgentStepRunsAfterPRBaseRestore(t *testing.T) { +func TestImportedPreAgentStepsRunAfterPRBaseRestore(t *testing.T) { tmpDir := testutil.TempDir(t, "pre-agent-steps-pr-restore-test") sharedDir := filepath.Join(tmpDir, "shared")