TFS 2017 vNext Build使用PowerShell获取工作区

时间:2017-12-11 11:23:12

标签: powershell tfs azure-devops azure-pipelines tfs2017

我有一个项目,在构建过程中需要更改某些文件。 我必须使用Powershell来做到这一点。我已经配置了所有必需的步骤来执行此操作。所有步骤都适用于我的客户端电脑。 Build服务器具有相同的配置。 Vs 2015(适用于TF Powertools 2015)和VS 2017安装。当我对Build进行排队时,构建在尝试获取Workspace时失败。也许这是因为,构建代理只创建本地工作区?此时已检出所需的更改。我无法使用TF.exe签入,因为有签入策略阻止签入没有关联的工作项。这是我在这一步尝试做的事情:

  • 通过来源路径获取工作区($ Env:BUILD_SOURCESDIRECTORY)
  • 获取此工作区的待定更改$pendingChanges = $tfsws.GetPendingChanges()
  • 使用关联的工作项创建workitemcheckininfo
  • 使用已创建的workitemcheckininfo $changesetNumber = $tfsws.CheckIn($pendingChanges,"$CommentString checked in by BuildServer",$null, $workItemChanges,$null)
  • 进行签入

由于我没有获得工作区(步骤1),以下步骤将无法启动。

这是我到目前为止所尝试的:

1

$binpath   = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer"
#$binpath   = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0"
Add-Type -path "$binpath\Microsoft.TeamFoundation.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.Common.dll"

$teamProjectCollection = "http://mytfs/tfs/defaultcollection"
$tfs = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($teamProjectCollection)

#The next line fails, as the commandlet is from TF Powertools 2015 and the TFS server is 2017.
#I get the error message "Microsoft.TeamFoundation.Client.TfsTeamProjectCollection cannot be converted to Microsoft.TeamFoundation.Client.TfsTeamProjectCollection"
$tfsws = Get-TfsWorkspace -Server $tfs -Computer $hostname -Owner $Username

2

$binpath   = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer"
#$binpath   = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0"
Add-Type -path "$binpath\Microsoft.TeamFoundation.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$binpath\Microsoft.TeamFoundation.Common.dll"

$localReference = join-path $Env:BUILD_SOURCESDIRECTORY $TargetBranch
$teamProjectCollection = "http://mytfs/tfs/defaultcollection"
$tfsTeamProjectCollection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($teamProjectCollection)
$versioncontrolServer = $tfsTeamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])

#The next lines fail, as $versioncontrolServer is nothing
[Microsoft.TeamFoundation.VersionControl.Client.Workstation]::Current.EnsureUpdateWorkspaceInfoCache($versionControlServer, $username);
$tfsws = $versioncontrolServer.GetWorkspace($localReference)

可能导致问题的两件事:1st =>构建代理只使用本地工作区?第2 => TFS 2017和VS 2015不够兼容?

有人是一个好的工作示例或解决方案吗?

我想到了其他选择。也许我可以编写一个可执行文件,这可以完成我的工作。

我可以在没有工作空间的情况下签到,然后关联工作项吗?如何以编程方式将工作项与现有的Changeset相关联?

2 个答案:

答案 0 :(得分:0)

没有工作区,您无法签到。

但是,该过程将在获取源步骤中创建本地工作空间。因此,您可以直接签入更改以绕过签入策略,然后将工作项与特定的变更集关联。

绕过/覆盖签入策略,您可以运行以下签入命令(您可以复制以下命令并保存为PowerShell / cmd脚本,然后添加PowerShell /命令运行脚本的任务)。见Checkin command

tf Checkin $source_dir /comment:"Change files" /noprompt /force /bypass /override:"Without associating workitem"

注意: 确保您使用的代理是2.122.1或更高版本,否则您可能会遇到错误,请参阅this related thread有关详细信息。

将工作项与现有的变更集相关联:

使用客户端API的C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace APPI
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://xxx.xxx.xxx.xxx:8080/tfs/DefaultCollection";
            TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri(url));
            WorkItemStore wis = ttpc.GetService<WorkItemStore>();
            VersionControlServer vcs = ttpc.GetService<VersionControlServer>();
            int wid = 194;
            int cid = 440;
            WorkItem wi = wis.GetWorkItem(wid);
            Changeset cs = vcs.GetChangeset(cid);
            ExternalLink el = new ExternalLink(wis.RegisteredLinkTypes["Fixed in Changeset"], cs.ArtifactUri.AbsoluteUri);
            wi.Links.Add(el);
            wi.Save();     
        }
    }
}

使用REST API的PowerShell:

Param(
   [string]$collectionurl = "http://server:8080/tfs/DefaultCollection",
   [string]$keepForever = "true",
   [string]$WorkitemID = "194",
   [string]$ChangesetID = "439",
   [string]$user = "UserName",
   [string]$token = "password/token"
)

# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

function CreateJsonBody
{

    $value = @"
[
 {
    "op": "add",
    "path": "/relations/-",
    "value": {
      "rel": "ArtifactLink",
      "url": "vstfs:///VersionControl/Changeset/$ChangesetID",
      "attributes": {
        "name": "Fixed in Changeset"
      }
    }
  }
]

"@

 return $value
}

$json = CreateJsonBody

$uri = "$($collectionurl)/_apis/wit/workitems/$($WorkitemID)?api-version=1.0"
$result = Invoke-RestMethod -Uri $uri -Method Patch -Body $json -ContentType "application/json-patch+json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

答案 1 :(得分:0)

你可能想要查看(没有双关语意)我的TFVC build tasks for VSTS/TFS。它提供您需要的大部分内容。它唯一缺少的是工作项关联,除非您使用更新门控更改。