使用 Azure DevOps 管道和版本部署虚拟助手
Posted
技术标签:
【中文标题】使用 Azure DevOps 管道和版本部署虚拟助手【英文标题】:Deploy Virtual Assistant using Azure DevOps pipelines and releases 【发布时间】:2019-05-23 02:53:53 【问题描述】:我正在尝试创建一种简单的方法,让产品所有者能够站起来并拆除虚拟助手所需的 Azure 资源。但是,部署脚本 deploy.ps1
需要 PowerShell 6+,而 Azure DevOps 似乎不提供该版本。
最好的方法是什么?
描述您想要的解决方案
目标是使用发布管道自动支持机器人运行所需的 Azure 资源。
想法
有没有办法通过 Azure PowerShell 使用 PowerShell 6+? 我们不应该使用deploy.ps1
在 DevOps 发布管道中部署资源吗?
代码
这是deploy.ps1
和link to the latest 的内容。
#Requires -Version 6
Param(
[string] $name,
[string] $resourceGroup,
[string] $location,
[string] $appId,
[string] $appPassword,
[string] $luisAuthoringKey,
[string] $luisAuthoringRegion,
[string] $parametersFile,
[string] $languages = "en-us",
[string] $outFolder = $(Get-Location),
[string] $logFile = $(Join-Path $PSScriptRoot .. "deploy_log.txt")
)
# Reset log file
if (Test-Path $logFile)
Clear-Content $logFile -Force | Out-Null
else
New-Item -Path $logFile | Out-Null
# Get mandatory parameters
if (-not $name)
$name = Read-Host "? Bot Name (used as default name for resource group and deployed resources)"
if (-not $resourceGroup)
$resourceGroup = $name
if (-not $location)
$location = Read-Host "? Azure resource group region"
if (-not $appPassword)
$appPassword = Read-Host "? Password for MSA app registration (must be at least 16 characters long, contain at least 1 special character, and contain at least 1 numeric character)"
if (-not $luisAuthoringRegion)
$luisAuthoringRegion = Read-Host "? LUIS Authoring Region (westus, westeurope, or australiaeast)"
if (-not $luisAuthoringKey)
Switch ($luisAuthoringRegion)
"westus"
$luisAuthoringKey = Read-Host "? LUIS Authoring Key (found at https://luis.ai/user/settings)"
Break
"westeurope"
$luisAuthoringKey = Read-Host "? LUIS Authoring Key (found at https://eu.luis.ai/user/settings)"
Break
"australiaeast"
$luisAuthoringKey = Read-Host "? LUIS Authoring Key (found at https://au.luis.ai/user/settings)"
Break
default
Write-Host "! $($luisAuthoringRegion) is not a valid LUIS authoring region." -ForegroundColor DarkRed
Break
if (-not $luisAuthoringKey)
Break
if (-not $appId)
# Create app registration
$app = (az ad app create `
--display-name $name `
--password $appPassword `
--available-to-other-tenants `
--reply-urls 'https://token.botframework.com/.auth/web/redirect')
# Retrieve AppId
if ($app)
$appId = ($app | ConvertFrom-Json) | Select-Object -ExpandProperty appId
if(-not $appId)
Write-Host "! Could not provision Microsoft App Registration automatically. Review the log for more information." -ForegroundColor DarkRed
Write-Host "! Log: $($logFile)" -ForegroundColor DarkRed
Write-Host "+ Provision an app manually in the Azure Portal, then try again providing the -appId and -appPassword arguments. See https://aka.ms/vamanualappcreation for more information." -ForegroundColor Magenta
Break
# Get timestamp
$timestamp = Get-Date -f MMddyyyyHHmmss
# Create resource group
Write-Host "> Creating resource group ..."
(az group create --name $name --location $location) 2>> $logFile | Out-Null
# Deploy Azure services (deploys LUIS, QnA Maker, Content Moderator, CosmosDB)
Write-Host "> Deploying Azure services (this could take a while)..." -ForegroundColor Yellow
if ($parametersFile)
(az group deployment create `
--name $timestamp `
--resource-group $resourceGroup `
--template-file "$(Join-Path $PSScriptRoot '..' 'Resources' 'template.json')" `
--parameters "@$($parametersFile)" `
--parameters microsoftAppId=$appId microsoftAppPassword="`"$($appPassword)`"") 2>> $logFile | Out-Null
else
(az group deployment create `
--name $timestamp `
--resource-group $resourceGroup `
--template-file "$(Join-Path $PSScriptRoot '..' 'Resources' 'template.json')" `
--parameters microsoftAppId=$appId microsoftAppPassword="`"$($appPassword)`"") 2>> $logFile | Out-Null
# Get deployment outputs
$outputs = (az group deployment show `
--name $timestamp `
--resource-group $resourceGroup `
--query properties.outputs)
# If it succeeded then we perform the remainder of the steps
if ($outputs)
# Log and convert to JSON
$outputs >> $logFile
$outputs = $outputs | ConvertFrom-Json
# Update appsettings.json
Write-Host "> Updating appsettings.json ..."
if (Test-Path $(Join-Path $outFolder appsettings.json))
$settings = Get-Content $(Join-Path $outFolder appsettings.json) | ConvertFrom-Json
else
$settings = New-Object PSObject
$settings | Add-Member -Type NoteProperty -Force -Name 'microsoftAppId' -Value $appId
$settings | Add-Member -Type NoteProperty -Force -Name 'microsoftAppPassword' -Value $appPassword
if ($outputs.appInsights) $settings | Add-Member -Type NoteProperty -Force -Name 'appInsights' -Value $outputs.appInsights.value
if ($outputs.storage) $settings | Add-Member -Type NoteProperty -Force -Name 'blobStorage' -Value $outputs.storage.value
if ($outputs.cosmosDb) $settings | Add-Member -Type NoteProperty -Force -Name 'cosmosDb' -Value $outputs.cosmosDb.value
if ($outputs.contentModerator) $settings | Add-Member -Type NoteProperty -Force -Name 'contentModerator' -Value $outputs.contentModerator.value
$settings | ConvertTo-Json -depth 100 | Out-File $(Join-Path $outFolder appsettings.json)
# Delay to let QnA Maker finish setting up
Start-Sleep -s 30
# Deploy cognitive models
Invoke-Expression "$(Join-Path $PSScriptRoot 'deploy_cognitive_models.ps1') -name $($name) -luisAuthoringRegion $($luisAuthoringRegion) -luisAuthoringKey $($luisAuthoringKey) -qnaSubscriptionKey $($outputs.qnaMaker.value.key) -outFolder $($outFolder) -languages `"$($languages)`""
Write-Host "> Done."
else
# Check for failed deployments
$operations = az group deployment operation list -g $resourceGroup -n $timestamp | ConvertFrom-Json
$failedOperations = $operations | Where $_.properties.statusmessage.error -ne $null
if ($failedOperations)
foreach ($operation in $failedOperations)
switch ($operation.properties.statusmessage.error.code)
"MissingRegistrationForLocation"
Write-Host "! Deployment failed for resource of type $($operation.properties.targetResource.resourceType). This resource is not avaliable in the location provided." -ForegroundColor DarkRed
Write-Host "+ Update the .\Deployment\Resources\parameters.template.json file with a valid region for this resource and provide the file path in the -parametersFile parameter." -ForegroundColor Magenta
default
Write-Host "! Deployment failed for resource of type $($operation.properties.targetResource.resourceType)."
Write-Host "! Code: $($operation.properties.statusMessage.error.code)."
Write-Host "! Message: $($operation.properties.statusMessage.error.message)."
Write-Host "+ To delete this resource group, run 'az group delete -g $($resourceGroup) --no-wait'" -ForegroundColor Magenta
Break
设置截图
尝试运行 Azure PowerShell
当我尝试使用 Azure PowerShell 运行脚本时,我收到以下错误。
##[error]The script 'deploy.ps1' cannot be run because it contained a "#requires" statement for Windows PowerShell 6.0. The version of Windows PowerShell that is required by the script does not match the currently running version of Windows PowerShell 5.1.17763.316.
这是将Azure PowerShell Version
设置为Latest installed version
。使用Specify other version
和6.7.0
、6.2.1
或6.0.0
也不起作用。这些似乎都没有真正的效果。它总是以5.1.17763.316
的形式返回。
【问题讨论】:
您没有在项目模板中添加一个JSON格式的ARM模板文件,可以创建资源吗? deploy.ps1 的内容是什么? 我编辑了我的帖子以包含deploy.ps1
的内容。我可能有一个可用的 ARM 模板,但我认为它比我从 ARM 模板中得到的更多。我不知道。 Virtual Assistant docs 中没有提到如何进行。任何提示表示赞赏。
@EricHansen 为什么你认为 PowerShell 6+ 在 Azure DevOps 上不可用?
你好@PravinAmbekar。在我的专业意见中〜在我的原始帖子之后 1 年,不要使用管道中的 deploy.ps1。 deploy.ps1 是一个很好的快速启动脚本,可让您启动并运行,但如果您想真正使这个强大的企业使用,请修改 Microsoft 提供的 ARM 模板以满足您的需求。我建议详细阅读 deploy.ps1 的每一行。你会看到它使用了一个存储在这里的模板github.com/microsoft/botframework-solutions/tree/master/…。
我认为最好的解决方案是使用 ARM 部署任务来部署/更新资源。您仍然需要运行一些 CLI 命令来与您供应的资源进行交互。我建议不要使用 Microsoft 提供的 PowerShell 脚本之一。取而代之的是,提取您需要的特定 CLI 命令(以脚本为例来查看您需要什么)并为特定场景所需的各个 CLI 命令创建单独的任务。
【参考方案1】:
Build Agent 有 PSv6,他们也有 PSv5 每个代理上的软件都列在:https://github.com/Microsoft/azure-pipelines-image-generation/tree/master/images/win
这里的问题是任务正在使用“Azure Powershell”,它使用 PS v5 cmdlet,因此将强制使用 PSv5 (powershell.exe) 而不是 PSv6 (pwsh.exe)。
如果您要使用普通的“Powershell”任务并选择“使用 Powershell Core”,您将很难(或不安全)登录。
对于这种情况,您需要从 Azure CLI 任务执行 PSv6 脚本。为此,只需添加 Azure CLI 任务并执行下面的内联脚本(修复您发布的路径和参数)。
pwsh -File $System.DefaultWorkingDirectory\<some-path-to>\deploy.ps1 -script-arguments-copy-pasted-here
注意:唯一可行的方法是,如果传递了所有参数并且未命中读取主机,如 4c74356b41 所述,则无法从管道获取输入。
【讨论】:
我也面临这个问题 - 但是当我按照您的步骤操作时,管道会执行半小时并且没有日志并且它会超时【参考方案2】:首先,您的脚本正在使用Read-Host
,它在管道中不可用。构建代理确实有 pwsh(所以 Powershell 6.0 +),但是您的脚本根本没有使用 Azure Powershell,它使用的是 Azure CLI(也可以在构建代理上使用)。
一般来说,您需要为管道重构脚本,它会正常工作。
【讨论】:
我不是 PowerShell 或 Azure DevOps 专家,所以关于如何重构deploy.ps1
的任何提示? deploy.ps1
直接来自 Microsoft's Virtual Assistant repo,所以我相信任何关于如何使用 DevOps 管道做到这一点的文档都会受到不仅仅是我的赞赏。另外,我天真地认为我正在使用 Azure PowerShell,尽管您可能是对的。我用设置的屏幕截图更新了我的帖子,希望它比我的文字更具描述性。
azure powershell cmdlet 如下所示:az-verbnoun
你有az verb verb noun
。这就是 Azure CLI。要重构,您至少需要删除对Read-Host
的所有调用并强制参数以上是关于使用 Azure DevOps 管道和版本部署虚拟助手的主要内容,如果未能解决你的问题,请参考以下文章
从 Azure DevOps 管道启动适用于 VS 2019 的开发人员 PowerShell
在 Azure Devops 中部署管道后暂存槽的 Web 作业未停止
如何从 Azure DevOps 中的部署后批准/部署后门调用 Powershell 脚本