在从 VSTS 进行新部署之前删除 Azure 上的文件和文件夹

Remove files and foldes on Azure before a new deploy from VSTS

作为我在 VSTS 中构建过程的一部分,我想在新部署之前从我的 Azure 站点中删除所有文件和文件夹(少数除外)。我的猜测是,使用 Azure Powershell 脚本是个好主意,我更愿意制作内联脚本。

我正在使用 Azure 资源管理器作为连接类型,我已经 select 编辑了我的订阅和脚本类型(内联脚本),但后来我迷路了,我如何 select 我的应用服务和,首先,列出我的文件?

只是为了测试,仅在我的 VSTS 环境中提供我的文件

Get-ChildItem -Path $(build.sourcesDirectory)

首先,最好将文件包含到 Web 应用程序需要的项目中,然后只需选中 Remove additional files at destination 选项(首先选中 Publish using Web Deploy 选项)以删除其他文件。

其次,您可以通过 Kudu API 删除文件。

DELETE /api/vfs/{path}    (Delete the file at path)

更多信息,您可以参考:Interacting with Azure Web Apps Virtual File System using PowerShell and the Kudu API

更新(添加 Kudu 示例):

  1. 添加 Azure PowerShell step/task
  2. 指定参数,例如:-resourceGroupName XXX -webAppName XXX -kuduPath Global.asax

脚本:

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

这是一个经过调整的脚本版本,它应该包含在您的项目中并作为构建的一部分导出,我称之为 Delete-WebAppFiles。ps1

它通过处理虚拟应用程序和对文件不存在的情况进行错误处理来扩展以前的答案,例如首次部署到新环境时

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

然后您可以如上所述添加一个 Powershell 任务,它看起来应该有点像这样...

这是使用 Postman 测试您在上述 PowerShell 脚本中使用的设置的方法。

我发现使用 Postman 玩转 REST API 有助于了解上面的 PowerShell 脚本在做什么,并了解我可以从 API 返回什么状态代码。我还注意到删除目录的递归逻辑 returns 出现 409 冲突错误,即使确实删除了文件。

在下面的示例中,我的应用服务称为 "YatesDeleteMe"

创建一个 base 64 编码的用户名和密码字符串,以在下面的授权中使用 header 或 运行 上面的 PowerShell 脚本,它将为您输出一个

  1. 下载应用服务的发布文件,可以从 Azure 门户的“概述”选项卡下载。
  2. 使用文本编辑器打开文件
  3. 找到用户名(用户名示例:$YatesDeleteMe)和密码(密码示例:ch222cDlpCjx4Glq333qo4QywGPMs1cK2Rjrn6phqZ9HswtgEEE12CrhDmcn)
  4. 从中创建一个字符串并用冒号分隔它们(应该看起来像这样:$YatesDeleteMe:ch222cDlpCjx4Glq333qo4QywGPMs1cK2Rjrn6phqZ9HswtgEEE12CrhDmcn)
  5. 使用您自己的程序对它们进行 Base 64 编码 site。结果应如下所示:JFlhdGVzRGVsZXRlTWU6Y2gyMjJjRGxwQ2p4NEdscTMzM3FvNFF5d0dQTXMxY0syUmpybjZwaHFaOUhzd3RnRUVFMTJDcmhEbWNu

检索单个文件

  1. 打开 Postman
  2. 将动词更改为 GET
  3. 在要检索的文件中输入 URL(例如,https://YatesDeleteMe.scm.azurewebsites.net/api/vfs/site/wwwroot/web.config). For more info on paths see this
  4. 添加了一个header-->
    • 密钥:授权
    • 值:基本 YourBase64EncodedStringFromAbove
  5. Left-click "Send" 按钮和文件将下载

删除单个文件

  1. 打开 Postman
  2. 将动词更改为 DELETE
  3. 在要删除的文件中输入 URL(例如 https://YatesDeleteMe.scm.azurewebsites.net/api/vfs/site/wwwroot/web.config
  4. 添加了一个header-->
    • 密钥:授权
    • 值:基本 YourBase64EncodedStringFromAbove
  5. 添加了一个header-->
    • 密钥:If-Match
    • 值:*
  6. Left-click "Send" 按钮和文件将被删除

删除目录下的所有文件

  1. 打开 Postman
  2. 将动词更改为 DELETE
  3. 在要删除的文件夹中输入 URL,然后添加斜线和查询字符串 ?recursive=true(例如,https://YatesDeleteMe.scm.azurewebsites.net/api/vfs/site/wwwroot/?recursive=true
  4. 添加了一个header-->
    • 密钥:授权
    • 值:基本 YourBase64EncodedStringFromAbove
  5. 添加了一个header-->
    • 密钥:If-Match
    • 值:*
  6. Left-click "Send" 按钮和文件夹将被删除。我总是收到 409 错误,但文件夹已删除。

参考

  • 带图片的博客 post。here