【问题标题】:TFS 2017 vNext Build Get workspace with powershellTFS 2017 vNext Build 使用 powershell 获取工作区
【发布时间】:2018-05-24 21:55:50
【问题描述】:

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

  • 通过源路径获取 Workspace ($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)

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

有人有很好的工作示例或解决方案吗?

我考虑过其他选择。也许我可以编写一个可执行文件来完成我的工作。

我可以在没有工作区的情况下签入,然后再关联工作项吗?如何以编程方式将工作项与现有变更集相关联?

【问题讨论】:

  • 在构建过程中您是如何更改文件的?它将在获取源步骤期间创建一个本地工作区。因此,您可以直接从该工作区签入更改并绕过签入策略。

标签: powershell tfs azure-devops azure-pipelines


【解决方案1】:

如果没有工作区,您将无法签入。

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

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

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

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

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

带有客户端 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)}

【讨论】:

  • 这个解决方案对我有用。非常感谢! :-D 正如您所说,代理在签入覆盖策略方面存在问题。我们更新了客户端,错误消息并没有消失,但是文件被签入了。真的很奇怪。 :-)
【解决方案2】:

您可能想查看(不是双关语)我的TFVC build tasks for VSTS/TFS。它提供了您需要的大部分东西。它唯一遗漏的是工作项关联,除非您使用 Update Gated Changes。

【讨论】:

    猜你喜欢
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 2016-09-22
    • 2016-01-23
    相关资源
    最近更新 更多