As part of my build process in VSTS I want to delete all files and folders (except af few) from my azure site before a new deploy. My guess is, that using a Azure Powershell
Here's a tweaked version of the script which should be included in your project and exported as an artefact as part of your build, I call mine Delete-WebAppFiles.ps1
It expands on the previous answer by also handling virtual applications and having error handling for the case when the files do not exist e.g. on first deployment to a new environment
param(
[string]$resourceGroupName,
[string]$webAppName,
[string]$appPath="wwwroot",
[string]$slotName="",
[string]$kuduPath,
[bool]$recursive=$false
)
function Get-AzureRmWebAppPublishingCredentials($resourceGroupName, $webAppName, $slotName = $null){
if ([string]::IsNullOrWhiteSpace($slotName)){
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
}
else{
$resourceType = "Microsoft.Web/sites/slots/config"
$resourceName = "$webAppName/$slotName/publishingcredentials"
}
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force
Write-Host $publishingCredentials
return $publishingCredentials
}
function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName, $slotName = $null){
$publishingCredentials = Get-AzureRmWebAppPublishingCredentials $resourceGroupName $webAppName $slotName
Write-Host $publishingCredentials.Properties.PublishingUserName
Write-Host $publishingCredentials.Properties.PublishingPassword
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}
function Delete-KuduFile($resourceGroupName, $webAppName, $appPath, $slotName, $kuduPath, $recursive){
$kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppName $slotName
if ($recursive -eq $true) {
if (-not ($kuduPath.endswith("recursive=true"))) {
if (-not ($kuduPath.endswith("/"))) {
$kuduPath += "/"
}
$kuduPath += "?recursive=true"
}
}
if ($slotName -eq ""){
$kuduApiUrl = "https://$webAppName.scm.azurewebsites.net/api/vfs/site/$appPath/$kuduPath"
}
else{
$kuduApiUrl = "https://$webAppName`-$slotName.scm.azurewebsites.net/api/vfs/site/$appPath/$kuduPath"
}
Write-Output $kuduApiUrl
Write-Output $kuduApiAuthorisationToken
try
{
Invoke-RestMethod -Uri $kuduApiUrl `
-Headers @{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method DELETE
} catch {
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
if (-not ($_.Exception.Response.StatusCode.value__ -eq 404)) {
throw $PSItem
}
}
}
Delete-KuduFile $resourceGroupName $webAppName $appPath $slotName $kuduPath $recursive
You can then add a Powershell task as mentioned above which should look a little like this...
I found it useful to play with the REST API using Postman to understand what the PowerShell scripts above were doing and understand what status codes I could expect back from the API. I also noticed that the recursive logic for deleting a directory returns a 409 Conflict error even though is DOES delete the files.
In the examples below, my app service is called "YatesDeleteMe"
Create a base 64 encoded username and password string to use below in your authorization header OR run the PowerShell scripts above and it will output one for you
Retrieve a single file
Delete a single file
Delete all the files in a directory
Reference
First, it’s better to include the files to the project that the web app needs, then just check Remove additional files at destination option (Check Publish using Web Deploy option first) to remove additional files.
Secondly, you can remove the files through Kudu API.
DELETE /api/vfs/{path} (Delete the file at path)
More information, you can refer to: Interacting with Azure Web Apps Virtual File System using PowerShell and the Kudu API
Update (Add Kudu sample):
Script:
param(
[string]$resourceGroupName,
[string]$webAppName,
[string]$slotName="",
[string]$kuduPath
)
function Get-AzureRmWebAppPublishingCredentials($resourceGroupName, $webAppName, $slotName = $null){
if ([string]::IsNullOrWhiteSpace($slotName)){
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
}
else{
$resourceType = "Microsoft.Web/sites/slots/config"
$resourceName = "$webAppName/$slotName/publishingcredentials"
}
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force
Write-Host $publishingCredentials
return $publishingCredentials
}
function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName, $slotName = $null){
$publishingCredentials = Get-AzureRmWebAppPublishingCredentials $resourceGroupName $webAppName $slotName
Write-Host $publishingCredentials.Properties.PublishingUserName
Write-Host $publishingCredentials.Properties.PublishingPassword
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}
function Delete-FileToWebApp($resourceGroupName, $webAppName, $slotName = "", $kuduPath){
$kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppName $slotName
if ($slotName -eq ""){
$kuduApiUrl = "https://$webAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/$kuduPath"
}
else{
$kuduApiUrl = "https://$webAppName`-$slotName.scm.azurewebsites.net/api/vfs/site/wwwroot/$kuduPath"
}
Write-Output $kuduApiUrl
Write-Output $kuduApiAuthorisationToken
Invoke-RestMethod -Uri $kuduApiUrl `
-Headers @{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method DELETE
}
Delete-FileToWebApp $resourceGroupName $webAppName $slotName $kuduPath