fix(isolated): inject target input into generated apm.yml#33
Conversation
APM v0.12.3 (microsoft/apm#1154) introduced strict harness detection: `apm install` exits 2 with "No harness detected" when there is no target signal (apm.yml `target:`, --target flag, or on-disk marker like .github/copilot-instructions.md). The action's isolated mode generates apm.yml from inline `dependencies` input but never propagated the workflow's `target:` input into the manifest. Result: every gh-aw / inline-deps workflow upgrading past v0.12.3 broke with exit 2. Fix: when `target:` input is set, write `target: <value>` into the generated apm.yml. Manifest stays unchanged when target is not set so callers that rely on on-disk markers keep working. Also expands the `target:` input description in action.yml to cover the install-time use, lists all supported harnesses, and notes the APM v0.12.3+ requirement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes isolated-mode installs for APM v0.12.3+ by persisting the action’s target input into the generated apm.yml, ensuring apm install has an explicit harness signal.
Changes:
- Read
targetinput in isolated mode and writetarget: <value>into the generatedapm.ymlwhen provided. - Extend isolated-mode tests to cover both “target present” and “target absent” manifest generation.
- Update
action.ymlinput description and regeneratedist/index.js.
Show a summary per file
| File | Description |
|---|---|
src/runner.ts |
Injects optional target into generated apm.yml during isolated installs and logs it. |
src/__tests__/runner.test.ts |
Adds regression tests verifying target: is written/omitted correctly in isolated mode. |
dist/index.js |
Compiled output reflecting the runner changes. |
action.yml |
Documents target as both a pack-time and isolated-install-time harness signal. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/4 changed files
- Comments generated: 1
| const targetLine = target ? `target: ${target}\n` : ''; | ||
| const content = `name: inline-workflow\nversion: 1.0.0\n${targetLine}dependencies:\n apm:\n${depEntries.join('\n')}\n`; | ||
| fs.writeFileSync(apmYmlPath, content, 'utf-8'); | ||
| core.info(`Generated apm.yml with ${deps.length} dependencies (isolated mode)`); | ||
| const targetSuffix = target ? ` (target: ${target})` : ''; | ||
| core.info(`Generated apm.yml with ${deps.length} dependencies (isolated mode)${targetSuffix}`); |
Two related changes prompted by the v0.12.3 strict-detection rollout: 1. Pin the action's default `apm-version` from `latest` to `0.12.3`. Floating on `latest` means every APM release ships into every downstream workflow without review -- exactly how v0.12.3 broke gh-aw and apm-action's own CI in the same hour. The new default gives users a known-good baseline and forces an explicit, reviewed bump (or an explicit `apm-version: latest` opt-in) for upgrades. 2. Add `target:` to every CI test fixture (apm.yml + isolated mode `with:` blocks). v0.12.3 requires an explicit harness signal -- without it `apm install` exits 2 with "No harness detected". The action now correctly propagates the input into isolated-mode manifests; the test workflows just needed to declare a target like any real consumer would. Both action.yml input description and the existing tests in runner.test.ts already cover the new behaviour. dist/ unchanged (action.yml + workflow files only). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pushed Two changes in this follow-up commit:
|
v0.12.3 dropped the 'vscode' target alias. Valid targets are now: agent-skills, claude, codex, copilot, cursor, gemini, opencode, windsurf. The 'copilot' target deploys to .github/ -- same outcome as the old 'vscode' alias, just under its canonical name. Updates pack/restore CI fixtures and trims 'vscode' from the `target:` input description in action.yml. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two assertions in ci.yml predated v0.12.3 and no longer reflect the shipped behaviour: 1. Skills under the `copilot` target now deploy to `.agents/skills/` (universal AGENTS-style fallback) rather than `.github/skills/`. Other primitive types (agents, instructions, prompts) still land under `.github/`. Update the isolated and setup-only checks to look for the skill at the new path. 2. The `plugin` bundle format now ships `apm.lock.yaml` alongside `plugin.json` (lockfile is needed to reproduce the deployed set when the plugin is restored). Drop the obsolete "plugin must NOT contain apm.lock.yaml" assertion; keep the positive plugin.json presence check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#36) Mirror of #33's fix for the second install path. Isolated mode writes `target:` into the generated apm.yml; the non-isolated additive path (`apm install <dep>` per inline dep, no apm.yml present) had no such signal and so APM v0.12.3+ strict harness detection rejected with exit code 2 ("No harness detected") on every workspace without an on-disk marker like `.github/copilot-instructions.md`. `installDeps` now accepts the validated target and appends `--target <value>` to every `apm install <dep>` call. The bare `apm install` (apm.yml-driven) path is intentionally left alone - the project's apm.yml is the source of truth for that case, and overriding it from the action input would be surprising. Caught by test-action.yml's `Install with inline dependencies (additive)` job on the v1.7.0 tag run. Regression test asserts the per-dep call sequence is `apm install <pkg> --target <value>`. 111/111 unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TL;DR
APM v0.12.3 (microsoft/apm#1154) made target detection strict. In isolated mode, this action generates
apm.ymlfrom inlinedependencies:but never persisted thetarget:input into that manifest, so every workflow upgrading past v0.12.3 now exits 2 withError: No harness detected for installation.This PR injects
target: <value>into the generated manifest when the input is set.Symptom
Broken run on
microsoft/apmitself (usesapm-action@v1from a gh-aw workflow):The workflow set
target: claudebut the generatedapm.ymlonly containedname/version/dependencies.Root cause
src/runner.tsgenerateManifest()wrote:with no harness signal. Pre-v0.12.3 APM silently defaulted to
copilot; v0.12.3 (microsoft/apm#1154) requires an explicit signal — apm.ymltarget:,--target, or an on-disk marker like.github/copilot-instructions.md— and exits 2 otherwise.The action's
target:input was only consumed by the pack/bundle step, never by isolated install.Fix
generateManifest()now accepts an optionaltargetand writes atarget: <value>line into the generatedapm.ymlwhen set.core.getInput('target')and forwards it.target:input is empty, manifest is unchanged (back-compat — workflows that rely on an on-disk harness marker keep working).action.yml: expandedtarget:input description to cover the install-time use, list all supported harnesses (copilot/vscode/claude/cursor/codex/opencode/gemini/windsurf, also accepts CSV), and note the APM v0.12.3+ requirement.Tests
src/__tests__/runner.test.ts— two new cases under the existing isolated-mode block:writes target into generated apm.yml when target input set (isolated mode)— asserts the generatedapm.ymlcontains^target: claude$when the workflow passestarget: claude.omits target line when target input not set (isolated mode)— asserts no spurioustarget:line is written when the input is empty (back-compat).Local validation (mirrors CI):
Trade-offs
apm.ymlfrom the checkout, which should already declare its target — passing--targetthere would be redundant and risk overriding the project's intent.target:input keeps the surface flat. The input was already documented forpack; we now also document its install-time meaning.How to test
After merge, re-run the previously failing job in microsoft/apm: https://github.com/microsoft/apm/actions/runs/25484800900/job/74779405094 — it should resolve and install without the
No harness detectederror.Or locally, with the rebuilt
dist/:The generated
apm.ymlwill includetarget: claude, andapm installwill deploy to.claude/.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com