Skip to content

Add Actions type of resource - #1734

Open
Steve Lee (SteveL-MSFT) wants to merge 23 commits into
PowerShell:mainfrom
SteveL-MSFT:actions
Open

Steve Lee (SteveL-MSFT) wants to merge 23 commits into
PowerShell:mainfrom
SteveL-MSFT:actions

Conversation

@SteveL-MSFT

@SteveL-MSFT Steve Lee (SteveL-MSFT) commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

PR Summary

Add Actions type of resource which implements a single invoke operation but declares if it's supported for get, set, test, and/or export`. Input schema required if input taken. Optional output schema if output returned and differs from input schema.

Moved some of the common types from dscresource into new resource folder.

ResourceInvoke trait abstracts resources, actions, and adapters. This resulted in wide code changes which used to take a DscResource. Functions added to trait for common properties across these types and also as_dsc_resource() and as_action() to make it easier to use.

ManifestKind extended with as_action_manifest() and as_resource_manifest() to easily access their respective manifests.

Consolidated the different DiscoveryCache into a single type since they all implement ResourceInvoke which also caused lots of code change.

Other specific changes:

  • path and directory in dscresource, extension, and action are now Option
  • remove use of unstable feature on config.toml since it's now stable
  • add new DscResourceKind that encapulates DscResource and DscAction, this resulted in many changes that formally only expected a DscResource
  • add new dsc action list to list actions, did not implement dsc action invoke since expectation is apps use the server apis
  • add invoke_dsc_action(), list_dsc_actions(), and show_dsc_action() server APIs
  • add tests for new server apis and using actions in configuration
  • add test actions that also cover security context and versioning
  • command discovery looks separately for actions and caches them separately
  • instead of relying on resources cache empty empty to perform discovery, add a flag since there's now 2 types of resources to be discovered

PR Context

Fix #1470

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved moderate issues affect MCP contracts, input validation, configuration behavior, and discovery caching.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 6 Medium severity · 1 Low severity

Open (7)
What changed in this PR

Adds DSC action manifests, discovery, configuration support, CLI listing, MCP APIs, schemas, and test coverage.

Changes:

  • Adds action discovery, caching, invocation, and validation.
  • Adds dsc action list and MCP action tools.
  • Integrates actions with configuration and resource dispatch.
  • Adds fixtures, tests, localization, and stable Cargo configuration.
File Summary
tools/​dsctest/​src/​main.rs Adds action test support and schemas.
tools/​dsctest/​src/​args.rs Adds action arguments.
tools/​dsctest/​src/​action.rs Implements test action input/output.
tools/​dsctest/​dsctest.dsc.manifests.json Adds action manifests.
tools/​dsctest/​dsctest.dsc.action.json Adds an action fixture.
tools/​dsctest/​.project.data.json Includes the action fixture.
lib/​dsc-lib/​src/​lib.rs Exposes action support and resource kinds.
lib/​dsc-lib/​src/​extensions/​dscextension.rs Corrects directory documentation.
lib/​dsc-lib/​src/​extensions/​discover.rs Discovers action extensions.
lib/​dsc-lib/​src/​dscresources/​dscresource.rs Handles resource/action distinctions.
lib/​dsc-lib/​src/​dscresources/​command_resource.rs Adds action security validation.
lib/​dsc-lib/​src/​discovery/​mod.rs Adds action caching and lookup; cache readiness needs correction.
lib/​dsc-lib/​src/​discovery/​discovery_trait.rs Extends discovery APIs for actions.
lib/​dsc-lib/​src/​discovery/​command_discovery.rs Loads action manifests; resource cache guarding needs correction.
lib/​dsc-lib/​src/​configure/​mod.rs Executes actions during configuration; test/set operation selection needs correction.
lib/​dsc-lib/​src/​actions/​mod.rs Registers action modules.
lib/​dsc-lib/​src/​actions/​dscaction.rs Implements action loading and invocation; missing inputs can bypass validation.
lib/​dsc-lib/​src/​actions/​action_manifest.rs Defines action schemas; schema transforms need alignment with resource manifests.
lib/​dsc-lib/​locales/​en-us.toml Adds action messages.
dsc/​tests/​dsc_server.tests.ps1 Tests MCP action tools.
dsc/​tests/​dsc_actions.tests.ps1 Tests action CLI and configuration behavior.
dsc/​src/​subcommand.rs Adds action listing and validation; required null inputs and localization need correction.
dsc/​src/​server/​show_dsc_resource.rs Separates actions from resources.
dsc/​src/​server/​show_dsc_action.rs Adds action details API.
dsc/​src/​server/​mod.rs Registers action server modules.
dsc/​src/​server/​mcp_server.rs Registers action tool routers.
dsc/​src/​server/​list_dsc_resources.rs Restricts listing to resources.
dsc/​src/​server/​list_dsc_actions.rs Adds action listing; metadata incorrectly describes resources.
dsc/​src/​server/​invoke_dsc_resource.rs Restricts invocation to resources.
dsc/​src/​server/​invoke_dsc_action.rs Adds action invocation; metadata does not match the request contract.
dsc/​src/​resource_command.rs Separates action and resource CLI operations.
dsc/​src/​main.rs Dispatches the action subcommand.
dsc/​src/​args.rs Defines action CLI arguments.
dsc/​locales/​en-us.toml Adds CLI action strings.
dsc-bicep-ext/​src/​main.rs Rejects actions in Bicep resource operations.
.cargo/​config.toml Removes obsolete unstable Cargo configuration.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread dsc/src/server/invoke_dsc_action.rs Outdated
Comment thread dsc/src/server/list_dsc_actions.rs Outdated
Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/configure/mod.rs Outdated
Comment thread lib/dsc-lib/src/discovery/command_discovery.rs Outdated
Comment thread lib/dsc-lib/src/discovery/mod.rs Outdated
Comment thread dsc/src/subcommand.rs
@SteveL-MSFT
Steve Lee (SteveL-MSFT) marked this pull request as draft September 26, 2026 00:51
@SteveL-MSFT Steve Lee (SteveL-MSFT) changed the title Actions Add Actions type of resource Sep 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread dsc/src/server/invoke_dsc_resource.rs Outdated
Comment thread dsc/src/subcommand.rs
Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/discovery/mod.rs
Comment thread lib/dsc-lib/src/dscresources/dscresource.rs
Comment thread dsc/src/server/list_dsc_actions.rs Outdated
Comment thread dsc/locales/en-us.toml
Comment thread dsc/src/server/invoke_dsc_action.rs Outdated
… strings, MCP metadata

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved invocation deadlocks, metadata handling, discovery gaps, and schema publication defects block reliable action support.

2 open issues
6 previously missed issues

In code that hasn't changed since last review

Medium severity Mark generic action tools as non-idempotent

dsc/​src/​server/​invoke_dsc_action.rs:44

This tool can execute arbitrary action commands, and neither the manifest nor the handler guarantees idempotency. Repeating a restart, notification, or other imperative action can produce additional effects, so advertising every invocation as idempotent gives MCP clients an incorrect retry contract. Mark the generic action tool as non-idempotent unless idempotency is explicitly guaranteed.

Medium severity Use a distinct export base name for SchemaArgKind

lib/​dsc-lib/​src/​actions/​action_manifest.rs:116

SchemaArgKind and ArgKind share definitions/commandArgs.action.json, although only the latter accepts JSON-input and what-if argument objects. Exporting both will fail the exporter's duplicate-path check and cannot publish their distinct contracts. Give schema-command arguments their own base name.

Medium severity Skip metadata injection for schema-less action input

lib/​dsc-lib/​src/​configure/​mod.rs:292

For a no-input action with resource metadata, including metadata added by a copy loop, this helper injects _metadata into otherwise empty input. The action then rejects that input with SchemaNotAvailable. Skip metadata injection when an action has no input schema and no properties were supplied.

Medium severity Reject native actions when require_adapter is specified

lib/​dsc-lib/​src/​discovery/​mod.rs:197

For an action, as_dsc_resource() returns None, so this condition falls through to true even when the filter specifies require_adapter. A configuration that pins an adapter can therefore select a native action that does not require that adapter, violating the filter contract used by filter_resources(). Reject non-resource candidates when an adapter requirement is present.

Medium severity Populate DscResource.author from resource manifests

lib/​dsc-lib/​src/​dscresources/​resource_manifest.rs:68

The new author field is accepted in resource manifests, but load_resource_manifest() never copies it into DscResource.author, which defaults to None. Consequently, dsc resource list reports a null author and show_dsc_resource omits it even when the manifest supplies one. Copy the field while constructing the discovered resource, as the action loader does.

Medium severity Register action schemas in the explicit export list

xtask/​src/​schemas/​export.rs:113

The explicit schema export list contains no action types, so schema generation never produces bundled/action/manifest.json, which the new fixtures reference. Deriving DscRepoSchema does not register these types automatically. Register the action manifest, output, and supporting schemas after resolving their conflicting export paths.

15 resolved since last review

Review effort: Balanced

Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/extensions/discover.rs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ifests during resource discovery

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved action execution, manifest loading, schema export, and discovery-cache defects prevent approval.

2 open issues
5 previously missed issues

In code that hasn't changed since last review

Medium severity Do not advertise arbitrary actions as idempotent

dsc/​src/​server/​invoke_dsc_action.rs:44

An arbitrary action is not guaranteed to be idempotent: this handler executes its command on every call without a convergence check, so repeating an action can repeat side effects. Advertising idempotent_hint = true incorrectly tells MCP clients that repeated invocations have no additional effect. Use false for this generic invocation tool unless idempotence is explicitly established for every action it can invoke.

Medium severity Load actions from ManifestList content

lib/​dsc-lib/​src/​discovery/​command_discovery.rs:58

The ManifestList branch of load_manifest_content ignores the new actions member, so an extension returning manifestContent: {"actions": [...]} silently loses those actions. Add condition evaluation and action loading to that branch, using a valid directory context for inline manifests.

Medium severity Persist discovery readiness across manager requests

lib/​dsc-lib/​src/​discovery/​command_discovery.rs:576

Each new DscManager creates a fresh CommandDiscovery with resources_discovered = false, so successive server requests rescan paths and rerun extension discovery and command-backed action schema providers despite the populated static cache. Keep readiness state at the cache's lifetime, or reuse the discovery instance, while preserving explicit refresh behavior.

Medium severity Reject input for schema-less actions

lib/​dsc-lib/​src/​dscresources/​dscresource.rs:808

This unconditional success accepts properties for schema-less actions even though invocation rejects every nonempty input string. It also lets add_metadata inject _metadata, causing a no-input action with even metadata: {} to fail with SchemaNotAvailable. Reject supplied input during validation and keep configuration metadata out of the payload, preserving an empty input string when properties are absent.

Medium severity Copy manifest author into discovered resources

lib/​dsc-lib/​src/​dscresources/​resource_manifest.rs:68

The new author field is never copied into the discovered DscResource, so dsc resource list reports a null author and show_dsc_resource omits it even when the manifest supplies one. Assign resource.author = manifest.author.clone() alongside the description in load_resource_manifest (lib/dsc-lib/src/discovery/command_discovery.rs:1094).

2 resolved since last review

Review effort: Balanced

Comment thread lib/dsc-lib/src/discovery/command_discovery.rs Outdated
Comment thread xtask/src/schemas/export.rs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread lib/dsc-lib/src/actions/dscaction.rs
Comment thread lib/dsc-lib/src/actions/dscaction.rs Outdated
Comment thread lib/dsc-lib/src/discovery/command_discovery.rs Outdated
Comment thread lib/dsc-lib/src/discovery/mod.rs Outdated
Comment thread lib/dsc-lib/src/configure/mod.rs
Comment thread lib/dsc-lib/src/discovery/command_discovery.rs
Comment thread lib/dsc-lib/src/discovery/command_discovery.rs Outdated
Comment thread lib/dsc-lib/src/discovery/mod.rs
Comment thread lib/dsc-lib/src/dscresources/dscresource.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Adapter invocation, validation, cache identity, and action API contracts have unresolved correctness issues.

3 open issues
3 previously missed issues

In code that hasn't changed since last review

Medium severity Do not advertise idempotence for action invocations

dsc/​src/​server/​invoke_dsc_action.rs:44

Action invocation always executes the command, and the manifest provides no idempotency guarantee. Advertising idempotent_hint = true tells MCP clients that repeating a call has no additional effects, which is unsafe for actions such as restarting a service and can repeat disruptive side effects on retries. Set this hint to false unless the action explicitly guarantees idempotence.

Medium severity Allow boolean schemas in show_dsc_action responses

dsc/​src/​server/​show_dsc_action.rs:16

The manifest accepts boolean JSON Schemas, and get_schema preserves them, so show_dsc_action can return inputSchema: true or outputSchema: false. This response schema excludes both values, causing schema-validating MCP clients to reject an otherwise successful response. Allow booleans alongside objects and null.

Medium severity Preserve adapter schema validation for action resources

dsc/​src/​subcommand.rs:532

validate_properties requires a local schema or manifest before it tries schema(). Resources returned by an adapter's list command, such as Adapted/One, have neither, so this unconditional call makes valid adapted configurations fail with a missing-manifest error; the previous ImplementedAs::Command guard skipped them. Preserve that behavior while including actions, or extend the helper to validate through the adapter-provided schema.

9 resolved since last review

Review effort: Balanced

Comment on lines +229 to +230
Some(value) => {
let map: Map<String, Value> = serde_json::from_value(value.clone()).ok()?;
for (resource_name, resources) in command_discovery.find(std::slice::from_ref(filter))? {
let entry = self.resources.entry(resource_name).or_default();
for resource in resources {
if !entry.iter().any(|r| r.version() == resource.version() && r.type_name() == resource.type_name()) {
processed_args.push(format!("\"{}\"", resource.path.to_string_lossy()));
} else {
processed_args.push(resource.path.to_string_lossy().to_string());
if let Some(path) = &resource.path {
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.

Add support for actions

2 participants