TFS2010 - Wrong changeset appearing at SourceGetVersion

試著忘記壹切 提交于 2019-12-02 19:07:58

Finally I found out what is going on:

Basically The changeset that can be seen in my picture 1 is always the latest changeset of the entire Team Project Collection. It is the property "SourceGetVersion" on the object "BuildDetails" of type "IBuildDetails".

I think this is a bug which can be worked around: If you change the BuildDetails.SourceGetVersion (which is a string) to some other value, then the build summary will show the updated string. Furthermore, it is then saved correctly to the collection database.

What I have done in order to add the correct changeset number is I have created a custom build activity that takes the branch which should be build as input parameter. It outputs the correct changeset. The activity finds out the correct changeset by connecting to the TFS and downloading the History. Then it looks at all the items in the history and outputs the largest changeset number. Here is the code of that activity:

using System.Activities;
using System.Collections;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Build.Client;

namespace SourceGetVersionActivity
{
    [BuildActivity(HostEnvironmentOption.All)]
    public sealed class SourceGetVersionActivity : CodeActivity<string>
    {
        // Define an activity input argument of type string
        public InArgument<string> Branch { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override string Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            string branch = context.GetValue(this.Branch);

            ICredentials account = new NetworkCredential("Useranme", "password", "domain");

            // connect / authenticate with tfs
            TeamFoundationServer tfs = new TeamFoundationServer("http://tfs:8080/tfs/CollectionName", account);
            tfs.Authenticate();

            // get the version control service
            VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));

            IEnumerable changesets = versionControl.QueryHistory(branch, VersionSpec.Latest, 0, RecursionType.Full,
                null, null, null, int.MaxValue, false, false, false, false);

            int maxVersion = 0;

            foreach (Changeset c in changesets)
            {
                if (c.ChangesetId > maxVersion)
                {
                    maxVersion = c.ChangesetId;
                }
            }

            return string.Concat('C', maxVersion.ToString());
        }
    }
}

I call this activity as soon as possible (after the GetBuild activity).

Basically in the BuildProcessTemplate I have added an Argument (string) "Branch" which needs to be filled with a string that points to the top folder that is being build. The custom activity takes that as input and outputs a string which is the correct changeset id. The BuildDetail.SourceGetVersion property will then be overriden by the correct changeset id.

I find it really strange that no-one else seems to have encountered this problem. I could not find any person on the internet with the same problem. Anyway, I hope this answer helps someone else in the future as well.

EDIT - Writing the above code directly in Workflow Foundation:

To get the correct changeset using more compact code and avoiding custom activites, it is also possible to use Workflow Foundation directly. Below is the "code" (doing exactly what is done in above C# code):

(1) The GetTeamProjectCollection activity gets the current collection. I am saving it inside the TeamProjectCollection variable (see bottom of the picture). Important: The variable needs to be defined inside this sequence, if you define it in outer scope, an error will occur: "Unable to serialize type 'Microsoft.TeamFoundation.Client.TfsTeamProjectCollection'. Verify that the type is public and either has a default constructor or an instance descriptor."

(2) Foreach "changeset" in "TeamProjectCollection.GetService(Of VersionControlServer).QueryHistory(Branch, VersionSpec.Latest, 0, RecursionType.Full, Nothing, Nothing, Nothing, Integer.MaxValue, False, False, False).Cast(Of Changeset)()" The TypeArgument of the Foreach loop is "Microsoft.TeamFoundation.VersionControl.Client.Changeset". This expression gets the version control object from the collection, calls it "QueryHistory" method which returns an IEnumerable with all changesets.

(3) So we are iterating over all changesets and looking at the ChangesetId. Then saving the maximum ChangesetId to the variable "maxId".

(4) At the end, BuildDetails.SourceGetVersion = "C" + maxId.ToString(). The "C" indicates, that the version is a changeset.

I hope someone finds this piece of "Code" useful!

Christian

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!