Scripts/SolutionDeploy.ps1
# # SolutionDeploy.ps1 # function Deploy-Solution { Param( [string] [Parameter(Mandatory = $true)] $DeployServerUrl, [string] [Parameter(Mandatory = $true)] $UserName, [string] [Parameter(Mandatory = $false)] $Password = "", [string] [Parameter(Mandatory = $true)] $PipelinePath, [bool] [Parameter(Mandatory = $false)] $UseClientSecret = $false, [bool] [Parameter(Mandatory = $false)] $RunLocally = $false, [string] [Parameter(Mandatory = $false)] $EnvironmentName = $env:ENVIRONMENT_NAME ) ######################## SETUP . "$PSScriptRoot\..\Private\_SetupTools.ps1" Install-PAC if (!$RunLocally) { Write-Host "Preparing local run" Install-ConfigMigrationModule Install-XrmModule } function Import-Package { #[string]$PackageDirectory = "$PipelinePath/drop/PackageDeployer/bin/Release" #[string]$LogsDirectory = "$PackageDirectory" [string]$LogsDirectory = $PipelinePath if ($UseClientSecret) { #(New-Object PSCredential "user", $clientKeySS).GetNetworkCredential().Password [string]$CrmConnectionString = "AuthType=ClientSecret;Url=$DeployServerUrl;ClientId=$UserName;ClientSecret=$Password" } else { [string]$CrmConnectionString = "AuthType=OAuth;Username=$UserName;Password=$Password;Url=$DeployServerUrl;AppId=51f81489-12ee-4a9e-aaae-a2591f45987d;RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97;LoginPrompt=never" #Need to replace AppId and RedirectUri from Library values } #Write-Host $PackageDirectory Write-Host $LogsDirectory $Packages = Get-Content "$PipelinePath\deployPackages.json" | ConvertFrom-Json Write-Host "##[section] Creating CRM connection" $CRMConn = Get-CrmConnection -ConnectionString $CrmConnectionString -Verbose #-MaxCrmConnectionTimeOutMinutes 10 #Set-CrmConnectionTimeout -conn $CRMConn -TimeoutInSeconds 600 if ($false -eq $CRMConn.IsReady) { Write-Error "An error occurred: " $CRMConn.LastCrmError Write-Error $CRMConn.LastCrmException.Message Write-Error $CRMConn.LastCrmException.Source Write-Error $CRMConn.LastCrmException.StackTrace throw "Could not establish connection with server" } foreach ($package in $Packages) { $anyFailuresInImport = $false; $Deploy = $package.DeployTo | Where-Object { $_.EnvironmentName -eq $EnvironmentName } if ($null -ne $Deploy) { Write-Host "Deployment step manifest" Write-Host $Deploy $PSolution = $package.SolutionName Write-Host "##[group] Preparing Deployment for $PSolution" If ($Deploy.DeploymentType -eq "Unmanaged") { Write-Host "##[section] Switching $PSolution Solution to Unmanaged" # $folder = ($_.solutionpackagefilename).Replace("_managed.zip", "").Replace(".zip", "") # $newFileName = ($_.solutionpackagefilename).Replace("_managed", "") $fileToPack = "$($envName)_$($PSolution).zip" # $_.solutionpackagefilename = $fileToPack $packageFolder = "dataverse_$($PSolution)" Write-Host "##[command] Packing Unmanaged Solution $PSolution" #Checking for Canvas App $canvasApps = Get-ChildItem -Path $PipelinePath\$PSolution\$packageFolder\CanvasApps\ -Directory -ErrorAction SilentlyContinue # pack canvas apps $canvasApps | ForEach-Object { Write-Host "Packing Canvas App $($_.name)"; & $env:APPDATA\Microsoft.PowerPlatform.DevOps\PACTools\tools\pac.exe canvas pack --msapp $_.DirectoryName.msapp --sources $_.FullName } & $env:APPDATA\Microsoft.PowerPlatform.DevOps\PACTools\tools\pac.exe solution pack -f $PipelinePath\$PSolution\$packageFolder -z $PipelinePath\$PSolution\$fileToPack -p Unmanaged } else { Write-Host "##[section] Switching $PSolution Solution to Managed" # $folder = ($_.solutionpackagefilename).Replace("_managed.zip", "").Replace(".zip", "") $fileToPack = "$($envName)_$($PSolution)_managed.zip" # $_.solutionpackagefilename = $fileToPack $packageFolder = "dataverse_$($PSolution)" Write-Host "##[command] Packing Managed Solution $PSolution" #Checking for Canvas App <# $canvasApps = Get-ChildItem -Path $PipelinePath\$PSolution\$packageFolder\CanvasApps\ -Directory -ErrorAction SilentlyContinue # pack canvas apps $canvasApps | ForEach-Object { Write-Host "Packing Canvas App $($_.name)"; & $env:APPDATA\Microsoft.PowerPlatform.DevOps\PACTools\tools\pac.exe canvas pack --msapp "$($_.FullName).msapp" --sources $_.FullName Remove-Item $_.FullName -Recurse -ErrorAction SilentlyContinue } #> & $env:APPDATA\Microsoft.PowerPlatform.DevOps\PACTools\tools\pac.exe solution pack -f $PipelinePath\$PSolution\$packageFolder -z $PipelinePath\$PSolution\$fileToPack -p Managed -same } if ($Deploy.PreAction -eq $true) { Write-Host "##[section] Execute Pre Action" Write-Host "$PipelinePath\drop\$PFolder\bin\release\Scripts" . $PipelinePath\drop\$PFolder\bin\release\Scripts\PreAction.ps1 -Conn $CRMConn -EnvironmentName $Deploy.EnvironmentName -Path "$PipelinePath\drop\$PFolder\bin\release\" } Write-Host "##[section] Importing package" $skipDeploy = $false try { $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $error.Clear() Write-Host "##[section] Deploying $($package.SolutionName) as $($Deploy.DeploymentType) to - $EnvironmentName" #Get Currently Deployed Solution Version Write-Host "Getting Current Solution Version from Target" $SolutionQuery = Get-CrmRecords -conn $CRMConn -EntityLogicalName solution -Fields 'solutionid','friendlyname', 'version', 'uniquename' -FilterAttribute uniquename -FilterOperator eq -FilterValue $($package.SolutionName) $Solution = $SolutionQuery.CrmRecords[0] if (!$Solution) { $deployAsHolding = $false; Write-Host "Solution not found in Target, Importing as New" } else { $SolutionVersion = $Solution.version Write-Host "Found: $SolutionVersion in $EnvironmentName" if ($null -ne $Deploy.DeployAsHolding) { $deployAsHolding = $Deploy.DeployAsHolding [System.Convert]::ToBoolean($deployAsHolding) } else { $deployAsHolding = $false } } Write-Host "Getting Version to be Deployed..." $deployingVersion = Get-Content -Path $PipelinePath\$PSolution\$PSolution.version Write-Host "Version to be deployed : $deployingVersion" if ($deployingVersion -le $SolutionVersion) { $skipDeploy = $true; Write-Host "Skipping Deployment as Target has same or newer" } #if ($RunLocally) { # Write-Host "Skipping version checking for Local Deployment run" # $skipDeploy = $false; #run locally regardless of version number #} if (!$skipDeploy) { $activatePlugIns = $true; $overwriteUnManagedCustomizations = $true; $skipDependancyOnProductUpdateCheckOnInstall = $true; $isInternalUpgrade = $true; Write-Host "Initiating Import and deployment to $($DeployServerUrl)" Write-Host "Import as Holding solution : $($deployAsHolding)" $importId = [guid]::Empty $result = $CRMConn.ImportSolutionToCrmAsync("$PipelinePath\$PSolution\$fileToPack", [ref]$importId, $activatePlugIns, $overwriteUnManagedCustomizations, $skipDependancyOnProductUpdateCheckOnInstall, $deployAsHolding, $isInternalUpgrade) Write-Host Async Operation ID: $result Write-Host Import Job ID: $importId do { $operation = Get-CrmRecord -conn $CRMConn -EntityLogicalName asyncoperation -Id ($result) -Fields name, statuscode, friendlymessage, completedon, errorcode [int]$statuscode = $operation.statuscode_Property.value.Value; if ($statuscode -le 30) { $job = Get-CrmRecord -conn $CRMConn -EntityLogicalName importjob -Id ($importId) -Fields progress Write-Host "Polling Import for Solution: $($PSolution) : $($operation.statuscode) - $($job.progress)%" $anyFailuresInImport = $false; Start-Sleep -Seconds 5 } elseif ($statuscode -eq 31 -or $statuscode -eq 32) { Write-Error "##[error]: Unable to import solution - please check Solution import history in https://make.powerapps.com/environments" Write-Warning "##[warning] Import Failed: $($operation.statuscode)" Write-Warning "##[warning] Error Code: $($operation.errorcode)" Write-Warning "##[warning] $($operation.friendlymessage)" $anyFailuresInImport = $true; } } until ($statuscode -eq 30 -or $statuscode -eq 31 -or $statuscode -eq 32) if ($deployAsHolding -eq $true -and $anyFailuresInImport -eq $false) { Write-Host "Applying Upgrade to Solution" $promoteRequestId = $CRMConn.DeleteAndPromoteSolutionAsync($PSolution); if (($null -eq $promoteRequestId) -or ($promoteRequestId -eq [Guid]::Empty)) { Write-Error "##[error]: Unable to promote or delete solution - please check Solution import history in https://make.powerapps.com/environments" $anyFailuresInImport = $true; } else { Write-Host Async Operation ID: $promoteRequestId do { $operation = Get-CrmRecord -conn $CRMConn -EntityLogicalName asyncoperation -Id ($promoteRequestId) -Fields name, statuscode, friendlymessage, completedon, errorcode [int]$statuscode = $operation.statuscode_Property.value.Value; if ($statuscode -le 30) { #$Jobs= (Get-CrmRecordsByFetch -conn $CRMConn -Fetch ' #<fetch count="1"><entity name="importjob"><attribute name="importjobid" /><attribute name="progress" /><attribute name="solutionname" /> # <filter type="and"><condition attribute="solutionname" operator="eq" value="CICDDemoSolution" /></filter></entity></fetch>').CrmRecords # $job = $Jobs[0]; Write-Host "Polling Promotion status for Solution: $($PSolution) : $($operation.statuscode)" $anyFailuresInImport = $false; Start-Sleep -Seconds 5 } elseif ($statuscode -eq 31 -or $statuscode -eq 32) { Write-Error "##[error]: Unable to promote or delete solution - please check Solution import history in https://make.powerapps.com/environments" Write-Warning "##[warning] Delete and Promote Failed: #($operation.statuscode)" Write-Warning "##[warning] Error Code: $($operation.errorcode)" Write-Warning "##[warning] $($operation.friendlymessage)" $anyFailuresInImport = $true; } }until($statuscode -eq 30 -or $statuscode -eq 31 -or $statuscode -eq 32) } } } [int]$elapsedTime = $stopwatch.Elapsed.TotalMinutes $stopwatch.Stop() Write-Host "##[section] Import Complete in $($elapsedTime) minutes" } catch { Write-Error "##[error]:$($_)" Write-Host "##[section] Skipping $PSolution due to Solution import error" } If ($Deploy.DeployData -eq $true -and $anyFailuresInImport -eq $true) { Write-Host "##[group] Importing reference Data ..." try { if (Test-Path -Path $PipelinePath\$PSolution\ReferenceData\data.zip) { Import-CrmDataFile -CrmConnection $CRMConn -DataFile $PipelinePath\$PSolution\ReferenceData\data.zip -EnabledBatchMode -Verbose } else { Write-Host "Config Data file does not Exist" } } catch { Write-Host $_ } } else { Write-Host "##[section] No Data to Import for $PSolution" } if ($Deploy.PostAction -eq $true -and $anyFailuresInImport -eq $true) { Write-Host "##[section] Execute Post Action" Write-Host "$PipelinePath\drop\$PFolder\bin\release\Scripts" . $PipelinePath\drop\$PFolder\bin\release\Scripts\PostAction.ps1 -Conn $CRMConn -EnvironmentName $Deploy.EnvironmentName -Path "$PipelinePath\drop\$PFolder\bin\release\" } } else { Write-Host "##[warning] $($package.SolutionName) is not configured for deployment to $env:ENVIRONMENT_NAME in deployPackages.json" } Write-Host "##[endgroup]" Write-Host "##[endgroup]" } } Write-Host Environment $EnvironmentName Import-Package } |