微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从异步执行PowerShell进程中更新TFS构建环境变量

如何解决从异步执行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

请注意,每次迭代都会增加“ test.zip”文件的大小。

解决方法

您并不遥远。我会做以下

  1. 使用脚本下载巨大的zip文件。最后一步是设置变量"Write-Host ##vso[task.setvariable variable=IsDownloadComplete]True"
  2. 执行与大型下载同时进行的步骤,直到将一切统一的工作开始。
  3. 添加带有Powershell脚本的步骤来检查$env:IsDownloadComplete -eq 'True'。让它循环播放直到IsDownloadComplete为true,或者您遇到超时(您不想在出现问题时永远运行您的构建)。不要忘记在此步骤中添加refreshenv,因为该值是由其他过程更新的。
  4. 其余步骤
,

如上面的OP和注释中所述,我无法从异步作业中获取环境变量更新调用。 最后,时间限制要求快速而肮脏的解决方案:

  1. 在启动异步作业的构建步骤中,在创建异步过程之前,我创建了一个文本文件,其中包含单词“ False”:

    New-Item -Path $tempFilePath -Name "ArtifactDownloadComplete.txt" -ItemType "file" -Value "False"
    
  2. 开始异步下载过程;步骤结束并构建进度(异步过程在后台执行)。异步函数中的Invoke-RestMethod调用完成后,“ ArtifactDownloadComplete.txt”文件的内容将更新为“ True”:

    ((Get-Content -Path "$tempFilePath\ArtifactDownloadComplete.txt" -Raw) -replace "False","True") | Set-Content -Path "$tempFilePath\ArtifactDownloadComplete.txt"
    
  3. 在构建中需要下载下载的档案之前,我添加了一个步骤来解压缩档案。在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 举报,一经查实,本站将立刻删除。