4

我在 TFS 中使用 Workspace.Checkin 命令时遇到错误,因为我尝试签入的文件是门控构建定义的一部分。有很多人询问如何使用 TFS API 覆盖门控签到。但一个非常不同的问题是:如果我真的以编程方式执行门控签到怎么办?如何在 TFS API 中触发它?

我想做的是:

  1. 对一组挂起的更改执行正常的签入操作
  2. 接收有关已启动的封闭式构建的信息
  3. 订阅该构建的完成事件,或轮询构建直到它完成。
  4. 如果构建成功并提交更改,则继续(如果可能,获取生成的更改集)
  5. 如果构建不成功则停止,并报告错误。

我找不到任何东西来回答这个问题;也许这是一个极端情况,我是唯一一个疯狂到想要这样做的人。也就是说,我对此的需求是合法的。我唯一能想到的是,我需要通过门控签入过程的较低级别功能:1)遍历构建定义以查看任何文件的路径是否与任何路径一致在任何封闭式构建中。2) 如果存在交叉点,则创建挂起更改的搁置集 3) 使用搁置集对门控定义的新构建进行排队 4) 查询构建定义并刷新信息,直到构建状态完成 5) 如果构建成功,取消搁置挂起的更改,然后使用覆盖签入。

但是,请注意,即使我执行了这些步骤,生成的构建也不会看起来像一个封闭的构建。将发送策略覆盖通知,让某人知道实际执行构建的唯一方法是将此类信息包含在策略覆盖注释中。有没有更直接的方法可以让它看起来像任何其他封闭式构建?

4

2 回答 2

8

在 Scordo 的帖子的提示下,我能够弄清楚如何做到这一点。这是代码:

//Initialize connection to server
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(ServerAddress));
try
{
    tpc.EnsureAuthenticated();
}
catch (Exception e)
{
    System.Environment.Exit(-1);
}
VersionControlServer vcServer = tpc.GetService<VersionControlServer>();
IBuildServer buildServer = tpc.GetService<IBuildServer>();

//.
//.
//Program logic goes here...
//.
//.

//Get the workspace and the respective changes
Workspace workspace = vcServer.TryGetWorkspace(LocalProjectPath);  
PendingChange[] changes = workspace.GetPendingChanges();  

//Perform the check-in
bool checkedIn = false;

//Either wait for the gated check-in or continue asynchronously...  
bool waitForGatedCheckin = true;  

//Attempt a normal check-in
try
{
    //First, see what policy failures exist, and override them if necessary
    CheckinEvaluationResult result = workspace.EvaluateCheckin(CheckinEvaluationOptions.All, 
    changes, changes, "Test", null, null);

    //Perform the check-in, with overrides if necessary, including Work Item policies
    //or include additional code to comply with those policies
    PolicyOverrideInfo override = null;
    if (result.PolicyFailures != null)
    {
        override = new PolicyOverrideInfo("override reason", result.PolicyFailures);
    }
    workspace.CheckIn(changes, comment, null, null, override);
    checkedIn = true;
}
catch (GatedCheckinException gatedException)
{
    //This exception tells us that a gated check-in is required.
    //First, we get the list of build definitions affected by the check-in
    ICollection<KeyValuePair<string, Uri>> buildDefs = gatedException.AffectedBuildDefinitions;

    if (buildDefs.Count == 1)
    {
        //If only one affected build definition exists, then we have everything we need to proceed
        IEnumerator<KeyValuePair<string, Uri>> buildEnum = buildDefs.GetEnumerator();
        buildEnum.MoveNext();
        KeyValuePair<string, Uri> buildDef = buildEnum.Current;
        String gatedBuildDefName = buildDef.Key;
        Uri gatedBuildDefUri = buildDef.Value;
        string shelvesetSpecName = gatedException.ShelvesetName;
        string[] shelvesetTokens = shelvesetSpecName.Split(new char[] { ';' });

        //Create a build request for the gated check-in build
        IBuildRequest buildRequest = buildServer.CreateBuildRequest(gatedBuildDefUri);  
        buildRequest.ShelvesetName = shelvesetTokens[0]; //Specify the name of the existing shelveset
        buildRequest.Reason = BuildReason.CheckInShelveset; //Check-in the shelveset if successful 
        buildRequest.GatedCheckInTicket = gatedException.CheckInTicket; //Associate the check-in

        //Queue the build request
        IQueuedBuild queuedBuild = buildServer.QueueBuild(buildRequest);

        //Wait for the build to complete, or continue asynchronously
        if (waitForGatedCheckin)
        {
            while (!queuedBuild.Build.BuildFinished)
            {
                //Get the latest status of the build, and pause to yield CPU
                queuedBuild.Refresh(QueryOptions.Process);  
                System.Threading.Thread.Sleep(1000)
            }
            if (queuedBuild.Build.Status == BuildStatus.Succeeded)
            {
                checkedIn = true;
            }
        }
    }
    else
    {
        //Determine a method for specifying the appropriate build definition
        //if multiple build definitions are affected
    }
}
catch (CheckinException checkinException)
{
    //Handle other checkin exceptions such as those occurring with locked files, 
    //permissions issues, etc.
}

if (checkedIn)
{
    //Additional logic here, if the check-in was successful
}
于 2014-04-09T16:45:17.710 回答
4

我以前从未这样做过,但这应该对您有所帮助:

当您使用工作区签入更改并且此签入受门控构建保护时,将引发GatedCheckinException。此异常应具有创建搁置集和触发使用该搁置集的正确构建的所有必要信息。例如,该AffectedBuildDefinitions属性应包含作为门控构建定义的构建定义。

希望有帮助。

于 2014-03-26T09:35:52.810 回答