APM in CI/CD
APM integrates into your CI/CD pipeline to ensure agent context is always up to date.
GitHub Actions
Section titled “GitHub Actions”Use the official apm-action to install APM and run commands in your workflows:
name: APMon: push: branches: [main] pull_request:
jobs: install: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install APM packages uses: microsoft/apm-action@v1 # Optional: add compile: true if targeting Codex, Gemini, # or other tools whose instructions require compilationPrivate Dependencies
Section titled “Private Dependencies”For private repositories, pass a token via the workflow env: block. See the Authentication guide for all supported tokens and priority rules.
- name: Install APM packages uses: microsoft/apm-action@v1 env: GITHUB_APM_PAT: ${{ secrets.APM_PAT }}Verify Compiled Output (Optional)
Section titled “Verify Compiled Output (Optional)”If your project uses apm compile to target tools like Codex or Gemini, add a check to ensure compiled output stays in sync:
- name: Check for drift run: | apm compile if [ -n "$(git status --porcelain -- AGENTS.md CLAUDE.md GEMINI.md)" ]; then echo "Compiled output is out of date. Run 'apm compile' locally and commit." exit 1 fiThis step is not needed if your team only uses GitHub Copilot and Claude, which read deployed primitives natively.
Verify Deployed Primitives
Section titled “Verify Deployed Primitives”apm audit --ci catches integration drift by default — no separate
git status step required:
- name: Audit + drift check run: apm audit --ciThis single command runs the nine baseline lockfile checks PLUS integration
drift detection (default-on) AND replays
the install pipeline into a scratch tree to detect missed apm install
runs, hand-edited deployed files, and orphaned files. See the
Drift Detection guide for details and
opt-out (--no-drift).
For repos that commit their deployed files, use the audit-only pattern to
catch tampering or stale committed outputs without letting apm install
rewrite the checkout first. apm install overwrites managed files before
audit runs, which erases any tampered bytes before content-integrity or
drift can see them. Pass setup-only: true to the action so it only
provides the CLI, then run the full CI gate:
- uses: microsoft/apm-action@v1 with: setup-only: true - name: Audit (audit-only, committed-output gate) run: apm audit --ciIn setup-only CI, apm audit --ci now self-hydrates a lock-pinned scratch
install when apm_modules/ is absent, so drift and config-consistency
still run without mutating the checkout. Repos that gitignore deployed
outputs still need those files on disk for deployed-files-present, so keep
the full-install pattern for that case. See
Audit-only CI pattern
for the full recipe and when to use each approach.
Azure Pipelines
Section titled “Azure Pipelines”steps: - script: | curl -sSL https://aka.ms/apm-unix | sh export PATH="$HOME/.apm/bin:$PATH" apm install # Optional: only if targeting Codex, Gemini, or similar tools # apm compile displayName: 'APM Install' env: ADO_APM_PAT: $(ADO_PAT)ADO with AAD bearer (no PAT)
Section titled “ADO with AAD bearer (no PAT)”In orgs that disable PAT creation, use a Workload Identity Federation (WIF) service connection and let APM consume the az session inherited from AzureCLI@2. Do NOT set ADO_APM_PAT — APM falls back to the bearer cleanly only when no PAT env var is present.
steps: - task: AzureCLI@2 displayName: 'APM Install (AAD bearer)' inputs: azureSubscription: 'my-wif-service-connection' scriptType: bash scriptLocation: inlineScript inlineScript: | curl -sSL https://aka.ms/apm-unix | sh export PATH="$HOME/.apm/bin:$PATH" apm installFor GitHub Actions targeting ADO repos, use azure/login@v2 with OIDC federated credentials so az is signed in before apm install runs:
permissions: id-token: write contents: read
jobs: install: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - uses: microsoft/apm-action@v1 # Do not set ADO_APM_PAT -- APM picks up the az session.See Azure DevOps Services AAD bearer tokens for resolution precedence and verbose output.
General CI
Section titled “General CI”For any CI system with Python available:
pip install apm-cliapm install# Optional: only if targeting Codex, Gemini, or similar tools# apm compile --verboseGovernance with apm audit
Section titled “Governance with apm audit”apm audit --ci verifies lockfile consistency in CI (the baseline checks plus integration drift detection, no configuration). Add --policy org to enforce organizational rules. For full setup including SARIF integration and GitHub Code Scanning, see the Enforce in CI guide.
For content scanning and hidden Unicode detection, apm install automatically blocks critical findings. Run apm audit for on-demand reporting. See Governance for the full governance model.
Pack & Distribute
Section titled “Pack & Distribute”Use apm pack in CI to build a distributable bundle once, then consume it in downstream jobs without needing APM installed.
Pack in CI (build once)
Section titled “Pack in CI (build once)”apm-action@v1 with pack: true emits an APM-format bundle (--format apm --archive) so downstream jobs can restore it via unzip or the action’s restore mode.
- uses: microsoft/apm-action@v1 with: pack: true- uses: actions/upload-artifact@v4 with: name: agent-config path: build/*.zipPack as standalone plugin
Section titled “Pack as standalone plugin”# Export as a Claude Code plugin directory (default format)- run: apm pack- uses: actions/upload-artifact@v4 with: name: plugin-bundle path: build/Consume in another job (no APM needed)
Section titled “Consume in another job (no APM needed)”The APM bundle layout below assumes the upstream job ran apm-action@v1 with pack: true (or apm pack --format apm --archive). Plugin-format output cannot be restored this way because it does not carry the install-time directory tree.
- uses: actions/download-artifact@v4 with: name: agent-config- run: unzip -o build/*.zip -d ./Or use the apm-action restore mode to unpack a bundle directly:
- uses: microsoft/apm-action@v1 with: bundle: ./agent-config.zipSee the Pack a bundle guide for the full workflow.
Best Practices
Section titled “Best Practices”- Pin APM version in CI to avoid unexpected changes:
pip install apm-cli==0.22.0 - Commit
apm.lock.yamlso CI resolves the same dependency versions as local development - Commit
.github/,.claude/,.cursor/,.opencode/, and.gemini/deployed files so contributors and cloud-based Copilot get agent context without runningapm install - If using
apm compile(for Codex, Gemini instructions), run it in CI and fail the build if the output differs from what’s committed - Use
GITHUB_APM_PATfor private dependencies; never use the defaultGITHUB_TOKENfor cross-repo access