Manual Power Platform deployments create unnecessary risk. Exporting solutions through the UI produces opaque .zip files with no visibility into what changed. Canvas apps remain binary .msapp files that source control can’t diff. Teams work blind, with no code review process and no way to track who changed what or why.

The Power Platform CLI solves this by extracting solutions and canvas apps into source-controllable files. Once unpacked, you can version components in Git, review changes in pull requests, and automate deployments through CI/CD pipelines. The workflow transforms Power Platform development from manual exports to proper application lifecycle management.

The CLI Approach to ALM

Traditional Power Platform development exports solutions as monolithic .zip files. These files contain XML and binary data compressed into a format that source control systems can’t parse meaningfully. When a developer exports a solution and checks it into source control, the entire file shows as changed even if only a single field was modified.

The Power Platform CLI unpacks these .zip files into individual component files. A solution with three entities, two flows, and a canvas app becomes a directory structure with separate XML files for each form, view, workflow, and connection reference. Source control now tracks changes at the component level, enabling meaningful diffs and merge conflict resolution.

Canvas apps present a different challenge. The .msapp file is a binary package containing app metadata, resources, and logic. The CLI can unpack these files into readable source format, though this functionality is in preview and should be evaluated carefully for production use.

Core Workflow Pattern

The ALM workflow with Power Platform CLI follows a consistent cycle.

  1. Developer makes changes in Power Apps or Power Automate
  2. Export solution from the environment
  3. Unpack solution into source files
  4. Commit changes to version control
  5. Pack solution in CI/CD pipeline
  6. Import solution to target environment

This pattern separates development artifacts (unpacked source files) from deployment artifacts (packed .zip files). Source control stores the unpacked files. Build pipelines generate deployment artifacts on demand.

Environment Setup

Install the Power Platform CLI and authenticate to your environment.

# Authenticate to environment
pac auth create --url https://yourorg.crm.dynamics.com

List available authentication profiles to verify connection.

pac auth list

The CLI stores authentication profiles locally. Switch between profiles when working across multiple environments.

Extracting Solutions

Export a solution from your development environment to a local .zip file.

pac solution export --name YourSolutionName --path ./exports/YourSolution.zip

For managed solutions, add the --managed flag.

pac solution export --name YourSolutionName --path ./exports/YourSolution_managed.zip --managed true

Large solutions benefit from asynchronous export to avoid timeout issues.

pac solution export --name YourSolutionName --path ./exports/YourSolution.zip --async --max-async-wait-time 120

Once exported, unpack the solution into a source directory.

pac solution unpack --zipfile ./exports/YourSolution.zip --folder ./src/YourSolution

The unpack operation creates a structured directory with individual files for each component.

src/YourSolution/
├── Entities/
│   ├── Account/
│   │   ├── FormXml/
│   │   │   └── main.xml
│   │   └── SavedQueries/
│   │       └── ActiveAccounts.xml
│   └── Contact/
├── PluginAssemblies/
├── SolutionPackage/
├── Workflows/
└── Other/

Each entity’s forms, views, and fields become separate XML files. Source control can now track changes to individual components.

Unpacking Canvas Apps

Canvas apps exported as .msapp files can be unpacked into source format for version control. This feature is currently in preview.

If your canvas app is part of a solution, the .msapp file is already included in the unpacked solution directory. Locate it in the solution’s CanvasApps folder.

src/YourSolution/
├── CanvasApps/
│   └── prefix_yourcanvasapp_12abc.msapp
├── Entities/
├── Workflows/
└── Other/

Unpack the canvas app from the solution directory.

pac canvas unpack --msapp ./src/YourSolution/CanvasApps/prefix_yourcanvasapp_12abc.msapp --sources ./src/CanvasApps/YourCanvasApp

Alternatively, if the canvas app exists outside a solution, download it directly from the environment.

pac canvas list
pac canvas download --name YourCanvasApp --environment https://yourorg.crm.dynamics.com
pac canvas unpack --msapp YourCanvasApp.msapp --sources ./src/CanvasApps/YourCanvasApp

The unpacked structure reveals the app’s screens, controls, and formulas as readable files.

src/CanvasApps/YourCanvasApp/
├── Src/
│   ├── App.pa.yaml
│   ├── Screen1.pa.yaml
│   ├── Screen2.pa.yaml
│   └── Components/
│       └── Component1.pa.yaml
├── DataSources/
├── Connections/
└── Resources/

Power Apps source files use the .pa.yaml format, which contains Power Fx expressions in a structure that source control can diff and merge. Changes to individual screens, components, or controls become visible in commit history.

Important consideration: Canvas app unpacking is preview functionality. Microsoft’s documentation recommends setting ProcessCanvasApps to False in production ALM pipelines. Evaluate this feature in non-production environments before relying on it for critical deployments.

Source Control Integration

Once unpacked, commit the source files to your version control system. The directory structure supports multiple developers working on the same solution simultaneously.

git add src/YourSolution
git commit -m "Add account form validation logic"
git push origin feature/account-validation

When developers modify different components (different entities, forms, or workflows), Git merges changes automatically. The component-level file structure prevents most merge conflicts.

Conflicts occur when multiple developers modify the same file. For example, if two developers customize the same view, the XML file for that view will conflict during merge. The unpacked format makes these conflicts identifiable and resolvable.

From Microsoft’s documentation on team development:

Scenario: Two developers modify different components

  • Developer A customizes Contact entity (Active Contacts view, main form)
  • Developer B customizes Account entity (main form) and Contact entity (Lookup View)
  • Both export, unpack, and commit
  • No conflicts occur because the modified files are separate

Scenario: Two developers modify the same view

  • Developer A customizes Active Contacts view
  • Developer B customizes Active Contacts view
  • Developer A commits first
  • Developer B encounters a conflict on the Active Contacts view XML file
  • Developer B must reconcile changes by reviewing the diff, discussing with Developer A, or re-applying changes after pulling the latest source

The CLI doesn’t prevent conflicts, but it makes them visible and manageable through standard source control workflows.

Deployment Approaches

Two common patterns exist for deploying solutions after source control integration.

Option 1: Export Both Managed and Unmanaged Solutions

Export both managed and unmanaged versions of your solution during the extraction process.

# Export unmanaged for unpacking and source control
pac solution export --name YourSolution --path ./exports/YourSolution.zip

# Export managed for deployment
pac solution export --name YourSolution --path ./exports/YourSolution_managed.zip --managed true

# Unpack the unmanaged version for source control
pac solution unpack --zipfile ./exports/YourSolution.zip --folder ./src/YourSolution

Commit both the unpacked source files and the exported managed .zip to source control. During deployment, use the pre-exported managed .zip file directly.

pac solution import --path ./exports/YourSolution_managed.zip --environment https://targetorg.crm.dynamics.com

This approach uses the exact .zip file that was exported from the development environment. The managed solution has already been built by the Power Platform, eliminating any potential packing discrepancies.

Option 2: Pack Solutions from Source

Alternatively, pack source files into deployable .zip files during the deployment pipeline.

pac solution pack --zipfile ./deploy/YourSolution_managed.zip --folder ./src/YourSolution --packagetype Managed

The pack operation generates a deployment artifact from source files. Import the packed solution to the target environment.

pac solution import --path ./deploy/YourSolution_managed.zip --environment https://targetorg.crm.dynamics.com

Trade-offs: Exporting managed solutions directly ensures the deployment artifact matches what the development environment produced. Packing from source provides flexibility to generate both managed and unmanaged packages from the same source files, but introduces an additional transformation step.

Both approaches work. The key is consistency across your deployment pipeline.

CI/CD Pipeline Integration

A complete ALM pipeline for Power Platform solutions includes:

  1. Source control trigger: Commit to main branch or pull request merge
  2. Deploy pre-exported solution or pack from source
  3. Import to test environment: Deploy and validate
  4. Automated testing: Run test cases against deployed solution
  5. Import to production: Deploy to production environment after validation

Example GitHub Actions workflow using pre-exported managed solution:

name: Deploy Power Platform Solution

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Import to Production
        run: |
          pac auth create --url ${{ secrets.PROD_ENV_URL }}
          pac solution import --path ./exports/YourSolution_managed.zip

Alternatively, pack from source if your workflow requires generating deployment artifacts dynamically:

      - name: Pack Solution
        run: |
          pac solution pack \
            --zipfile ./deploy/YourSolution_managed.zip \
            --folder ./src/YourSolution \
            --packagetype Managed
      
      - name: Import to Production
        run: |
          pac auth create --url ${{ secrets.PROD_ENV_URL }}
          pac solution import --path ./deploy/YourSolution_managed.zip

Both patterns eliminate manual exports and imports. Developers commit changes to source control, and automation handles deployment.

Managing Environment Variables and Connection References

Solutions often contain environment-specific settings like connection references and environment variables. These values shouldn’t be committed to source control with hard-coded production credentials.

The CLI supports deployment settings files to manage environment-specific configurations programmatically.

Generate Deployment Settings File

Create a deployment settings file from your exported solution. This file contains templates for all environment variables and connection references in the solution.

pac solution create-settings --solution-zip ./exports/YourSolution_managed.zip --settings-file ./settings/YourSolution-settings.json

The generated JSON file includes placeholders for each environment variable and connection reference.

{
  "EnvironmentVariables": [
    {
      "SchemaName": "prefix_ApiEndpoint",
      "Value": ""
    },
    {
      "SchemaName": "prefix_ServiceAccountEmail",
      "Value": ""
    }
  ],
  "ConnectionReferences": [
    {
      "LogicalName": "prefix_SharePointConnection",
      "ConnectionId": "",
      "ConnectorId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline"
    }
  ]
}

Create Environment-Specific Settings Files

Populate separate settings files for each environment (dev, test, production) with appropriate values.

settings/prod-settings.json:

{
  "EnvironmentVariables": [
    {
      "SchemaName": "prefix_ApiEndpoint",
      "Value": "https://api.production.yourcompany.com"
    },
    {
      "SchemaName": "prefix_ServiceAccountEmail",
      "Value": "[email protected]"
    }
  ],
  "ConnectionReferences": [
    {
      "LogicalName": "prefix_SharePointConnection",
      "ConnectionId": "your-production-connection-id",
      "ConnectorId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline"
    }
  ]
}

Deploy with Settings File

During import, specify the settings file to apply environment-specific values programmatically.

pac solution import --path ./exports/YourSolution_managed.zip --settings-file ./settings/prod-settings.json

The import operation applies the values from the settings file, configuring environment variables and connection references automatically. No manual configuration required after deployment.

Pipeline Integration

In CI/CD pipelines, generate or retrieve environment-specific values from secure storage and populate the settings file before import.

- name: Configure Production Settings
  run: |
    # Retrieve secrets from Azure Key Vault or GitHub Secrets
    API_ENDPOINT="${{ secrets.PROD_API_ENDPOINT }}"
    SERVICE_EMAIL="${{ secrets.PROD_SERVICE_EMAIL }}"
    CONNECTION_ID="${{ secrets.PROD_SHAREPOINT_CONNECTION }}"
    
    # Update settings file with environment values
    # (using jq or similar JSON manipulation tool)
    
- name: Import Solution with Settings
  run: |
    pac auth create --url ${{ secrets.PROD_ENV_URL }}
    pac solution import \
      --path ./exports/YourSolution_managed.zip \
      --settings-file ./settings/prod-settings.json

This approach separates configuration from code. Source control tracks the solution logic and settings file structure. Secure storage (Azure Key Vault, GitHub Secrets) stores environment-specific credentials. Deployment pipelines merge the two at deployment time.

Version Control Benefits

Unpacking solutions provides several measurable advantages over UI-based exports.

Component-level change tracking: Git history shows exactly which form, view, or workflow changed. Commit messages explain why changes were made.

Code review capability: Pull requests display diffs for modified components. Reviewers can comment on specific changes before they reach production.

Merge conflict detection: When multiple developers modify the same component, source control identifies the conflict immediately. Without unpacking, these conflicts only surface when importing solutions and result in unexpected overwrites.

Audit trail: Every change has a timestamp, author, and explanation. Compliance requirements for change tracking are satisfied through Git history.

Rollback capability: Reverting a problematic change becomes a Git operation instead of restoring database backups.

Practical Considerations

File system performance: Solutions with hundreds of entities create thousands of XML files. File system performance matters when packing and unpacking large solutions. SSD storage significantly outperforms HDD for these operations.

Solution size: Very large solutions (100MB+) take several minutes to unpack. Consider breaking monolithic solutions into smaller, focused solutions when possible.

Canvas app limitations: Canvas app unpacking is preview functionality. Microsoft’s guidance recommends disabling ProcessCanvasApps in production pipelines. If canvas apps are critical to your solution, validate the unpack/pack cycle thoroughly in lower environments.

Incremental changes: The CLI doesn’t support incremental unpacking. Every unpack operation extracts all components. For solutions with minimal changes, this creates noise in commit history. Consider squashing commits or using feature branches to isolate work-in-progress changes.

Key Takeaways

Power Platform CLI transforms solution development from manual exports to proper application lifecycle management.

  • Export and unpack solutions to track component-level changes in source control
  • Unpack canvas apps for visibility into formulas and screen logic (preview feature, evaluate for production use)
  • Pack solutions in CI/CD pipelines to generate deployment artifacts from source
  • Use solution settings files to manage environment-specific configurations
  • Enable code review workflows through pull requests with component-level diffs

The CLI workflow requires initial setup and process changes, but the return is measurable. Version control visibility, automated deployments, and conflict detection reduce deployment risk and accelerate delivery. Once established, the pattern applies across all Power Platform solutions, creating consistency in how teams build and deploy applications.

Additional Resources