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
8 changes: 4 additions & 4 deletions .github/workflows/shared/apm.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines 5 to +7
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

The header comment says the agent job unpacks the bundle as pre-agent-steps, but this PR changes the restore to run as pre-agent-steps. Please update this comment to avoid confusion about which phase runs the APM restore steps.

This issue also appears on line 85 of the same file.

Copilot uses AI. Check for mistakes.
#
# Documentation: https://github.com/microsoft/APM
#
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/smoke-claude.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions pkg/workflow/compiler_pre_agent_steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,71 @@ Main workflow.
t.Errorf("Main pre-agent-step (%d) should appear before AI execution step (%d)", mainIdx, aiStepIdx)
}
}

func TestImportedPreAgentStepsRunAfterPRBaseRestore(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)
}
}
Loading