从 Powershell 启动 vNext 构建并获取工件

Start vNext build from Powershell and get artifacts

为了自动化我们的部署,我想根据给定的 ChangeSetId 重建一个应用程序。此构建完成后,我想获取构建的 artifacts(.exe),以便我们部署它们。为了这个问题,我专注于 'Get artifacts from build' 部分。

出于 DevOps 的目的,我想使用 PowerShell,因为它应该能够访问 TFS API 库,并且因为 MS 推荐使用它。

环境

我已经在我们的 On Premise TFS 2015 服务器(运行良好)中设置了构建 - 并在此构建之后添加了一个 VSO 任务 'Publish artifacts'。到目前为止,一切都很好。 已发布的工件将存储在服务器上,这基本上意味着我必须下载连接到构建的工件 - 每个现有构建都将链接其工件 - 这比我书中的 UNC 掉落更好。

没有我的挑战;我如何以编程方式访问这些工件,第 3 步?

  1. 获取 ChangeSetId 的来源
  2. 具有给定配置的 MSBuild 应用程序
  3. 使用 PowerShell 获取构建工件
  4. 使用 Release Management(以及 Powershell)部署到环境

TFS 2015 附带 new REST API,它包含获取特定构建工件的方法。我将通过以下方式应对您的挑战:

  • 在 "Publish artifacts" 步骤后添加 "PowerShell script" 构建步骤
  • 在该 PowerShell 脚本中:
    • 获取当前构建的ID。 TFS 公开 a number of predefined variables, and build ID is there. All those variables end up as environment variable, and this post 可以帮助您从您的 PowerShell 脚本中读取合适的
    • 接下来,向 get build artifacts 发出 Web 请求。从 API 描述中可以看出,您只需提供构建 ID
    • 然后,解析 JSON 响应 - downloadUrl 属性 包含 link 以下载压缩为单个存档的构建的所有工件
    • 最后,解压缩存档并挑选您需要的那些工件。也许,您也想在此步骤中将其部署到您的测试环境

希望对您有所帮助。

好吧,正如 Yan Sklyarenko 所说,TFS 2015(和 2013,经过一些更新),具有出色的 REST API。

我已经创建了一个非常非常粗糙的基本 PowerShell 脚本来执行我想要的操作。我怎么强调这段代码需要重构多少都不为过——我真的只是需要它作为概念证明,我们将开发多个脚本来满足不同的需求,但是对于来这里查看代码示例的人来说,你会发现在这里。

  1. 连接到 TFS 的构建系统
  2. 列出构建定义项(对于我自己,Poc)
  3. 搜索一些字符串并获取构建 ID
  4. 开始构建,使用硬编码 ID 7 (因为我知道这会起作用,因此我的工作已经完成)
  5. 获取 Artifacts(我在其中合并了 VSO 构建任务 'Publish Artifacts Server')
  6. Extract 说收到了 Artifacts,因为 TFS 压缩了它们。

从那时起,我将把这些脚本和输出合并到 MS Release Management 服务中 - 并准备好在 VSO Release vNext 为本地 TFS 2015 发布时迁移到它!

    $projectId ='{ProjectIdGuid}'
    $buildNr = '3945' 
    $username =  'username'
    $password  =  'password' 
    $zipDestination = 'C:\temp\unzip\temp.zip'
    $workingFolder = ('C:\temp\unzip\' + [System.DateTime]::Now.ToString("yyyyMMddhhmmss"))  #temp because of file already exist warnings... after completion we should delete the working directory content
    $tfsURL = 'http://myTFS:8080/tfs/MyCollection/'+ $projectId 

    $cred = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString -String $password -AsPlainText -Force))

    #write list of build definitions (to be used later)
    $allbuildDefs = (Invoke-RestMethod -Uri ($tfsURL + '/_apis/build/definitions?api-version=2.0') -Method GET -Credential $cred).value | Where-Object {$_.name -like '*buildName*'} | Out-Default | select name
    Write-Host($allbuildDefs)


    $buildDefs = ConvertFrom-Json($allbuildDefs) 
    $buildId = ($buildDefs.value).id;


    #Get build Definition for what you want to build
    $buildDefinitionURI = $tfsURL + '/_apis/build/requests?api-version=1.0'


    #kick off build 
    $body = '{ "definition": { "id": '+ 7 + '}, reason: "Manual", priority: "Normal"}'
    $BuildReqBodyJson =  $body | ConvertTo-Json
    $buildOutput = Invoke-RestMethod -Method Post -Uri $buildDefinitionURI -Credential $cred -ContentType 'application/json' -Body $body

    #get buildNr


    #build URI for buildNr
    $BuildURI = $tfsURL + '/_apis/build/builds/' + $buildNr + '/artifacts'

    #get artifact downloadPath
    $downloadURL = (Invoke-RestMethod -Uri $BuildURI -Credential $cred).Value.Resource.downloadUrl

    #download ZIP
    Invoke-WebRequest -uri $downloadURL -Credential  $cred -OutFile $zipDestination

    #unzip
    Add-Type -assembly 'system.io.compression.filesystem'
    [io.compression.zipfile]::ExtractToDirectory($zipDestination, $workingFolder)