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

Sam*_*len 11 msbuild powershell tfs-2015 devops

为了自动化我们的部署,我想基于给定的ChangeSetId重建应用程序.一旦这个构建完成,我想得到构建的工件(.exe),所以我们可以部署它们.为了这个问题,我将重点放在"从构建中获取工件"部分.

出于DevOps的目的,我想使用PowerShell,因为它应该能够访问TFS API库,因为MS建议使用它.

环境

我在我们的On Premise TFS 2015服务器上设置了Builds(它工作正常) - 并在此构建之后添加了VSO任务 'Publish artifacts'.到现在为止还挺好.发布的工件将存储在服务器上,这基本上意味着我必须下载连接到构建的工件 - 每个现有的构建都将链接其工件 - 这比我书中的UNC更好.

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

  1. 获取ChangeSetId的源代码
  2. 具有给定配置的MSBuild应用程序
  3. 使用PowerShell获取构建工件
  4. 使用版本管理(Powershell)部署到环境

Yan*_*nko 10

TFS 2015附带了新的REST API,它包含了获取特定构建工件的方法.我将通过以下方式接近您的挑战:

  • 在"发布工件"步骤之后添加"PowerShell脚本"构建步骤
  • 在该PowerShell脚本中:
    • 获取当前版本的ID.TFS公开了许多预定义变量,并且存在构建ID.所有这些变量最终都是环境变量,这篇文章可以帮助您从PowerShell脚本中读取相应的变量
    • 接下来,发出Web请求以获取构建工件.从API描述中可以看出,您只需提供构建ID
    • 然后,解析JSON响应 - 该downloadUrl属性包含用于下载作为单个存档压缩的构建的所有工件的链接
    • 最后,提取存档并获取所需的工件.也许,您也希望在此步骤中将其部署到您的测试环境中

希望这可以帮助.


Sam*_*len 7

好的,就像Yan Sklyarenko所说,TFS 2015(和2013年,经过一些更新)后,有一个出色的REST API.

我已经创建了一个非常非常粗糙的基本PowerShell脚本来完成我想要的.我不能强调这个代码需要多少重构 - 我真的只需要这个作为概念证明,我们将开发多个脚本以满足不同的需求,但是对于那些来到这里寻找代码示例的人来说,你会发现在这里.

  1. 连接到TFS的构建系统
  2. 列出构建定义项(对我自己,Poc)
  3. 搜索一些字符串并获取Build ID
  4. 使用硬编码ID 7启动构建(因为我知道这将起作用,因此我的工作已经完成)
  5. 获取工件(我在其中整合了VSO构建任务'发布工件服务器 ')
  6. 提取收到的Artifacts,因为TFS拉链它们.

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

    $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)
Run Code Online (Sandbox Code Playgroud)