Scripts/ExportSolution.ps1
# ExportSolution.ps1 function Get-DataverseSolution { Param( [string] [Parameter(Mandatory = $true)] $StartPath, [string] [Parameter(Mandatory = $true)] $SelectedSolution ) try { $SolutionName = $SelectedSolution ######################## EXPORT SOLUTION ######################## # If patch version numbers can change, get existing values if ($global:devops_projectFile.IncrementLatestPatchOnExport -eq "True") { # Get current solution versions in files before updating them try { $versionsFile = Get-Content -Path $global:devops_projectLocation\$global:devops_SolutionName\$global:devops_SolutionName.version -ErrorAction SilentlyContinue | ConvertFrom-Json # Sort by version $existingPatchVersions = $versionsFile | Sort-Object { [version]$_.Version } } catch { #Legacy Solution Packaging Support $versionsFile = Get-Content -Path $PipelinePath\$SolutionFolder\$versionFile $existingPatchVersions = @([ordered]@{SolutionName = $package.SolutionName; Version = $versionsFile ; }) } } # Update version file Set-DataverseSolutionVersion # Delete any files in old formats / file structures that still exist from Microsoft.PowerPlatform.DevOps Remove-Item (Join-Path $StartPath "\dataverse_$SolutionName") -Force -Recurse -ErrorAction Ignore Remove-Item (Join-Path $StartPath "\dataverse_*patch*") -Force -Recurse -ErrorAction Ignore Remove-Item (Join-Path $StartPath "\pac_$SolutionName") -Force -Recurse -ErrorAction Ignore Remove-Item (Join-Path $StartPath "\pac_*patch*") -Force -Recurse -ErrorAction Ignore $patchFilesFolderPath = (Join-Path $StartPath "Patches\") $deployFilesFolderPath = (Join-Path $StartPath "Deploy\") $patchSolutionNames = @() # If there are no patches if (!$PatchQuery.CrmRecords) { # Delete any patch files Remove-Item $patchFilesFolderPath -Force -Recurse -ErrorAction Ignore Remove-Item $deployFilesFolderPath -Force -Recurse -ErrorAction Ignore # Export base solution Unpack-Solution "$SolutionName" -IsPatchExport $false } else { # Export Patches # If project config says to increment latest patch if ($global:devops_projectFile.IncrementLatestPatchOnExport -eq "True") { Write-Host "Exporting all patches with changed version numbers" $patchCount = $PatchQuery.CrmRecords.Count $iterator = 1 foreach ($PatchSolution in $PatchQuery.CrmRecords) { $patchSolutionNames += $PatchSolution.uniquename $existingPatch = $existingPatchVersions | Where-Object { $PatchSolution.uniquename -eq $_.SolutionName } # If version number in CRM is different to existing file if ([version]$existingPatch[0].Version -eq [version]$PatchSolution.version) { Write-Host "Skipping patch $iterator of $patchCount due to unchanged version number: $($PatchSolution.uniquename)" } else { Write-Host "Exporting patch $iterator of $patchCount" # Remove the managed and unmanaged zip files Remove-Item -Path (Join-Path $deployFilesFolderPath "$($PatchSolution.uniquename).zip") -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path $deployFilesFolderPath "$($PatchSolution.uniquename)_managed.zip") -Force -ErrorAction SilentlyContinue # Export and unpack Unpack-Solution "$($PatchSolution.uniquename)" -IsPatchExport $true } $iterator += 1 } } # Else (patches have static versions) else { foreach ($PatchSolution in $PatchQuery.CrmRecords) { $patchSolutionNames += $PatchSolution.uniquename # Export and unpack Unpack-Solution "$($PatchSolution.uniquename)" -IsPatchExport $true } } # Delete old patch files $exportedPatchSolutionNames = Get-ChildItem -Path $patchFilesFolderPath -Directory | Select-Object -ExpandProperty Name $filteredPatchSolutionNames = $exportedPatchSolutionNames | Where-Object { $patchSolutionNames -notcontains $_ } foreach ($patchSolutionName in $filteredPatchSolutionNames) { Write-Host "Deleting patch: $patchSolutionName" # Remove the folder and its contents Remove-Item -Path (Join-Path $patchFilesFolderPath $patchSolutionName) -Recurse -Force -ErrorAction SilentlyContinue # Remove the managed and unmanaged zip files Remove-Item -Path (Join-Path $deployFilesFolderPath "$patchSolutionName.zip") -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path $deployFilesFolderPath "$($patchSolutionName)_managed.zip") -Force -ErrorAction SilentlyContinue Write-Host "Deleted patch: $patchSolutionName" } } Get-FlowsToBeDeployed "$StartPath" $patchSolutionNames Get-ExportDataValid } catch { Write-Host $_ pause } finally { } } function Unpack-Solution { Param( [string] [Parameter(Mandatory = $true)] $ExportSolutionName, [bool] [Parameter(Mandatory = $true)] $IsPatchExport = $false ) try { $pacExePath = "$env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe" $deployFilesFolderPath = (Join-Path $StartPath "Deploy\") # Define the full path for the exported ZIP file $unmanagedExportedZipFilePath = Join-Path $deployFilesFolderPath "$ExportSolutionName.zip" Write-Host "Unmanaged solution file name: $unmanagedExportedZipFilePath" if (!(Test-Path -Path $unmanagedExportedZipFilePath)) { # Export the unmanaged solution to a ZIP file $unmanagedExportCommand = "solution export -n $ExportSolutionName -p $deployFilesFolderPath --managed false --async --max-async-wait-time 120" Write-Host "Running export command: $pacExePath $unmanagedExportCommand" & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution export -n $ExportSolutionName -p $deployFilesFolderPath --managed false --async --max-async-wait-time 120 # Export the managed solution to a ZIP file $managedExportCommand = "solution export -n $ExportSolutionName -p $deployFilesFolderPath --managed true --async --max-async-wait-time 120" Write-Host "Running export command: $pacExePath $managedExportCommand" & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution export -n $ExportSolutionName -p $deployFilesFolderPath --managed true --async --max-async-wait-time 120 # Check if the export was successful if (Test-Path -Path $unmanagedExportedZipFilePath) { Write-Host "Solution exported successfully: $unmanagedExportedZipFilePath" # If $IsPatchExport unpack to Patches folder. Otherwise unpack to src folder if ($IsPatchExport) { Write-Host "Patch solution $ExportSolutionName exported" $destinationFolderPath = (Join-Path $StartPath "Patches\$ExportSolutionName\") } else { Write-Host "Full solution exported" Remove-Item (Join-Path $StartPath "src\.") -Force -Recurse -ErrorAction Ignore $destinationFolderPath = (Join-Path $StartPath "src\") } Write-Host "Unpacking to destination folder path - " $destinationFolderPath # Unpack the solution (extract the content) $unpackCommand = "solution unpack --zipfile $unmanagedExportedZipFilePath --folder $destinationFolderPath --packagetype Both --processCanvasApps true" Write-Host "Running unpack command: $pacExePath $unpackCommand" & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution unpack --zipfile $unmanagedExportedZipFilePath --folder $destinationFolderPath --packagetype Both --processCanvasApps true } else { Write-Host "Solution export of $ExportSolutionName failed!" } } } catch { Write-Host $_ pause } } function Get-FlowsToBeDeployed { Param( [string] [Parameter(Mandatory = $true)] $StartPath, [array] [Parameter(Mandatory = $false)] $patchSolutionNames ) try { Write-Host "Generating Flows_Default.json for activating post-deploy" $SolutionPath = (Join-Path $StartPath "src\Workflows") $FlowJSON = @() $AddedFlows = @() $Workflows = Get-ChildItem -Path $SolutionPath -Filter *.json -ErrorAction SilentlyContinue if ($Workflows) { $Workflows | ForEach-Object { $FlowName = $_.BaseName.SubString(0, $_.BaseName.Length - 36) $FlowID = $_.BaseName.Replace($FlowName, '') $FlowJSON += @([ordered]@{FlowID = $FlowID; FlowName = $FlowName; ActivateAsUser = ""; }) $AddedFlows += $FlowID } } # If there are patches to check too if ($patchSolutionNames.Count -gt 0) { foreach ($PatchName in $patchSolutionNames) { $SolutionPath = (Join-Path $StartPath "Patches\$PatchName\Workflows") $PatchesFlowJSON = @() $Workflows = Get-ChildItem -Path $SolutionPath -Filter *.json -ErrorAction SilentlyContinue if ($Workflows) { $Workflows | ForEach-Object { $FlowName = $_.BaseName.SubString(0, $_.BaseName.Length - 36) $FlowID = $_.BaseName.Replace($FlowName, '') # If the flow isn't already in the list, add it if ($AddedFlows -notcontains $FlowID) { $FlowJSON += @([ordered]@{FlowID = $FlowID; FlowName = $FlowName; ActivateAsUser = ""; }) $AddedFlows += $FlowID } } } } } if ($FlowJSON) { ConvertTo-Json -Depth 3 $FlowJSON | Format-Json | Out-FileUtf8NoBom $StartPath\Flows_Default.json } } catch { Write-Host $_ pause } } |