Hello!

As part of the npm package provided by Microsoft, there is a PowerShell script called PrePostDeployment script. This script very helpfully sorts out the ADF prior to the ARM tempalte being deployed.

This script however is not without its problems. Firstly when it attempts to stop triggers it does so by getting a list of all those that are not stopped. This line used to not include the -and $_.RuntimeState -ne 'Stopped' operand, so it is an improvement, but it can be improved further by retruning only those that are started

This is the offending line…

$triggersToStop = $triggersDeployed | Where-Object { $_.Name -in $triggerNamesInTemplate -and $_.RuntimeState -ne 'Stopped' }

…which would return only those we wish to stop by altering the operand to returning only those started…

$triggersToStop = $triggersDeployed | Where-Object { $_.Name -in $triggerNamesInTemplate -and $_.RuntimeState -eq 'Started' }

…this is a minor change, but could save quite a bit of time when only stopping thsoe triggers that are already started, as opposed to trying to stop triggers that are disabled.

Another very minor issue which troubles me is the fact that the Start-Sleep for waiting for triggers status to change is 15 seconds. This adds up, and weould be much better if it was reduced to 5 or even 3 seconds. I appreciate that multiple calls to Azure can cause issues itself, however there’s an argument to be said for taking up valuable AzDo Agent time by waiting in a sleep cycle for an egregious length of time.

These two issues, small as they, only really affect the time taken to run the script. But the last issue is one that worries me the most: it is to do with the deletion of the deployment entry in the deployment registry.

Deleting a successful ARM template deployment from the deployment registry on a Resource Group is a smart thing to do as the registry can become bloated and even run out of space, espeically if you are using the same Resource Group to create Sandbox-type environments.

What isn’t particularly smart however is the way in which the deployment entry is searched for:

        if ($DeleteDeployment -eq $true) {
            Write-Host "Deleting ARM deployment ... under resource group: $ResourceGroupName"
            $deployments = Get-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName
            $deploymentsToConsider = $deployments | Where-Object { $_.DeploymentName -like "ArmTemplate_master*" -or $_.DeploymentName -like "ArmTemplateForFactory*" } | Sort-Object -Property Timestamp -Descending
            $deploymentName = $deploymentsToConsider[0].DeploymentName

            Write-Host "Deployment to be deleted: $deploymentName"
            $deploymentOperations = Get-AzResourceGroupDeploymentOperation -DeploymentName $deploymentName -ResourceGroupName $ResourceGroupName
            $deploymentsToDelete = $deploymentOperations | Where-Object { $_.properties.targetResource.id -like "*Microsoft.Resources/deployments*" }

            $deploymentsToDelete | ForEach-Object {
                Write-Host "Deleting inner deployment: $($_.properties.targetResource.id)"
                Remove-AzResourceGroupDeployment -Id $_.properties.targetResource.id
            }
            Write-Host "Deleting deployment: $deploymentName"
            Remove-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -Name $deploymentName
        }

For those not really paying attention, the method here is return all the deployments, find one that has a prefix we’re sort of expecting, and if not that then another one, find the most recent one of those and delete it. This fuzzy logic approach has caused us a fair few problems, particularly when we decided to name our depoyments so that we could use the name to search for them if they failed.

What would make much more sense would be to add the deployment name as a parameter on the script, and if the parameter is included then use that and if not then resort to the logic above, which I’m still not wild about, but including to only consider states that are successful, so at least we won’t delete anything that might not be missed..?

if ($DeleteDeployment -eq $true) { Write-Host “Deleting ARM deployment … under resource group: $ResourceGroupName” if ($null -eq $deploymentName) { $deployments = Get-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName $deploymentsToConsider = $deployments | Where-Object { ($_.DeploymentName -like “ArmTemplate_master*” -or $_.DeploymentName -like “ArmTemplateForFactory*") -and ($_.ProvisioningState -eq ‘Succeeded’) } | Sort-Object -Property Timestamp -Descending $deploymentName = $deploymentsToConsider[0].DeploymentName } Write-Host “Deployment to be deleted: $deploymentName” $deploymentOperations = Get-AzResourceGroupDeploymentOperation -DeploymentName $deploymentName -ResourceGroupName $ResourceGroupName $deploymentsToDelete = $deploymentOperations | Where-Object { $_.properties.targetResource.id -like “*Microsoft.Resources/deployments*” }

$deploymentsToDelete | ForEach-Object {
    Write-Host "Deleting inner deployment: $($_.properties.targetResource.id)"
    Remove-AzResourceGroupDeployment -Id $_.properties.targetResource.id
}
Write-Host "Deleting deployment: $deploymentName"
Remove-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -Name $deploymentName

}

So whinging aside, I did not know until I started writing this blog post that this code is available on GitHub, and that there’s a newer version AND pending changes for running the script faster. My plan is now to abandon using the script that is part of the npm package and to start using the v2 version stored in a repo, then after a while open a PR on the GitHub repo.