Skip to main content

Pipeline Integration

Azure DevOps Pipeline

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

pool:
vmImage: 'ubuntu-latest'

variables:
- group: 'FlowOn-Credentials'

stages:
- stage: Build
jobs:
- job: Export
steps:
- task: UseDotNet@2
inputs:
version: '9.0.x'

- script: dotnet tool install --global FlowOn.Xrm.Tools
displayName: 'Install FlowOn Tools'

- script: |
flowon export \
--solution "$(SolutionName)" \
--project "$(ProjectName)" \
--output "$(Build.ArtifactStagingDirectory)" \
--managed \
--unmanaged \
--include-data \
--data-spec "./specs/data-spec.xml" \
--connection "$(DevConnectionString)"
displayName: 'Export Artifacts'

- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'flowon-artifacts'

- stage: DeployUAT
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
jobs:
- deployment: DeployToUAT
environment: 'UAT'
strategy:
runOnce:
deploy:
steps:
- task: UseDotNet@2
inputs:
version: '9.0.x'

- script: dotnet tool install --global FlowOn.Xrm.Tools
displayName: 'Install FlowOn Tools'

- script: |
flowon import \
--solution "$(Pipeline.Workspace)/flowon-artifacts/solutions/*_managed.zip" \
--package "$(Pipeline.Workspace)/flowon-artifacts/flowon/*.flop" \
--data "$(Pipeline.Workspace)/flowon-artifacts/data" \
--mappings "./mappings/uat" \
--apply-mappings \
--publish-customizations \
--connection "$(UATConnectionString)"
displayName: 'Deploy to UAT'

- stage: DeployProduction
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToProduction
environment: 'Production'
strategy:
runOnce:
deploy:
steps:
- task: UseDotNet@2
inputs:
version: '9.0.x'

- script: dotnet tool install --global FlowOn.Xrm.Tools
displayName: 'Install FlowOn Tools'

- script: |
flowon disable-plugins \
--project "$(ProjectName)" \
--all \
--connection "$(ProdConnectionString)"
displayName: 'Disable Plugins'

- script: |
flowon import \
--solution "$(Pipeline.Workspace)/flowon-artifacts/solutions/*_managed.zip" \
--package "$(Pipeline.Workspace)/flowon-artifacts/flowon/*.flop" \
--data "$(Pipeline.Workspace)/flowon-artifacts/data" \
--mappings "./mappings/production" \
--apply-mappings \
--publish-customizations \
--connection "$(ProdConnectionString)"
displayName: 'Deploy to Production'

- script: |
flowon enable-plugins \
--project "$(ProjectName)" \
--all \
--connection "$(ProdConnectionString)"
displayName: 'Enable Plugins'

GitHub Actions

# .github/workflows/deploy.yml
name: FlowOn CI/CD

on:
push:
branches: [main, develop]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Install FlowOn Tools
run: dotnet tool install --global FlowOn.Xrm.Tools

- name: Export Artifacts
run: |
flowon export \
--solution "${{ vars.SOLUTION_NAME }}" \
--project "${{ vars.PROJECT_NAME }}" \
--output "./artifacts" \
--managed \
--include-data \
--data-spec "./specs/data-spec.xml" \
--connection "${{ secrets.DEV_CONNECTION_STRING }}"

- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: flowon-artifacts
path: ./artifacts

deploy-uat:
needs: build
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
environment: UAT
steps:
- uses: actions/checkout@v4

- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: flowon-artifacts
path: ./artifacts

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Install FlowOn Tools
run: dotnet tool install --global FlowOn.Xrm.Tools

- name: Deploy to UAT
run: |
flowon import \
--solution "./artifacts/solutions/*_managed.zip" \
--package "./artifacts/flowon/*.flop" \
--mappings "./mappings/uat" \
--apply-mappings \
--publish-customizations \
--connection "${{ secrets.UAT_CONNECTION_STRING }}"

deploy-production:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: Production
steps:
- uses: actions/checkout@v4

- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: flowon-artifacts
path: ./artifacts

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Install FlowOn Tools
run: dotnet tool install --global FlowOn.Xrm.Tools

- name: Deploy to Production
run: |
flowon import \
--solution "./artifacts/solutions/*_managed.zip" \
--package "./artifacts/flowon/*.flop" \
--mappings "./mappings/production" \
--apply-mappings \
--publish-customizations \
--connection "${{ secrets.PROD_CONNECTION_STRING }}"

Pipeline Variables and Secrets

Azure DevOps Variable Groups

Create a variable group named FlowOn-Credentials with:

VariableDescriptionSecret
DevConnectionStringDev environment connection stringYes
UATConnectionStringUAT environment connection stringYes
ProdConnectionStringProduction environment connection stringYes
SolutionNameDynamics 365 solution nameNo
ProjectNameFlowOn project nameNo

GitHub Secrets

Configure these secrets in your repository settings:

SecretDescription
DEV_CONNECTION_STRINGDev environment connection string
UAT_CONNECTION_STRINGUAT environment connection string
PROD_CONNECTION_STRINGProduction environment connection string

Configure these variables:

VariableDescription
SOLUTION_NAMEDynamics 365 solution name
PROJECT_NAMEFlowOn project name

Environment Protection

Azure DevOps Environments

Configure environment approvals in Azure DevOps:

  1. Go to Pipelines > Environments
  2. Create environments: UAT, Production
  3. Add approval checks for Production

GitHub Environments

Configure environment protection in GitHub:

  1. Go to Settings > Environments
  2. Create environments: UAT, Production
  3. Add required reviewers for Production
  4. Configure deployment branches