如何解决从异步执行PowerShell进程中更新TFS构建环境变量
我正在一个TFS构建过程中,该过程的特征是从Artifactory存储库中下载大型ZIP存档。下载通常需要20分钟以上的时间,实际上使我的构建执行时间翻了一番。
为了加快构建速度,我想从PowerShell的构建步骤开始一个异步过程,以请求工件下载并移至下一个构建步骤,同时下载在后台执行。
我已经成功管理了此操作(启动过程powershell -WindowStyle隐藏等);该工件确实能够成功下载,并且至关重要的是,在PowerShell步骤完成并且构建继续到后续步骤之后,下载继续并完成。
现在,在以后的版本中将需要对下载的存档进行进一步处理。因此,为了确保在下载完成之前不开始处理,我想将构建环境变量“ IsDownloadComplete”从“ False”更新为“ True”。
用于环境变量更新的常规PowerShell无法正常运行(我怀疑是由于从孤立的异步进程执行?):
"##vso[task.setvariable variable='IsDownloadComplete';]'True'"
那该怎么办?如何从异步过程中更新环境变量?
更新: 我的TFS构建步骤中的异步流程调用如下所示:
$cmd = "$(SupportFunctionsLocation)\[script].ps1 -artifactUrl '$(artifactUrl)' -artifactoryApiKey '$(ArtifactoryApiKey)' -baseDir '$(Build.BinariesDirectory)\[base_dir]' -envVarName 'IsDownloadComplete' -envVarValue 'true'"
try {
start-process PowerShell.exe -ArgumentList "-noprofile -WindowStyle Hidden -Command $cmd"
Start-Sleep -s 10
} catch {
Write-Host $_.ErrorMessage
}
完成构件提取后,用于更新构建环境变量的调用位于“ $(SupportFunctionsLocation)[script] .ps1”脚本中:
param (
[parameter(mandatory=$true)][string]$artifactUrl,[parameter(mandatory=$true)][string]$apiKey,[parameter(mandatory=$true)][string]$baseDir,[parameter(mandatory=$true)][string]$envVarName,[parameter(mandatory=$true)][string]$envVarValue
)
function Pull-FromArtifactory ($url,$apiKey,$dir) {
if (-not (Test-Path -Path $dir)) {
New-Item -Path $dir -ItemType "Directory"
}
$archive = $null
Write-Host "Pulling archive from Artifactory repository (this may take a minute or two)..."
try {
$archive = Split-Path $url -leaf
$headers = @{"X-JFrog-Art-Api" = $apiKey}
Invoke-RestMethod -Uri $url -Headers $headers -OutFile "$dir\$archive"
}
catch {
Write-Host "Failed to retrieve archive from Artifactory repository..."
Write-Host $_.Exception.Message
Exit 1
}
}
Pull-FromArtifactory $artifactUrl $apiKey $baseDir
# Update 'IsDownloadComplete' build environment variable
Write-Host "##vso[task.setvariable variable=$envVarName;]$envVarValue"
随后执行的调试构建步骤如下:
if (Test-Path ("$(Build.BinariesDirectory)\[base_dir]")) {
do {
Get-ChildItem "$(Build.BinariesDirectory)\[base_dir]" -Include "test.zip" -Force -Recurse
Write-Host "Download complete: " $env:IsDownloadComplete
Start-Sleep -s 30
} while ($env:IsDownloadComplete -ne 'true')
}
执行构建时,异步过程将从PowerShell步骤中的start-process调用成功启动。该步骤无需等待;它终止并且异步过程继续在后台执行。
随着调试步骤中的脚本循环,每次执行Get-ChildItem都会显示文件大小随着异步过程的进行而增加,直到下载完成(我们通过文件大小知道)。
但是,即使下载已完成,构建环境变量也无法更新;调试脚本步骤将继续无限循环。
调试步骤的日志输出:
2020-09-11T13:46:23.5557526Z目录:C:\ BuildAgent_work \ 15 \ b [base_dir]
2020-09-11T13:46:23.5557526Z
2020-09-11T13:46:23.5687526Z模式LastWriteTime长度名称
2020-09-11T13:46:23.5707484Z ---- ------------- ------ ----
2020-09-11T13:46:23.5737531Z -a ---- 2020年9月11日上午9:46 3572999 test.zip
2020-09-11T13:46:23.6027538Z下载完成:false
2020-09-11T13:46:53.6214501Z -a ---- 2020年9月11日上午9:46
30362999 test.zip
2020-09-11T13:46:53.6224502Z下载完成:false
2020-09-11T13:47:23.6271640Z -a ---- 2020年9月11日上午9:46
56742999 test.zip
2020-09-11T13:47:23.6291560Z下载完成:false
2020-09-11T13:47:53.6328511Z -a ---- 2020年9月11日上午9:46
83072999 test.zip
2020-09-11T13:47:53.6338508Z下载完成:false
2020-09-11T13:48:23.6377761Z -a ---- 2020年9月11日上午9:48
95577750 test.zip
2020-09-11T13:48:23.6387762Z下载完成: false
2020-09-11T13:48:53.6424119Z -a ---- 2020年9月11日上午9:48
95577750 test.zip
2020-09-11T13:48:53.6434120Z下载完成: false
2020-09-11T13:49:23.6473880Z -a ---- 2020年9月11日上午9:48 95577750 test.zip
2020-09-11T13:49:23.6483867Z下载完成: false
2020-09-11T13:49:53.6519497Z -a ---- 2020年9月11日上午9:48 95577750 test.zip
2020-09-11T13:49:53.6529503Z下载完成: false
2020-09-11T13:50:23.6560150Z -a ---- 2020年9月11日上午9:48 95577750 test.zip
解决方法
您并不遥远。我会做以下
- 使用脚本下载巨大的zip文件。最后一步是设置变量
"Write-Host ##vso[task.setvariable variable=IsDownloadComplete]True"
- 执行与大型下载同时进行的步骤,直到将一切统一的工作开始。
- 添加带有Powershell脚本的步骤来检查
$env:IsDownloadComplete -eq 'True'
。让它循环播放直到IsDownloadComplete为true,或者您遇到超时(您不想在出现问题时永远运行您的构建)。不要忘记在此步骤中添加refreshenv
,因为该值是由其他过程更新的。 - 其余步骤
如上面的OP和注释中所述,我无法从异步作业中获取环境变量更新调用。 最后,时间限制要求快速而肮脏的解决方案:
-
在启动异步作业的构建步骤中,在创建异步过程之前,我创建了一个文本文件,其中包含单词“ False”:
New-Item -Path $tempFilePath -Name "ArtifactDownloadComplete.txt" -ItemType "file" -Value "False"
-
开始异步下载过程;步骤结束并构建进度(异步过程在后台执行)。异步函数中的Invoke-RestMethod调用完成后,“ ArtifactDownloadComplete.txt”文件的内容将更新为“ True”:
((Get-Content -Path "$tempFilePath\ArtifactDownloadComplete.txt" -Raw) -replace "False","True") | Set-Content -Path "$tempFilePath\ArtifactDownloadComplete.txt"
-
在构建中需要下载下载的档案之前,我添加了一个步骤来解压缩档案。在PowerShell实施中,此步骤包括循环延迟;为了开始执行步骤处理,此循环的中断条件是“ ArtifactDownloadComplete.txt”文件的内容已更新为“ True”:
do { if ((Get-Content $statusFile) -eq "False") { Start-Sleep -s 20 } else { Write-ConsoleLog "Artifact download complete." } } while ((Get-Content $statusFile) -eq "False")
又快又脏。
他的过程的未来发展可能感兴趣的领域:TFS REST API。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。