azureazure-devopsazure-web-app-servicedevops

Delete files from app service as part of Azure DevOps release pipeline


We have an Azure DevOps release pipeline using the deploy azure app service task to deploy an application.

We would like to run a task prior to this deploy task to delete all files in the bin folder of the app service.

We do not want to delete all files on the target, just the ones in the bind folder.

I can't see any obvious task that will enable me to do this. Tasks seem to run in the context of the deployment server rather than the app service and so don't enable access to the app service file system.

What's the best way to do it?


Solution

  • This was an utter ballache but this Azure CLI ran as an inline script seemed to work in the end.

    I have tried to make it work with slots as well but that is a bit untested.

    Edited to include try catch on invoking the delete, as it errors otherwise if it can't find the file such as on a second run.

    # Variables
    $appName = "<app-name>"
    $resourceGroupName = "<resource-group>"
    $slotName = ""  # Use the production slot if not using slots
    $filesToDelete = @("/site/wwwroot/MyOldDll1.dll", "/site/wwwroot/MyOldDll2.dll")
    if ($slotName) {
        $kuduApiBaseUrl = "https://$appName-$slotName.scm.azurewebsites.net/api/vfs"
    } else {
        $kuduApiBaseUrl = "https://$appName.scm.azurewebsites.net/api/vfs"
    }
    
    # Function to retrieve publishing credentials
    function Get-PublishingProfile {
        param (
            [string]$appName,
            [string]$resourceGroupName
        )
        $publishingProfile = az webapp deployment list-publishing-profiles --name $appName --resource-group $resourceGroupName --query "[0]" -o json | ConvertFrom-Json
        if (-not $publishingProfile) {
            Write-Host "Failed to retrieve publishing profile. Ensure the app name and resource group are correct."
            return $null
        }
        return $publishingProfile
    }
    
    # Retrieve publishing credentials
    $publishingProfile = Get-PublishingProfile -appName $appName -resourceGroupName $resourceGroupName
    if (-not $publishingProfile) {
        Write-Host "Exiting script due to failure in retrieving publishing profile."
        exit 1
    }
    $publishingUser = $publishingProfile.userName
    $publishingPassword = $publishingProfile.userPWD
    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${publishingUser}:${publishingPassword}"))
                    
    # Function to delete files using Kudu API
    function Delete-KuduFile {
        param (
            [string]$filePath
        )
        $kuduApiUrl = "${kuduApiBaseUrl}${filePath}"
        $kuduApiHeaders = @{
            'Authorization' = ("Basic {0}" -f $base64AuthInfo)
            'If-Match'      = '*'
        }
        try {
          Invoke-RestMethod -Uri $kuduApiUrl -Method Delete -Headers $kuduApiHeaders
          Write-Host "Deleted $filePath"
          return $true
        } catch {
          Write-Host "Failed to delete $filePath. Exception: $_"
          return $false
        }
    }
    
    # Delete specified files
    $filesDeleted = $false
    foreach ($file in $filesToDelete) {
        if (Delete-KuduFile -filePath $file) {
            $filesDeleted = $true
        }
    }
    
    # Restart the app service if files were deleted
    if ($filesDeleted) {
        if ($slotName) {
            az webapp restart --name $appName --resource-group $resourceGroupName --slot $slotName
            Write-Host "Restarted app service $appName in slot $slotName"
        } else {
            az webapp restart --name $appName --resource-group $resourceGroupName
            Write-Host "Restarted app service $appName"
        }
    } else {
        Write-Host "No files were deleted. App service restart not required."
    }