DevOps

Building CI/CD Pipelines with Azure DevOps

January 10, 2026
CRX Partners Team
15 min read

What is CI/CD?

Continuous Integration (CI) and Continuous Deployment (CD) are practices that automate the building, testing, and deployment of applications. Azure Pipelines provides a powerful, flexible platform to implement CI/CD for any technology stack, including Dynamics 365 and Power Platform solutions. Azure Pipelines.

CI/CD Benefits

  • Faster delivery: Automate repetitive tasks
  • Higher quality: Catch issues early with automated testing
  • Reduced risk: Smaller, incremental changes
  • Consistency: Same process every deployment
  • Traceability: Link deployments to code changes

Azure Pipelines Overview

Pipeline Types

  • YAML Pipelines: Pipeline-as-code, version controlled, recommended approach
  • Classic Pipelines: Visual designer, UI-based configuration

Key Concepts

  • Trigger: What starts the pipeline (commit, schedule, manual)
  • Stage: Logical division (Build, Test, Deploy)
  • Job: Unit of work running on an agent
  • Step: Individual task or script
  • Agent: Machine that runs the pipeline

YAML Pipeline Basics

Simple Build Pipeline

# azure-pipelines.yml
trigger:
  branches:
    include:
      - main
      - develop

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildJob
    displayName: 'Build Solution'
    steps:
    - task: NuGetToolInstaller@1
      displayName: 'Install NuGet'

    - task: NuGetCommand@2
      displayName: 'Restore NuGet Packages'
      inputs:
        restoreSolution: '$(solution)'

    - task: VSBuild@1
      displayName: 'Build Solution'
      inputs:
        solution: '$(solution)'
        platform: '$(buildPlatform)'
        configuration: '$(buildConfiguration)'

    - task: VSTest@2
      displayName: 'Run Unit Tests'
      inputs:
        platform: '$(buildPlatform)'
        configuration: '$(buildConfiguration)'

    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifacts'
      inputs:
        pathtoPublish: '$(Build.ArtifactStagingDirectory)'
        artifactName: 'drop'

Dynamics 365 CI/CD Pipeline

Power Platform Build Tools

Microsoft provides Power Platform Build Tools for Azure DevOps to automate solution management:

# Dynamics 365 Solution Pipeline
trigger:
  branches:
    include:
      - main

pool:
  vmImage: 'windows-latest'

variables:
  SolutionName: 'MySolution'
  ServiceConnection: 'PowerPlatform-Dev'

stages:
- stage: Export
  displayName: 'Export from Dev'
  jobs:
  - job: ExportSolution
    steps:
    - task: PowerPlatformToolInstaller@2
      displayName: 'Install Power Platform Tools'

    - task: PowerPlatformExportSolution@2
      displayName: 'Export Unmanaged Solution'
      inputs:
        authenticationType: 'PowerPlatformSPN'
        PowerPlatformSPN: '$(ServiceConnection)'
        SolutionName: '$(SolutionName)'
        SolutionOutputFile: '$(Build.ArtifactStagingDirectory)/$(SolutionName).zip'
        Managed: false

    - task: PowerPlatformUnpackSolution@2
      displayName: 'Unpack Solution'
      inputs:
        SolutionInputFile: '$(Build.ArtifactStagingDirectory)/$(SolutionName).zip'
        SolutionTargetFolder: '$(Build.SourcesDirectory)/solutions/$(SolutionName)'
        SolutionType: 'Both'

    - task: PublishBuildArtifacts@1
      displayName: 'Publish Solution Artifact'
      inputs:
        pathtoPublish: '$(Build.ArtifactStagingDirectory)'
        artifactName: 'solution'

- stage: Build
  displayName: 'Build Managed Solution'
  dependsOn: Export
  jobs:
  - job: PackSolution
    steps:
    - task: PowerPlatformToolInstaller@2

    - task: DownloadBuildArtifacts@1
      inputs:
        buildType: 'current'
        downloadType: 'single'
        artifactName: 'solution'

    - task: PowerPlatformPackSolution@2
      displayName: 'Pack as Managed'
      inputs:
        SolutionSourceFolder: '$(Build.SourcesDirectory)/solutions/$(SolutionName)'
        SolutionOutputFile: '$(Build.ArtifactStagingDirectory)/$(SolutionName)_managed.zip'
        SolutionType: 'Managed'

    - task: PublishBuildArtifacts@1
      inputs:
        pathtoPublish: '$(Build.ArtifactStagingDirectory)'
        artifactName: 'managed-solution'

Deployment Pipeline

- stage: DeployTest
  displayName: 'Deploy to Test'
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: DeployToTest
    displayName: 'Deploy to Test Environment'
    environment: 'Test'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerPlatformToolInstaller@2

          - task: PowerPlatformImportSolution@2
            displayName: 'Import Solution'
            inputs:
              authenticationType: 'PowerPlatformSPN'
              PowerPlatformSPN: 'PowerPlatform-Test'
              SolutionInputFile: '$(Pipeline.Workspace)/managed-solution/$(SolutionName)_managed.zip'
              AsyncOperation: true
              MaxAsyncWaitTime: '60'

          - task: PowerPlatformPublishCustomizations@2
            displayName: 'Publish Customizations'
            inputs:
              authenticationType: 'PowerPlatformSPN'
              PowerPlatformSPN: 'PowerPlatform-Test'

- stage: DeployProd
  displayName: 'Deploy to Production'
  dependsOn: DeployTest
  condition: succeeded()
  jobs:
  - deployment: DeployToProd
    displayName: 'Deploy to Production'
    environment: 'Production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerPlatformToolInstaller@2

          - task: PowerPlatformImportSolution@2
            inputs:
              authenticationType: 'PowerPlatformSPN'
              PowerPlatformSPN: 'PowerPlatform-Prod'
              SolutionInputFile: '$(Pipeline.Workspace)/managed-solution/$(SolutionName)_managed.zip'
              AsyncOperation: true
              MaxAsyncWaitTime: '120'

Service Connections

Power Platform Service Principal

Configure service connections for automated deployments:

  1. Create Azure AD App Registration
  2. Grant Dataverse API permissions
  3. Create Application User in Power Platform Admin Center
  4. Assign appropriate security roles
  5. Create Service Connection in Azure DevOps project settings

Environment Approvals and Gates

Manual Approvals

Configure approval gates for production deployments:

  • Define approvers for each environment
  • Set timeout and approval policies
  • Require multiple approvers for critical environments
  • Email notifications for pending approvals

Automated Gates

  • Azure Monitor alerts: Check for active incidents
  • Work item queries: Ensure all bugs are resolved
  • REST API calls: Custom validation endpoints
  • Azure Policy compliance: Security checks

Variables and Secrets

Variable Groups

Organize variables by environment:

variables:
- group: 'PowerPlatform-Dev-Variables'
- group: 'Common-Variables'
- name: localVariable
  value: 'someValue'

Azure Key Vault Integration

Link variable groups to Azure Key Vault for secure secret management:

  • Store connection strings and API keys in Key Vault
  • Create variable group linked to Key Vault
  • Secrets automatically fetched at runtime
  • Audit access through Key Vault logs

Testing in Pipelines

Unit Testing

- task: VSTest@2
  displayName: 'Run Unit Tests'
  inputs:
    testSelector: 'testAssemblies'
    testAssemblyVer2: |
      **/*Tests.dll
      !**/obj/**
    searchFolder: '$(System.DefaultWorkingDirectory)'
    codeCoverageEnabled: true
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

Solution Checker

Run static analysis on Power Platform solutions:

- task: PowerPlatformChecker@2
  displayName: 'Run Solution Checker'
  inputs:
    authenticationType: 'PowerPlatformSPN'
    PowerPlatformSPN: '$(ServiceConnection)'
    FilesToAnalyze: '$(Build.ArtifactStagingDirectory)/*.zip'
    RuleSet: 'Solution Checker'

Best Practices

Pipeline Design

  • Use YAML pipelines for version control
  • Keep pipelines DRY with templates
  • Implement meaningful stage/job names
  • Add appropriate timeout values
  • Use conditions to control execution flow

Security

  • Never store secrets in YAML files
  • Use service principals with minimal permissions
  • Enable branch policies for pipeline changes
  • Review pipeline runs for unexpected behavior
  • Rotate credentials regularly

Performance

  • Cache dependencies between runs
  • Parallelize independent jobs
  • Use appropriate agent sizes
  • Skip unnecessary steps with conditions
  • Archive artifacts selectively

Conclusion

Azure Pipelines provides a robust platform for implementing CI/CD for Dynamics 365 and Power Platform solutions. By automating the build, test, and deployment process, teams can deliver changes faster with greater confidence. Start with a simple pipeline and gradually add stages, tests, and approvals as your process matures.

Need Help with Your Dynamics 365 Project?

Our team of experts can help you set up CI/CD pipelines for your Power Platform and Dynamics 365 solutions.