AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Import Solution

skill-microsoft-power-platform-skills-import-solution · by microsoft

>-

No reviews yet
0 installs
27 views
0.0% view→install

Install

$ agentstack add skill-microsoft-power-platform-skills-import-solution

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-microsoft-power-platform-skills-import-solution)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Import Solution? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

> Plugin check: Run node "${PLUGIN_ROOT}/scripts/check-version.js" — if it outputs a message, show it to the user before proceeding.

import-solution

Imports a solution zip into a target Dataverse environment via ImportSolutionAsync. Supports optional staged import via StageSolution to check for missing dependencies before committing.

Prerequisites

  • PAC CLI installed and authenticated to the target environment
  • Azure CLI installed and logged in
  • Solution zip file exists on disk (produced by export-solution)

Phases

Phase 0 — ALM plan gate

> plan-alm is the front door. When the user expresses an ALM intent (promote / ship / deploy / set up CI-CD / move to staging / push to prod), the orchestrator (/power-pages:plan-alm) should run first. This Phase 0 enforces that and is meant to fail closed when there's no plan, not to be a one-time check the user can dismiss forever.

Skip rule. If this skill was invoked as part of an active plan-alm orchestration, skip Phase 0 entirely and proceed to Phase 1. The gate helper exposes this via its inExecution block — pass through silently to Phase 1 when:

inExecution.status === "active"

The helper computes this from docs/.alm-plan-data.jsonPLAN_STATUS === "In Execution" AND LAST_INVOCATION_AT within the last 60 minutes. check-alm-plan.js refreshes LAST_INVOCATION_AT automatically on every invocation that finds the plan in execution, so each in-chain skill keeps the chain alive for the next one — even multi-hour deploys (deploy-pipeline alone can take 60 min per stage) survive the window without the chain incorrectly de-classifying. Stalled chains (no heartbeat for > 60 min) reclassify as stale-heartbeat and Phase 0 gates fire normally so an abandoned plan doesn't silently bypass user confirmation.

When inExecution.status is anything other than "active" ("not-running", "stale-heartbeat", "no-plan"), run the Phase 0 gate flow below. Branch on the remaining helper fields:

Step 1 — Run the gate helper.

node "${PLUGIN_ROOT}/scripts/lib/check-alm-plan.js" --projectRoot "."

The helper returns JSON with { exists, deferred, stale, staleness: { reason, detail }, generatedAt, planStatus, ... }. Pass --envUrl, --token, --solutionId once Phase 1 has acquired them if you also want a freshness check; otherwise the helper does an existence-only check, which is sufficient for the gate decision below.

Step 2 — Branch on the result.

| Result | Behavior | |---|---| | deferred: true | The user has explicitly deferred ALM for this project (.alm-deferred marker present). Pass through silently to Phase 1 — do not nag. | | exists: false | The user hasn't run plan-alm yet. See Step 3. | | exists: true, stale: false | Plan is current. Pass through silently to Phase 1. | | exists: true, stale: true (reason: solution-modified) | The solution changed after the plan was generated. See Step 4. |

Step 3 — No plan. Tell the user:

> "No ALM plan exists for this project. /power-pages:plan-alm builds one — it detects the project state, asks about your promotion strategy (PP Pipelines vs Manual export/import), and orchestrates the right skills (including this one) in the right order. Want me to run plan-alm now?"

> 🚦 Gate (intent · import-solution:0.no-plan): Fail-closed entry gate when check-alm-plan.js returns exists:false. Helper-script-backed.

AskUserQuestion:

| Question | Header | Options | |---|---|---| | Run /power-pages:plan-alm first? | ALM plan gate | Yes — run /power-pages:plan-alm now (Recommended), Continue without a plan (advanced — I know what I'm doing), Cancel |

  • Yes (Recommended) → invoke /power-pages:plan-alm. It builds the plan and returns — plan-alm is a planner and does not deploy. This skill then re-runs the Phase 0 check (now exists:true) and proceeds to Phase 1.
  • Continue without a plan → set BYPASSED_PLAN_GATE = true and proceed to Phase 1.
  • Cancel → exit cleanly.

Step 4 — Stale plan. Tell the user:

> "ALM plan exists from {generatedAt} but the source solution has been modified since (at {solution.modifiedon}). Components may have changed. Re-running plan-alm will refresh the analysis and the rendered HTML."

> 🚦 Gate (intent · import-solution:0.stale-plan): Fail-closed entry gate when check-alm-plan.js returns stale:true. Helper-script-backed.

AskUserQuestion:

| Question | Header | Options | |---|---|---| | Refresh the plan first? | ALM plan freshness | Refresh — re-run /power-pages:plan-alm (Recommended), Continue with the existing plan, Cancel |

  • Refresh (Recommended) → invoke /power-pages:plan-alm. After completion, re-run the Phase 0 helper once to confirm freshness; if still stale, surface the detail and proceed to Phase 1 anyway (don't infinite-loop).
  • Continue → set STALE_PLAN_ACK = true and proceed to Phase 1.
  • Cancel → exit cleanly.

Why this gate exists. Direct invocation of import-solution deploys a zip into a target environment without the orchestrator's deployment-strategy selection or post-import validation steps. Users running this skill standalone often skip the staged-import dependency check, miss env var override values for the target environment, and have no plan-tracked record of which environment received which artifact version. The gate ensures plan-alm either ran (so the strategy was selected, per-stage values were captured in deployment-settings.json, and the deployment is reproducible) or the user explicitly chose to bypass it.

Phase 1 — Verify Prerequisites

Create all tasks upfront at the start of this phase.

Tasks to create:

  1. "Verify prerequisites"
  2. "Locate solution file"
  3. "Configure import"
  4. "Stage solution (dependency check)"
  5. "Import solution"
  6. "Verify import"
  7. "Detect cloud flows"
  8. "Present summary"

> Note: If the import fails with an AttachmentBlocked error, a Phase 5b remediation flow runs inline — no additional task is needed (it continues within the "Import solution" task). The "Detect cloud flows" task is skipped automatically if no Workflows/*.json files are present in the solution zip.

Steps:

  1. Run pac env who — extract environmentUrl (verify this is the target environment)
  2. Run az account get-access-token --resource "{environmentUrl}" --query accessToken -o tsv — capture token
  3. Verify API access: GET {environmentUrl}/api/data/v9.2/WhoAmI
  4. Present target environment URL and ask user to confirm this is correct before proceeding.

> Important: Confirm the target environment with the user — importing to the wrong environment can be disruptive.

If any check fails, stop (reference ${PLUGIN_ROOT}/references/dataverse-prerequisites.md).

Phase 1.5 — Ground in current ALM documentation

> Reference: ${PLUGIN_ROOT}/references/alm-docs-grounding.md

Cap this step at ~30 seconds. If MCP search / fetch errors out, log a one-line note and continue — this skill must remain runnable offline.

  1. Run microsoft_docs_search with the query: Power Pages solution import staging missing dependencies ImportSolutionAsync ALM.
  2. Fetch https://learn.microsoft.com/en-us/power-platform/alm/solution-concepts-alm (and at most one sister page on staged imports or dependency handling) in parallel via microsoft_docs_fetch.
  3. Extract a one-paragraph summary of what Microsoft Learn currently says about staging vs direct import, dependency resolution, and component-level error handling. Compare against ${PLUGIN_ROOT}/references/solution-api-patterns.md and flag any divergence in ImportSolutionAsync / StageSolution signatures.
  4. Use the summary to inform Phase 2+ decisions. Do not silently change skill behavior — surface any divergence to the user as a soft warning before Phase 4 (the actual import).

Phase 2 — Locate Solution File

  1. If a zip path was provided as an argument, use it directly
  2. Otherwise, search for solution zips: glob('**/*.zip', { ignore: ['**/node_modules/**'] })
  3. For each found zip, verify it contains solution.xml:
  • Use Bash: unzip -l "{zipPath}" 2>/dev/null | grep -qi solution.xml
  1. If multiple valid zips found, ask user to choose:

> 🚦 Gate (plan · import-solution:2.multiple-zips): More than one valid solution zip was discovered under the project root. User picks which one to import. Cancel exits before any target-env interaction.

Use AskUserQuestion with one option per valid zip — show filename + size + modified date so the user can identify the right one (most-recent export is usually the intended target).

  1. If no valid zip found: stop and explain — run export-solution first or provide the zip path

Step 5a — Pre-import content inspection (run after zip is confirmed, before presenting to user):

Inspect the zip to surface post-import manual requirements. Run all checks in sequence:

# 1. Connection references (require user-binding post-import)
unzip -p "{zipPath}" customizations.xml 2>/dev/null | grep -c '/dev/null | grep -qi "bots/" && echo "found" || echo "none"

# 3. Cloud flows with hardcoded environment URLs (will silently fail in target)
unzip -p "{zipPath}" "Workflows/*.json" 2>/dev/null | grep -o '"organization":\s*"https://[^"]*"' | head -5

Build a postImportWarnings list from the results:

| Finding | Warning to surface | |---|---| | connectionreference count > 0 | "⚠️ Connection references: This solution includes N connection(s) (e.g. Dataverse connector). After import, you must bind each connection reference to a live connection in the target environment, or cloud flows that depend on them will be disabled." | | bots/ folder present | "⚠️ Copilot Studio bot: This solution includes a bot. After import, the bot must be republished in the target environment to complete provisioning." | | Hardcoded org URL found | "⚠️ Hardcoded environment URL: The cloud flow contains a hardcoded environment URL ({foundUrl}). This will cause the flow to call the source environment after import. Edit the flow in the target environment to update the URL." |

If postImportWarnings is non-empty, display all warnings inline (not via AskUserQuestion) before presenting the zip details. The user should see these before confirming.

Present the selected zip file details (name, size, path), any pre-import warnings, and confirm with user.

Phase 3 — Configure Import

Step 3.0 — Version-skew advisory (read-only check before any prompt).

Before asking the user about staged/direct import, query the target environment for the solution unique name carried in the zip and compare the installed version against the zip's version. The goal is to surface "you're about to import the same version that's already installed" before the user clicks through — this is the most common silent-failure pattern for the manual export/import path, because the source-side bump is what produces an unambiguously promotable artifact.

  1. Extract the zip's uniqueName + version from solution.xml inside the zip:

``bash unzip -p "{zipPath}" solution.xml 2>/dev/null | head -50 ` Parse and from the XML. Store as ZIPSOLUTIONNAME and ZIPSOLUTIONVERSION`.

  1. Query the target for the installed solution:

`` GET {envUrl}/api/data/v9.2/solutions?$filter=uniquename eq '{ZIP_SOLUTION_NAME}'&$select=solutionid,uniquename,version,ismanaged ` Store the result as INSTALLED (or null if the filter returns an empty value` array).

  1. Compare versions via the shared helper, then branch on the result.

Precondition — skip this entire step when INSTALLED is null. That's the first-time-install case: there's nothing on the target to compare against. Do NOT call the helper with null substituted into '{INSTALLED.version}' — it would throw "version is required" and leave the agent without a branch. Jump straight to the staged/direct prompt below and treat the import as a fresh install.

Otherwise (INSTALLED is non-null), compare versions:

Critical: **do not compare version strings with raw > / INSTALLED. Same segment-wise integer rules as bumpPatchSegment (pad-with-zero, max-4-segments, reject non-integer). Capture stdout, trim, and store the integer as VERSION_CMP`. If the helper throws (malformed version on either side), surface the stderr to the user and stop — the version comparison is a precondition for safe import.

| INSTALLED | VERSION_CMP | Behavior | |---|---|---| | null | (helper not called — see precondition above) | First-time install. Continue silently to the staged/direct prompt below. | | not null | 1 (zip is strictly greater) | Normal upgrade. Report: "Target has v{INSTALLED.version} installed; this zip is v{ZIPSOLUTIONVERSION}. Importing will upgrade." | | not null | 0 (zip equals installed) | Surface the warning below (same-version skew — applies to both managed and unmanaged). | | not null | -1 (zip is strictly less) | Surface the warning below (downgrade — applies to both managed and unmanaged). |

> 🚦 Gate (consent · import-solution:3.0.version-skew): Zip version is equal-to or lower-than the installed solution's version on the target. Importing produces unpredictable upgrade semantics; the source export-solution is supposed to bump the version on every export. Re-export with bumped version, force the import anyway, or cancel.

Warning promptAskUserQuestion:

> "The target environment already has {ZIP_SOLUTION_NAME} v{INSTALLED.version} installed ({INSTALLED.ismanaged ? 'managed' : 'unmanaged'}). The zip you are about to import carries version {ZIP_SOLUTION_VERSION}. > > Importing the same or a lower version is unreliable: > - Managed: no upgrade lineage; the platform may apply or reject the import depending on internal heuristics. > - Unmanaged: behavior depends entirely on OverwriteUnmanagedCustomizations: true, and any in-target edits that happen to match the zip's component IDs get silently overwritten without a version change to point to. > > /power-pages:export-solution always bumps the source version before producing a zip (since 2026-05-25). If this zip was produced before that change, re-exporting will give you a clean, strictly-greater version. > > How would you like to proceed?" > > | Question | Header | Options | > |---|---|---| > | What to do? | Version skew | Re-export with a bumped version (Recommended — invokes /power-pages:export-solution), Import anyway (proceed at your own risk), Cancel |

  • Re-export: invoke /power-pages:export-solution. After it completes, restart this skill from Phase 2 with the freshly-produced zip.
  • Import anyway: set SKEW_ACK = true and proceed to the staged/direct prompt below. Record the acknowledged skew in docs/alm/last-import.json under versionSkew: { zipVersion, installedVersion, isManaged, acknowledged: true } for the audit trail.
  • Cancel: stop the skill cleanly. No target-env writes happened in Step 3.0 — it was read-only.
  1. If the comparison is the normal upgrade case (or the zip's solution isn't installed yet), continue silently — do not present a prompt, just record the version delta in the eventual docs/alm/last-import.json for the summary.

> 🚦 Gate (plan · import-solution:3.config): Staged vs Direct import, overwrite options. Cancel exits before any target-env mutation.

Ask user (via AskUserQuestion):

> Key Decision Point: Staged vs Direct import > - Staged (Recommended for managed solutions): Runs StageSolution first to check for missing dependencies. Shows issues before committing the import. Safer — the stage step is fully reversible. > - Direct: Skips staging and imports immediately. Faster but may fail mid-import if dependencies are missing.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.