# Deploy Solution Skill

Deploy Dataverse solutions between environments with proper dependency resolution. Handles the full ALM pipeline: export → dependency analysis → ordered import → verification.

## When to Use

- Moving a solution from dev to test/staging/prod for the first time
- Updating an existing solution in a target environment
- Troubleshooting failed solution imports (missing dependencies)
- Setting up a new environment with an existing solution stack

## Phase 0: Pre-Flight

1. **Verify connectivity** to both source and target environments via `dataverse_test_connection`
2. **Ask the user**:
   - Source environment name
   - Target environment name
   - Solution name to deploy
   - Managed or unmanaged export? (Managed is standard for non-dev targets)

## Guardrails

- **Read solution contents before importing.** Use `dataverse_get_solution` and check component types. Flag if the solution contains sitemaps, security roles, or forms that already exist in the target — these WILL be overwritten on import.
- **Never delete components to fix an import error.** Import errors are usually caused by missing dependencies (e.g., a table referenced by a view doesn't exist in the target). Trace the dependency chain to find the root cause.
- **Managed vs Unmanaged matters.** Managed solutions lock components in the target — they can't be edited there. Unmanaged solutions merge and can be edited. Confirm with the user which type is intended.
- **Export before importing to production-like environments.** If the target has customizations that could be overwritten, export the current solution as a backup first.
- **PCF controls, plugins, and web resources are solution dependencies.** If the solution contains form customizations that reference these, they must be imported first or included in the same solution.

## Phase 1: Export from Source

1. Call `dataverse_get_solution` on the source to verify the solution exists, check version, and review component summary
2. Call `dataverse_export_solution` with `managed: true` (for non-dev targets) or `managed: false` (for dev-to-dev)
3. Store the base64 ZIP — this is the artifact to import

## Phase 2: Dependency Analysis (CRITICAL)

**Before importing, always check for missing dependencies.** This prevents import failures and partial deployments.

### Step 2a: Identify solution dependencies

Query the source environment for the solution's dependencies:
```
Query solutioncomponents for the solution → for each component, check if it references
components outside the solution → those are external dependencies
```

Common dependency types that cause failures:
| Type Code | Component | Common Source | Resolution |
|-----------|-----------|---------------|------------|
| 66 | Custom Control (PCF) | `pac pcf push` to dev | Build solution ZIP from PCF source project, import first |
| 61 | Web Resource | Default Solution | Add to solution before export, OR export containing solution |
| 1 | Entity (Table) | Another solution | Import that solution first |
| 26 | View | System views | Usually auto-resolves, rarely blocks |
| 29 | Workflow/Process | Another solution | Import that solution first |
| 91 | Plugin Assembly | Plugin Registration Tool | Build solution from plugin project, import first |

### Step 2b: Check target for existing dependencies

Call `dataverse_list_solutions` on the target to see what's already installed. Many dependencies may already be satisfied.

### Step 2c: Resolve missing dependencies

For each missing dependency:

**PCF Controls (type 66):**
- PCF controls deployed via `pac pcf push` create a non-exportable managed solution named `solution`
- You CANNOT export this managed solution — it must be rebuilt from source
- Look for the PCF source project (typically in a `pcf/` directory)
- The distributable ZIP is at `{pcf-project}/solution/bin/Release/solution.zip`
- If no pre-built ZIP exists, rebuild: `cd {pcf-project}/solution && dotnet build -c Release`
- Import this ZIP to the target BEFORE the dependent solution

**Plugin Assemblies (type 91):**
- Similar to PCF — plugins registered via Plugin Registration Tool may not be in a solution
- Build a solution containing the plugin from the source project
- Or use `dataverse_register_plugin_assembly` + `dataverse_register_plugin_step` to recreate in target

**Web Resources (type 61):**
- If the web resource is in the Default Solution, add it to the main solution: `dataverse_add_solution_component` with `component_type: 61` and the web resource GUID
- Re-export the solution — the web resource now travels with it

**Tables from other solutions (type 1):**
- Import the other solution to the target first
- Or add the table to the current solution (creates a dependency reference, not a copy)

## Phase 3: Import to Target (Ordered)

Import solutions in dependency order — dependencies BEFORE dependents:

```
Example for MCPTestMatrix with a PCF dependency:
1. Import PCF solution (solution.zip) → creates the custom control
2. Import MCPTestMatrix (managed) → references the now-existing control
```

For each import:
1. Call `dataverse_import_solution` with the base64 ZIP
2. The import is **async** — it returns an `import_job_id` immediately
3. Poll the import job: `dataverse_get_record` with `entity_set: 'importjobs'`, `id: '{job_id}'`, `select: 'solutionname,progress,completedon'`
4. Wait until `progress: 100` and `completedon` is not null

### Import options:
- `overwrite_customizations: true` — overwrites any unmanaged customizations in the target that conflict. Use when updating an existing managed solution.
- `publish_workflows: true` — auto-publishes workflows/flows included in the solution

## Phase 4: Post-Import Verification

1. Call `dataverse_get_solution` on the target to verify the solution is installed with the expected version
2. Call `dataverse_list_tables` with `prefix_filter` matching the solution's publisher prefix — verify tables exist
3. Spot-check a few columns: `dataverse_list_columns` on key tables
4. If the solution includes an app: `dataverse_list_apps` to verify it's present
5. Call `dataverse_publish_all` to ensure all customizations are published

## Phase 5: Handle Import Failures

If the import fails:

### Missing dependency error (0x80048033)
- Parse the `<MissingDependencies>` XML from the error message
- Each `<MissingDependency>` has a `<Required>` element with `type`, `schemaName`, and `solution`
- Follow Phase 2 resolution steps for each missing dependency
- Retry the import after resolving all dependencies

### Custom control ID not found (0x80040216)
- The PCF control record exists but the compiled code doesn't
- This happens when you add the control metadata via `add_solution_component` without the actual bundle.js
- Resolution: import the proper PCF solution ZIP built from source, NOT just the metadata record

### General import error (0x80048036)
- "Managed solutions cannot be exported" — you're trying to export an already-managed solution
- Find the unmanaged source or rebuild from the original project

## Golden Rules

1. **NEVER modify the source solution to work around a dependency** — this can break existing environments
2. **NEVER delete components from the target to resolve conflicts** — this removes functionality
3. **Always import dependencies before dependents** — Dataverse validates dependencies at import time
4. **Always use managed solutions for non-dev environments** — unmanaged in prod = uncontrolled changes
5. **Always verify post-import** — a 100% progress doesn't always mean everything published correctly
6. **PCF controls from `pac pcf push` are NOT transportable** — always build a proper solution ZIP from source for ALM

## Validation

After importing or exporting a solution:
- For exports: verify the solution file was created and is non-empty
- For imports: verify key components exist in the target environment — check a sample table, form, and view
- If the solution contained a sitemap: open the app and verify navigation is correct
- If the solution contained security roles: verify role assignments are intact
- Report: solution name, version, component count, import/export status, any warnings
