src/Workflows/Upsert-XrmCloudFlow.ps1
|
<# .SYNOPSIS Create or update a cloud flow (solution-aware Power Automate flow). .DESCRIPTION Write a cloud flow (workflow, category 5) with a caller-controlled Id, so the Id stays the same across environments. An activated flow is turned off, written, then turned on again. With Activate, the flow is also turned on when it was off or new. With SolutionUniqueName, the flow is added to the solution (idempotent). Raises an error when the Id belongs to a process that is not a cloud flow, or when the flow cannot be turned on again (it then stays off). .PARAMETER XrmClient Xrm connector initialized to target instance. Use latest one by default. (Dataverse ServiceClient) .PARAMETER Id Flow unique identifier (workflowid). .PARAMETER Name Flow name. .PARAMETER ClientData Flow definition, as stored in the clientdata column (JSON with properties.definition and properties.connectionReferences). .PARAMETER Description Flow description. .PARAMETER SolutionUniqueName Unmanaged solution to add the flow to. .PARAMETER Activate Turn the flow on after writing it, even when it was off or new. .OUTPUTS Microsoft.Xrm.Sdk.EntityReference. Reference of the flow. .EXAMPLE $clientData = Get-Content -Path ".\flows\SyncAccounts.json" -Raw; $flow = Upsert-XrmCloudFlow -XrmClient $xrmClient -Id "5f0e2c1a-7a39-4a57-9d0b-2f1b8c3e4d5a" -Name "Sync accounts" -ClientData $clientData -SolutionUniqueName "MySolution" -Activate; .LINK https://github.com/AymericM78/PowerDataOps/blob/main/documentation/commands/Upsert-XrmCloudFlow.md #> function Upsert-XrmCloudFlow { [CmdletBinding(SupportsShouldProcess)] [OutputType([Microsoft.Xrm.Sdk.EntityReference])] param ( [Parameter(Mandatory = $false, ValueFromPipeline)] [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient] $XrmClient = $Global:XrmClient, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Guid] $Id, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $ClientData, [Parameter(Mandatory = $false)] [AllowEmptyString()] [String] $Description, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $SolutionUniqueName, [Parameter(Mandatory = $false)] [switch] $Activate ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $flowReference = New-XrmEntityReference -LogicalName "workflow" -Id $Id; $existing = $XrmClient | Get-XrmRecord -LogicalName "workflow" -Id $Id -Columns "category", "statecode" -IfExists -AsEntity; $wasActive = $false; if ($existing) { $category = $existing["category"].Value; if ($category -ne 5) { throw "Process '$Id' is not a cloud flow (category $category)."; } $wasActive = $existing["statecode"].Value -eq 1; } $attributes = @{ name = $Name; clientdata = $ClientData }; if ($PSBoundParameters.ContainsKey('Description')) { $attributes["description"] = $Description; } # A failed step stops here: the next ones would act on a flow in an unknown state if ($wasActive) { $XrmClient | Disable-XrmWorkflow -WorkflowReference $flowReference -ErrorAction Stop | Out-Null; } if ($existing) { $XrmClient | Update-XrmRecord -Record (New-XrmEntity -LogicalName "workflow" -Id $Id -Attributes $attributes) -ErrorAction Stop; } else { $attributes["category"] = New-XrmOptionSetValue -Value 5; $attributes["type"] = New-XrmOptionSetValue -Value 1; $attributes["primaryentity"] = "none"; $XrmClient | Add-XrmRecord -Record (New-XrmEntity -LogicalName "workflow" -Id $Id -Attributes $attributes) -ErrorAction Stop | Out-Null; } if ($PSBoundParameters.ContainsKey('SolutionUniqueName')) { $XrmClient | Add-XrmSolutionComponent -SolutionUniqueName $SolutionUniqueName -ComponentId $Id -ComponentType 29 | Out-Null; } if ($wasActive -or $Activate) { try { $XrmClient | Enable-XrmWorkflow -WorkflowReference $flowReference -ErrorAction Stop | Out-Null; } catch { throw "Cloud flow '$Name' ($Id) was written but could not be turned on: $($_.Exception.Message)"; } } $flowReference; } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Upsert-XrmCloudFlow -Alias *; |