Querying builds from TFS with QueryBuilds has very low performance

Viewed 105

I'm trying to reach each build in my local TFS 2015 server which has the "Retain Indefinitely" flag (BuildDetail.KeepForever Property) yet the QueryBuilds() function takes too long to get all of the builds.

TFS 2015 'Retain Indefinitely' Web GUI Menu Option

All I actually need is the KeepForever and the DropLocation properties.

I Found out you can get better efficiency using the IBuildDetailSpec interface yet I couldn't find an option in which I'll get the KeepForever property.

My current code snippet:

public void BackupOnlyRetainedBuilds(string TeamProjectName, string DestinationPath)
{
    defs[...]

    Uri configurationServerUri = new Uri("http://builder:8080/tfs");
    TfsTeamProjectCollection server = new TfsTeamProjectCollection(configurationServerUri);

    //get builds server
    buildServer = (IBuildServer)server.GetService(typeof(IBuildServer));

    //set up an array of all build definition from a spcific team project.
    IBuildDefinition[] bda = buildServer.QueryBuildDefinitions(TeamProjectName);

    //check each build definition.
    foreach (var buildDefinition in bda)
    {
        //set an array of builds history.
        IBuildDetail[] bha = buildDefinition.QueryBuilds();

        //check each build from build history build details.
        foreach (var buildDetails in bha)
        {
            //check if build is retained.
            if (buildDetails.KeepForever == true)
            {
                string dropLocationPath = buildDetails.DropLocation;

                //check if drop folder exists.
                if (Directory.Exists(dropLocationPath))
                {
                    //create all of the directories.
                    foreach (string dirPath in Directory.GetDirectories(dropLocationPath, "*",
                        SearchOption.AllDirectories))
                        Directory.CreateDirectory(dirPath.Replace(dropLocationPath, DestinationPath));

                    //copy all the files & Replaces any files with the same name.
                    foreach (string newPath in Directory.GetFiles(dropLocationPath, "*.*",
                        SearchOption.AllDirectories))
                        File.Copy(newPath, newPath.Replace(dropLocationPath, DestinationPath), true);
                }
            }
        }
    }
}
1 Answers

You can tell QueryBuilds to not grab all the build details, but only the ones you're interested in, from my patched version of tfsbuild.exe:

buildDetailSpec = this.BuildServer.CreateBuildDetailSpec(...)
buildDetailSpec.QueryDeletedOption = !forDestroy ? QueryDeletedOption.IncludeDeleted : QueryDeletedOption.OnlyDeleted;
buildDetailSpec.InformationTypes = null;
IBuildQueryResult buildQueryResult = this.BuildServer.QueryBuilds(buildDetailSpec);

Or alternatively use QueryBuildsUri and pass it (string[]) null, QueryOptions.None:

IBuildDetail[] buildDetailArray = this.BuildServer.QueryBuildsByUri(list2.ToArray(), (string[]) null, QueryOptions.None, QueryDeletedOption.IncludeDeleted);

You may need to pass it a specific set of InformationTypes depending on the data you need as part of your backup tool.

Related