Problem Statement
I have a pipeline which goes something like this:
- Deploy a new app service using an ARM template
- Deploy a zip artifact to that app service
More often than not, the second step fails with the following message when running the pipeline for the first time:
##[error]Error: Resource 'my-function-app' doesn't exist. Resource should exist before deployment.
If I "re-run failed jobs" or simply run the pipeline again, then the pipeline will succeed. This suggests to me that this isn't an issue with the values I am providing in the pipeline; but is something to do with the timing of the second stage.
Additional Details
- I am only deploying to a single location; North Europe
- I am deploying to a linux app service plan with SKU P1V3 (although I have noticed this issue with every SKU I have used to date)
- I am not currently using deployment slots
- The app service ARM template is deployed in the pipeline like this:
- task: AzureResourceManagerTemplateDeployment@3 name: DeployFunctionAppARM displayName: 'Deploy Function App ARM' inputs: deploymentScope: Resource Group azureResourceManagerConnection: ${{ variables.serviceConnection }} subscriptionId: ${{ variables.azureSubscription }} action: 'Create Or Update Resource Group' resourceGroupName: ${{ variables.resourceGroup }} location: ${{ variables.location }} # North Europe templateLocation: 'Linked artifact' csmFile: 'BuiltARMTemplates/main.json' # Built from bicep overrideParameters: >- -parameter1 $(parameter1) -parameter2 $(parameter2) ... - The artifact is then deployed like this:
- task: AzureFunctionApp@1 displayName: 'Deploy Function App' inputs: azureSubscription: ${{ variables.azureSubscription }} appType: functionAppLinux appName: 'my-funciton-app' package: $(Pipeline.Workspace)/**/*.zip # Matches only one zip file - The artifact deployment is definitely, 100% waiting until the ARM deployment is complete before proceeding.
Attempted Fix
I have tried running a script between the ARM deployment and the artifact deployment that uses the Azure CLI to verify the status of the app service:
- Deploy a new app service using an ARM template
- Call Azure CLI to make sure the app service is up and running
- Deploy a zip artifact to that app service
sub="${{ parameters.subscriptionId }}"
rg="${{ parameters.resourceGroup }}"
fn="${{ parameters.functionAppName }}"
expected="Running"
attempts=30 # Thirty Attempts
delaySeconds=10 # Gives about 5 minutes before timeout
for attempt in $(seq $attempts)
do
# Check if function app is "Running"
if [[ "$(az resource show --ids /subscriptions/$sub/resourceGroups/$rg/providers/Microsoft.Web/sites/$fn | jq -r ".properties.state")" = "$expected"* ]]
then
echo "$fn is \"$expected\""
break # If the resource is running, then break the loop
fi
# Otherwise, wait before trying again
echo "[$attempt/$attempts] $fn is not currently \"$expected\" waiting for $delaySeconds seconds..."
sleep $delaySeconds
done
Sometimes this script detects that the app service hasn't been provisioned yet, so I can delay the artifact deployment.
This has reduced the failure rate somewhat, but not completely. Often the Azure CLI is able to find that the app service exists and is running, but I still get the error message above when attempting the artifact deployment.
My Question
Does anybody know how to detect when an app service has been provisioned, but is not yet ready for a deployment to be made?
Note: I have not posted the full pipelines or any ARM templates as they're incredibly verbose (it's a big pipeline!) and I'm not sure that they're terribly important for the question I'm asking. That said, I am very happy to provide further details if they are material to the problem at hand!