Skip to content

feat: allow multiple targets in apm.yml and --target CLI flag#628

Open
sergio-sisternes-epam wants to merge 15 commits intomicrosoft:mainfrom
sergio-sisternes-epam:feat/529-multi-target-support
Open

feat: allow multiple targets in apm.yml and --target CLI flag#628
sergio-sisternes-epam wants to merge 15 commits intomicrosoft:mainfrom
sergio-sisternes-epam:feat/529-multi-target-support

Conversation

@sergio-sisternes-epam
Copy link
Copy Markdown
Collaborator

@sergio-sisternes-epam sergio-sisternes-epam commented Apr 8, 2026

Multi-target support for apm.yml and CLI --target

Closes #529

Problem

Users deploying to 2-3 tools (e.g. Copilot + Claude) had to choose between a single --target or all, which generates redundant output for tools they don't use.

Solution

Allow specifying multiple targets via list syntax in apm.yml and comma-separated values on the CLI:

# apm.yml
target: [claude, copilot]
# CLI
apm compile -t claude,copilot
apm install owner/repo -t claude,copilot
apm pack -t claude,copilot
apm deps update -t claude,copilot

Architecture

Unified through the existing active_targets() / resolve_targets() TargetProfile system -- no breaking API changes:

  • detect_target() stays scalar (Optional[str]) -- unchanged
  • active_targets() / resolve_targets() widened to accept Optional[Union[str, List[str]]]
  • TargetParamType (new Click parameter type) handles comma-separated parsing, alias resolution, validation
  • Compile/pack map list inputs to compiler-understood strings via _resolve_compile_target()
  • Install already iterated List[TargetProfile] -- minimal change (removed dead code)
  • Policy enforce/allow checks handle list targets

Changes

Commit Scope
feat: add normalize_target_list() and multi-target constants Core constants and normalization
feat(manifest): accept list in apm.yml target field APMPackage.target type widened
feat(targets): accept list in active_targets/resolve_targets Integration layer list support
feat(cli): add TargetParamType for comma-separated --target CLI parsing + 4 command updates
refactor(install): remove dead detect_target call Dead code cleanup
feat(policy): handle list targets in compilation target check Policy enforce/allow with lists
feat(compile,pack): handle multi-target lists Compile routing + pack filtering
docs: document multi-target support CHANGELOG, docs site, APM guide

Backward compatibility

  • Single-string target: copilot and -t copilot work exactly as before
  • "all" is exclusive -- cannot be combined with other targets
  • Aliases (vscode, agents) resolve to copilot in multi-target context
  • No changes to detect_target() return type or lockfile schema

Testing

  • 83+ new tests across 7 test files
  • 3830 total tests pass (full unit suite)
  • Coverage: TargetParamType parsing, manifest list field, active_targets list input, compile target mapping, pack prefix filtering, policy enforce/allow with lists

Sergio Sisternes and others added 9 commits April 8, 2026 19:10
Fixes microsoft#529

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add ALL_CANONICAL_TARGETS, TARGET_ALIASES, and normalize_target_list()
helper to target_detection.py. These are the foundation for multi-target
support (microsoft#529). Purely additive — no existing functions changed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Widen APMPackage.target type from Optional[str] to
Optional[Union[str, List[str]]]. PyYAML naturally returns list for
YAML sequences, so no parsing changes needed.

Add 6 tests covering string, list, missing, single-item-list, and
direct construction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ft#529)

Widen explicit_target parameter in active_targets(),
active_targets_user_scope(), and resolve_targets() from Optional[str]
to Optional[Union[str, List[str]]].

List handling: iterate targets, resolve aliases (vscode/agents ->
copilot), deduplicate by profile name, short-circuit on 'all'.
Single-string path unchanged for backward compatibility.

Add 11 tests for list input covering single-element, multi-element,
alias dedup, all-in-list, mixed known/unknown, order preservation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t#529)

Add TargetParamType (Click parameter type) that accepts comma-separated
target values. Single values and 'all' return strings for backward
compat; multiple targets return deduplicated list of canonical names.

- Validates each token against VALID_TARGET_VALUES (derived, not hardcoded)
- Enforces 'all' exclusivity ('all,claude' is rejected)
- Resolves aliases (vscode/agents -> copilot) on multi-target path
- Handles whitespace, empty parts, case normalization

Replace click.Choice with TargetParamType in compile, install, pack,
and deps commands. Add 37 tests for TargetParamType.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The install command already uses resolve_targets() for multi-target
resolution. The detect_target() call was assigning to unused variables
(detected_target, detection_reason). Remove the dead code and its
now-unused imports to prepare for multi-target list support where
detect_target() would break on list input.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oft#529)

Update _check_compilation_target() to handle target field being a list:
- enforce: check if enforced value is present in the target list
- allow: check every item in target list is in the allow set
- Backward compat: single strings normalized to [string] internally

Add 6 tests covering list enforce/allow scenarios plus backward compat.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Compile command:
- Add _resolve_compile_target() to map list inputs to compiler strings
  (copilot+claude -> 'all', claude-only -> 'claude', etc.)
- Apply to both CLI --target and apm.yml config_target
- Update progress logging for multi-target display

Pack/bundle:
- Update _filter_files_by_target() to compute union of prefixes and
  cross-target maps for list targets
- Update enrich_lockfile_for_pack() to accept and serialize list targets
- Update pack_bundle() to pass lists directly, bypassing detect_target()

Add 23 tests covering list target resolution, filtering, and packing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- CHANGELOG: add multi-target feature entry
- manifest-schema: target field type widened to string|list
- cli-commands: --target accepts comma-separated values
- compilation guide: multi-target examples
- pack-distribute: multi-target pack example
- policy-reference: enforce/allow semantics with lists
- apm-guide skills: update commands, workflow, governance

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sergio-sisternes-epam sergio-sisternes-epam marked this pull request as ready for review April 9, 2026 08:06
Copilot AI review requested due to automatic review settings April 9, 2026 08:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds multi-target support across APM’s manifest parsing, target resolution, CLI parsing, packing, and policy checks so users can specify a subset of targets (e.g. claude,copilot) instead of all.

Changes:

  • Extend target handling to accept str | list[str] in manifests, CLI, and target resolution.
  • Introduce a Click TargetParamType to parse comma-separated --target values with alias handling.
  • Update pack/lockfile enrichment, policy checks, and documentation; add unit tests for list-target behavior.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/unit/test_packer.py Adds pack-time coverage for list target filtering and pack metadata serialization.
tests/unit/test_lockfile_enrichment.py Adds coverage for list-target filtering and lockfile pack.target serialization.
tests/unit/test_apm_package.py Adds coverage for apm.yml target field accepting string or list.
tests/unit/policy/test_policy_checks.py Adds list-target coverage for compilation target policy enforcement/allow lists.
tests/unit/integration/test_targets.py Adds coverage for active_targets() handling explicit target lists.
tests/unit/core/test_target_detection.py Adds coverage for the new TargetParamType and accepted values.
tests/unit/compilation/test_compile_target_flag.py Adds coverage for compile list-target mapping via _resolve_compile_target().
src/apm_cli/policy/policy_checks.py Updates compilation target policy checks to handle list targets.
src/apm_cli/models/apm_package.py Widens APMPackage.target type to Optional[Union[str, List[str]]].
src/apm_cli/integration/targets.py Extends active_targets*()/resolve_targets() to accept list explicit targets.
src/apm_cli/core/target_detection.py Adds multi-target constants/helpers and the Click TargetParamType.
src/apm_cli/commands/pack.py Switches --target to TargetParamType() and updates help text.
src/apm_cli/commands/install.py Switches --target to TargetParamType() and removes dead detection code.
src/apm_cli/commands/deps/cli.py Switches --target to TargetParamType() and updates help text.
src/apm_cli/commands/compile/cli.py Adds _resolve_compile_target() and supports list targets in compile flow/logging.
src/apm_cli/bundle/packer.py Allows pack_bundle() to accept list targets from CLI or manifest.
src/apm_cli/bundle/lockfile_enrichment.py Extends target filtering/enrichment to accept list targets and serialize pack.target.
packages/apm-guide/.apm/skills/apm-usage/workflow.md Documents manifest/CLI multi-target syntax and updated detection wording.
packages/apm-guide/.apm/skills/apm-usage/governance.md Clarifies policy semantics when targets are lists.
packages/apm-guide/.apm/skills/apm-usage/commands.md Documents comma-separated --target on relevant commands.
docs/src/content/docs/reference/manifest-schema.md Updates manifest target schema to allow `string
docs/src/content/docs/reference/cli-commands.md Documents comma-separated multi-target --target for install/pack/compile/deps update.
docs/src/content/docs/introduction/how-it-works.md Notes that apm.yml target can restrict auto-detected targets (string or list).
docs/src/content/docs/guides/pack-distribute.md Adds example for comma-separated multi-target packing.
docs/src/content/docs/guides/compilation.md Adds example for comma-separated multi-target compilation and manifest list syntax.
docs/src/content/docs/enterprise/policy-reference.md Updates policy docs to describe list-target enforcement and expanded allowed values.
CHANGELOG.md Adds an entry describing multi-target support.

…osoft#628)

- Replace all non-ASCII characters (em dashes, Unicode arrows, box-drawing)
  with ASCII equivalents across 4 source files
- Fix normalize_target_list('all') to return sorted target list instead
  of None (clearer semantics, function currently unused)
- Add code comment documenting dict.update() last-wins limitation in
  cross-target map merging for multi-target packs
- Move CHANGELOG entry to [Unreleased] section, reference PR microsoft#628

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Allow multiple targets in apm.yml

3 participants