Private/Add-CICD.ps1
# _Add-CICD.ps1 function Add-CICDEnvironment { if (!$VerbosePreference -eq "Continue") { Clear-Host } $message = "Configuring CI/CD Environment" Write-Host $message try { $CreateOrSelectEnv = Read-Host -Prompt "CI/CD Environment : Would you like to [P]rovision a new Power Platform Environment ? or [S]elect an Existing One (Default [S])" if ($CreateOrSelectEnv -eq "P") { Add-Environment Invoke-ConfigureCICD } else { Invoke-ConfigureCICD } } catch { $global:devops_projectFile.CICDEnvironmentName = "Error" pause } $global:devops_projectFile | ConvertTo-Json | Out-FileUtf8NoBom ("$global:devops_projectLocation\$global:devops_gitRepo.json") } function Invoke-ConfigureCICD { $scRepo = $global:devops_gitRepo#.Replace(' ', '') $scOrg = $global:devops_projectFile.OrgName $scProject = $global:devops_projectFile.Project $message = "Connecting to Power Platform" Write-Host $message Get-DataverseLogin $connList = Get-AdminPowerAppEnvironment $options = $connList | ForEach-Object { "$($_.DisplayName) ($($_.Internal.properties.linkedEnvironmentMetadata.instanceUrl))" } do { $sel = Invoke-Menu -MenuTitle "---- Please Select your Continuous Deployment Environment ------" -MenuOptions $options $CICDEnvironment = $connList[$sel] $connCICD = Get-DataverseConnection($CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl) } until ($connCICD -ne "") Write-Host $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl $friendlyEnvironmentName = $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.friendlyName -replace '[^a-zA-Z0-9]', '' Write-Host "Adding Environment to Environments.json" ConvertTo-Json -Depth 3 @([ordered]@{EnvironmentName = $friendlyEnvironmentName; EnvironmentURL = $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl; PreAction = "false"; PreFunctions = @(); PostAction = "false"; PostFunctions = @() }) | Format-Json | Out-FileUtf8NoBom .\Environments.json if ($global:devops_DataverseCredType -eq "user") { if (!($global:Password) -or !($global:devops_DataverseEmail)) { Do { $Credentials = Get-Credential -Message "Enter the Credentials the Pipeline should use for Deploying to D365 / CDS" } Until (($Credentials.GetNetworkCredential().UserName -ne "") -and ($Credentials.GetNetworkCredential().Password -ne "")) $username = $Credentials.GetNetworkCredential().UserName $password = $Credentials.GetNetworkCredential().Password } else { $username = $global:devops_DataverseEmail $password = $global:Password } } else { $username = $global:devops_ClientID $password = $global:clientSecret } $message = "Creating variable groups in Azure DevOps" Write-Host $message try { $groups = az pipelines variable-group list --organization https://dev.azure.com/$scOrg --project $scProject | ConvertFrom-Json $varGroupCICD = $groups | where { $_.name -eq "$scRepo.PowerPlatformCICD" } if (!$varGroupCICD) { $varGroupCICD = az pipelines variable-group create --organization https://dev.azure.com/$scOrg --project $scProject --name "$scRepo.PowerPlatformCICD" --variables d365username=$username --authorize $true | ConvertFrom-Json } $vars = az pipelines variable-group variable list --organization https://dev.azure.com/$scOrg --project $scProject --group-id $varGroupCICD.id | ConvertFrom-Json if (!$vars.d365username) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365username --value $username --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365username --value $username --group-id $varGroupCICD.id } if (!$vars.d365password) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365password --value="$password" --secret $true --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365password --value="$password" --secret $true --group-id $varGroupCICD.id } if (!$vars.d365url) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365url --value $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365url --value $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl --group-id $varGroupCICD.id } $message = "Creating Build and Deploy Pipeline in Azure DevOps" Write-Host $message $global:devops_projectFile.CICDEnvironmentName = $CICDEnvironment.DisplayName $global:devops_projectFile.CICDEnvironmentURL = $CICDEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl $global:devops_projectFile.CICDFriendlyName = $friendlyEnvironmentName $global:devops_projectFile.CICDVarGroupID = $varGroupCICD.id $global:devops_projectFile | ConvertTo-Json | Out-FileUtf8NoBom ("$global:devops_projectLocation\$global:devops_gitRepo.json") $buildYAML = Get-Content -Path "$($global:devops_projectLocation)\Build.yaml" if(($buildYAML -Match "$scRepo.PowerPlatformCICD").Length -gt 0) { Write-Host "***----Previous CI/CD Pipeline Stage Entry Detected ----****" Write-Host "From the $global:devops_projectLocation\Build.yaml File, remove the entire 'stage' that contains the group '$scRepo.PowerPlatformCICD'" pause } $azureYAML = Get-Content -Path (Join-Path $PSScriptRoot ..\Snippets\Environment_CICD.yaml) $azureYAML = $azureYAML.Replace('environmentName_safe', $friendlyEnvironmentName) $azureYAML = $azureYAML.Replace('environmentName', $global:devops_projectFile.CICDFriendlyName) $azureYAML = $azureYAML.Replace('replaceRepo', $scRepo) $buildYAML + $azureYAML | Out-FileUtf8NoBom "$($global:devops_projectLocation)\Build.yaml" git add -A git commit -m "Added CICD Environment to Build.yaml" git push origin master $pipelines = az pipelines list --organization https://dev.azure.com/$scOrg --project $scProject --name "$scRepo.CI" | ConvertFrom-Json $pipeline = $pipelines | where { $_.name -eq "$scRepo.CI" } if(!$pipeline) { $pipeline = az pipelines create --organization https://dev.azure.com/$scOrg --project $scProject --name "$scRepo.CI" --yml-path /build.yaml --repository $scRepo --repository-type tfsgit --branch master | ConvertFrom-Json $global:devops_projectFile.CIPipeLineId = $pipeline.definition.id } else { az pipelines update --organization https://dev.azure.com/$scOrg --project $scProject --branch master --id $pipeline.id $global:devops_projectFile.CIPipeLineId = $pipeline.id } $global:devops_projectFile | ConvertTo-Json | Out-FileUtf8NoBom ("$global:devops_projectLocation\$global:devops_gitRepo.json") az pipelines show --organization https://dev.azure.com/$scOrg --project $scProject --id $global:devops_projectFile.CIPipeLineId --open } catch { Write-Host $_ $global:devops_projectFile.CICDEnvironmentName = "Error" $global:devops_projectFile | ConvertTo-Json | Out-FileUtf8NoBom ("$global:devops_projectLocation\$global:devops_gitRepo.json") pause } } function Invoke-ConfigureTargetEnvironment { $scRepo = $global:devops_gitRepo#.Replace(' ', '') $scOrg = $global:devops_projectFile.OrgName $scProject = $global:devops_projectFile.Project $message = "Connecting to Power Platform" Write-Host $message Get-DataverseLogin $connList = Get-AdminPowerAppEnvironment $options = $connList | ForEach-Object { "$($_.DisplayName) ($($_.Internal.properties.linkedEnvironmentMetadata.instanceUrl))" } do { $sel = Invoke-Menu -MenuTitle "---- Please Select your Deployment Environment ------" -MenuOptions $options $TargetEnvironment = $connList[$sel] $connTarget = Get-DataverseConnection($TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl) } until ($connTarget -ne "") Write-Host $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl $friendlyEnvironmentName = $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.friendlyName -replace '[^a-zA-Z0-9]', '' Write-Host "Adding Environment to Environments.json" $environmentsJSON = Get-Content .\Environments.json | ConvertFrom-Json $environmentsJSON += [ordered]@{EnvironmentName = $friendlyEnvironmentName; EnvironmentURL = $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl; PreAction = "false"; PreFunctions = @(); PostAction = "false"; PostFunctions = @() } ConvertTo-Json -Depth 3 $environmentsJSON | Format-Json | Out-FileUtf8NoBom .\Environments.json if ($global:devops_DataverseCredType -eq "user") { if (!($global:Password) -or !($global:devops_DataverseEmail)) { Do { $Credentials = Get-Credential -Message "Enter the Credentials the Pipeline should use for Deploying to D365 / CDS" } Until (($Credentials.GetNetworkCredential().UserName -ne "") -and ($Credentials.GetNetworkCredential().Password -ne "")) $username = $Credentials.GetNetworkCredential().UserName $password = $Credentials.GetNetworkCredential().Password } else { $username = $global:devops_DataverseEmail $password = $global:Password } } else { $username = $global:devops_ClientID $password = $global:clientSecret } $message = "Creating variable groups in Azure DevOps" Write-Host $message try { $groups = az pipelines variable-group list --organization https://dev.azure.com/$scOrg --project $scProject | ConvertFrom-Json $varGroupCICD = $groups | where { $_.name -eq "$scRepo.$friendlyEnvironmentName" } if (!$varGroupCICD) { $varGroupCICD = az pipelines variable-group create --organization https://dev.azure.com/$scOrg --project $scProject --name "$scRepo.$friendlyEnvironmentName" --variables d365username=$username --authorize $true | ConvertFrom-Json } $vars = az pipelines variable-group variable list --organization https://dev.azure.com/$scOrg --project $scProject --group-id $varGroupCICD.id | ConvertFrom-Json if (!$vars.d365username) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365username --value $username --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365username --value $username --group-id $varGroupCICD.id } if (!$vars.d365password) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365password --value="$password" --secret $true --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365password --value="$password" --secret $true --group-id $varGroupCICD.id } if (!$vars.d365url) { az pipelines variable-group variable create --organization https://dev.azure.com/$scOrg --project $scProject --name d365url --value $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl --group-id $varGroupCICD.id } else { az pipelines variable-group variable update --organization https://dev.azure.com/$scOrg --project $scProject --name d365url --value $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.instanceUrl --group-id $varGroupCICD.id } @{"description" = "$friendlyEnvironmentName"; "name" = "$friendlyEnvironmentName" } | ConvertTo-Json | Out-FileUtf8NoBom .\body.json az devops invoke --area distributedtask --resource environments --organization https://dev.azure.com/$scOrg --route-parameters project="$scProject" --in-file .\body.json --http-method post Remove-Item -Path .\body.json -Force $message = "Updating Build and Deploy Pipeline in Azure DevOps" Write-Host $message $buildYAML = Get-Content -Path "$global:devops_projectLocation\Build.yaml" if(($buildYAML -Match "$scRepo.$friendlyEnvironmentName").Length -gt 0) { Write-Host "***----Previous CI/CD Pipeline Stage Entry Detected ----****" Write-Host "From the $global:devops_projectLocation\Build.yaml File, remove the entire 'stage' that contains the group '$scRepo.$friendlyEnvironmentName'" pause } $azureYAML = Get-Content -Path (Join-Path $PSScriptRoot ..\Snippets\Environment_CICD.yaml) $azureYAML = $azureYAML.Replace('environmentName_safe', $friendlyEnvironmentName) $azureYAML = $azureYAML.Replace('environmentName', $TargetEnvironment.Internal.properties.linkedEnvironmentMetadata.friendlyName) $azureYAML = $azureYAML.Replace('replaceRepo', $scRepo) $azureYAML = $azureYAML.Replace('PowerPlatformCICD', $friendlyEnvironmentName) $buildYAML + $azureYAML | Out-FileUtf8NoBom "$global:devops_projectLocation\Build.yaml" } catch { Write-Host $_ $global:devops_projectFile.TargetEnvironmentName = "Error" $global:devops_projectFile | ConvertTo-Json | Out-FileUtf8NoBom ("$global:devops_projectLocation\$global:devops_gitRepo.json") pause } } |