Desarrollar plugins manualmente está bien para proyectos pequeños, pero en equipos con múltiples desarrolladores y entornos (desarrollo, testing, staging, producción), necesitas automatización. CI/CD (Continuous Integration / Continuous Deployment) te permite compilar, probar, y desplegar plugins automáticamente cuando el código cambia.
Objetivos de aprendizaje
- Estructurar un proyecto de plugins para CI/CD
- Configurar pipelines de Azure DevOps para plugins
- Usar Power Platform CLI en automatización
- Implementar autenticación con Service Principal
Por qué CI/CD para plugins
Sin automatización, el proceso típico es:
- El desarrollador compila localmente
- Abre Plugin Registration Tool
- Actualiza el assembly manualmente
- Repite para cada entorno (dev, test, prod)
- Espera que no haya olvidado ningún paso
Este proceso tiene problemas obvios: es lento, propenso a errores humanos, y difícil de auditar. ¿Quién desplegó qué versión a producción? ¿Cuándo? ¿Por qué?
Con CI/CD:
- Cada commit dispara compilación y tests automáticamente
- El despliegue a cada entorno sigue el mismo proceso exacto
- Tienes historial completo de qué se desplegó y cuándo
- Los rollbacks son simples: despliega la versión anterior
Estructura del proyecto
Para CI/CD efectivo, organiza tu repositorio así:
/
├── src/
│ ├── Plugins/
│ │ ├── MiEmpresa.Plugins.csproj
│ │ ├── AccountPlugin.cs
│ │ └── ContactPlugin.cs
│ └── Plugins.Tests/
│ ├── MiEmpresa.Plugins.Tests.csproj
│ ├── AccountPluginTests.cs
│ └── Mocks/
├── solutions/
│ └── MiSolucionPlugins/
│ └── src/
│ ├── PluginAssemblies/
│ ├── SdkMessageProcessingSteps/
│ └── Other/
├── azure-pipelines.yml
├── .gitignore
└── README.md
El directorio solutions/ contiene la solución de Dataverse desempaquetada. Usamos Solution Packager para descomponer la solución en archivos individuales que se versionan bien en Git.
Pipeline de CI/CD básico
El pipeline tiene varias etapas:
Commit → Build → Test → Pack Solution → Deploy to Dev → Integration Tests → Deploy to Staging → Deploy to Prod
Veamos cada etapa en detalle.
Build y Test
trigger:
- main
pool:
vmImage: 'windows-latest'
variables:
buildConfiguration: 'Release'
stages:
- stage: Build
jobs:
- job: BuildAndTest
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '**/*.sln'
- task: MSBuild@1
inputs:
solution: 'src/Plugins/MiEmpresa.Plugins.csproj'
configuration: '$(buildConfiguration)'
msbuildArguments: '/p:SignAssembly=true'
- task: VSTest@2
inputs:
testSelector: 'testAssemblies'
testAssemblyVer2: 'src/Plugins.Tests/bin/$(buildConfiguration)/*.Tests.dll'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: 'src/Plugins/bin/$(buildConfiguration)'
ArtifactName: 'plugins'
Deploy con Power Platform CLI
- stage: DeployToDev
dependsOn: Build
jobs:
- job: Deploy
steps:
- task: DownloadBuildArtifacts@0
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'plugins'
- task: PowerShell@2
displayName: 'Install Power Platform CLI'
inputs:
targetType: 'inline'
script: |
dotnet tool install --global Microsoft.PowerApps.CLI.Tool
- task: PowerShell@2
displayName: 'Authenticate and Deploy'
inputs:
targetType: 'inline'
script: |
pac auth create --url $(DataverseUrl) `
--applicationId $(AppId) `
--clientSecret $(ClientSecret) `
--tenant $(TenantId)
# Empaquetar solución con el plugin actualizado
pac solution pack --zipfile solution.zip `
--folder solutions/MiSolucionPlugins/src
# Importar solución
pac solution import --path solution.zip
# Publicar
pac solution publish
env:
DataverseUrl: $(DataverseDevUrl)
AppId: $(ServicePrincipalAppId)
ClientSecret: $(ServicePrincipalSecret)
TenantId: $(AzureTenantId)
Autenticación con Service Principal
Los pipelines no pueden usar credenciales interactivas. Necesitas un Service Principal (Application User) que autentica automáticamente.
Configuración paso a paso
1. Registrar aplicación en Azure AD:
- Azure Portal → App registrations → New registration
- Nombre: "Pipeline Dataverse Deploy"
- Redirect URI: dejarlo vacío (no es una app interactiva)
- Guarda el Application (client) ID y Directory (tenant) ID
2. Crear secret:
- En la aplicación → Certificates & secrets
- New client secret
- Guarda el valor (solo visible una vez)
3. Crear Application User en Dataverse:
- Admin center → Environments → tu entorno → Settings → Users + permissions → Application users
- New app user
- Selecciona la aplicación que registraste
- Asigna Business Unit y Security Roles (normalmente System Administrator para despliegues)
4. Configurar secrets en Azure DevOps:
- Project settings → Pipelines → Variable groups (o Library)
- Crea variables para AppId, ClientSecret, TenantId, DataverseUrl
- Marca ClientSecret como secret (oculto en logs)
Solution Packager para control de versiones
Las soluciones de Dataverse son archivos ZIP. No se versionan bien en Git. Solution Packager las descompone:
# Desempaquetar una solución exportada
pac solution unpack --zipfile MiSolucion.zip --folder solutions/MiSolucion/src
# Empaquetar para importar
pac solution pack --folder solutions/MiSolucion/src --zipfile MiSolucion.zip
Después de desempaquetar ves archivos individuales para cada componente: plugins, steps, entities, forms. Cada cambio aparece como diff en Git, facilitando code reviews.
Puntos clave
- CI/CD automatiza compilación, testing, y despliegue de plugins
- Power Platform CLI (pac) es la herramienta principal para automatización
- Service Principal permite autenticación sin credenciales interactivas
- Solution Packager descompone soluciones para versionado en Git
- Usa Variable Groups para gestionar secrets de forma segura