1

我安装了一个 TFS2012 作为测试系统,并在我们投入生产之前进行了一些测试。这包括定义许多 BuildDefinitions,这是很多工作。

测试成功后,将安装一个带有 TFS2012 的新服务器。

对于这个新服务器 - 然后作为生产系统运行 - 我想从测试系统恢复 BuildDefinitions。但只有 BuildDefinitions,而不是整个 TeamCollections。因为我运行了测试签入,我不想在我的生产服务器上运行这些。

现在,是否可以仅备份和恢复 BuildDefinitions?

也许可以直接通过 Sql 数据库?但我有点害怕那里的引用,指向其他一些表。

最好的问候,彼得布赫

4

2 回答 2

1

最后我决定不碰数据库,因为有很多其他表的引用。

我使用了 TFS API v11 (TFS2012) 和一点 C# 代码,我从这个基础上满足了我的需求:如何复制 TFS 2010 构建定义?

它将所有构建定义从一个 TFS2012 服务器复制到另一个。对于这两个服务器,都需要指定一个 TeamCollection 和一个 TeamProject。

因此,必须按 TeamProject 完成复制任务。

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

namespace TFSBuildDefinitionCreator
{

internal class Program
{
    private static void Main(string[] args)
    {
        // Copies build definitions from one server to another.
        // Uses the TeamFoundation API V11 (TFS2012).
        // Code was used to copy b uild definitions from a test server to a productive.

        string sourceServer = "http://testTfs:8080/tfs/MyTeamCollection";
        string sourceTeamProject = "MyTeamProject";

        string targetServer = "https://productiveTfs:8080/tfs/MyTeamCollection";
        string targetTeamProject = "MyTeamProject";

        // DropLocation for defininitions: Share on which the build should be dropped.
        string defaultDropLocation = "\\\\MyBuildserver\\Builds$";

        // Change the DefaultProcessTemplate in the following method below:         GetDefaultProcessTemplateByServerPathFromBuildServer.

        CopyBuildDefinitions(sourceServer, sourceTeamProject, targetServer, targetTeamProject, defaultDropLocation);

        Console.Read();
    }

    private static IBuildServer GetBuildServerFromServerUrl(string serverUrl)
    {
        var tfs = TeamFoundationServerFactory.GetServer(serverUrl);
        return (IBuildServer)tfs.GetService(typeof(IBuildServer));
    }

    private static IBuildController GetDefaultBuildControllerFromBuildServer(IBuildServer buildServer)
    {
        return buildServer.QueryBuildControllers()[0];
    }

    private static IProcessTemplate GetDefaultProcessTemplateByServerPathFromBuildServer(IBuildServer buildServer, string teamProject)
    {
        var processTemplates = buildServer.QueryProcessTemplates(teamProject);
        var result = processTemplates.First(t => t.ServerPath.Contains("/BuildProcessTemplates/MyDefaultTemplate.xaml"));

        return result;
    }

    private static void CopyBuildDefinitions(string sourceServer, string sourceTeamProject, string targetServer,
                                             string targetTeamProject, string defaultDropLocation)
    {
        var sourceBuildServer = GetBuildServerFromServerUrl(sourceServer);
        var sourceBuildDetails = sourceBuildServer.QueryBuildDefinitions(sourceTeamProject);

        foreach (var sourceBuildDetail in sourceBuildDetails)
        {
            CopyBuildDefinition(sourceBuildDetail, targetServer, targetTeamProject, defaultDropLocation);
        }
    }

    private static void CopyBuildDefinition(IBuildDefinition buildDefinition, string targetServer, string targetTeamProject, string defaultDropLocation)
    {
        var targetBuildServer = GetBuildServerFromServerUrl(targetServer);

        var buildDefinitionClone = targetBuildServer.CreateBuildDefinition(targetTeamProject);

        buildDefinitionClone.BuildController = GetDefaultBuildControllerFromBuildServer(targetBuildServer);
        buildDefinitionClone.ContinuousIntegrationType = buildDefinition.ContinuousIntegrationType;
        buildDefinitionClone.ContinuousIntegrationQuietPeriod = buildDefinition.ContinuousIntegrationQuietPeriod;

        // Noch ändern.
        //buildDefinitionClone.DefaultDropLocation = buildDefinition.DefaultDropLocation;
        buildDefinitionClone.DefaultDropLocation = defaultDropLocation;

        buildDefinitionClone.Description = buildDefinition.Description;
        buildDefinitionClone.Enabled = buildDefinition.Enabled;

        //buildDefinitionClone.Name = String.Format("Copy of {0}", buildDefinition.Name);
        buildDefinitionClone.Name = buildDefinition.Name;

        //buildDefinitionClone.Process = buildDefinition.Process;
        buildDefinitionClone.Process = GetDefaultProcessTemplateByServerPathFromBuildServer(targetBuildServer, targetTeamProject);

        buildDefinitionClone.ProcessParameters = buildDefinition.ProcessParameters;

        foreach (var schedule in buildDefinition.Schedules)
        {
            var newSchedule = buildDefinitionClone.AddSchedule();
            newSchedule.DaysToBuild = schedule.DaysToBuild;
            newSchedule.StartTime = schedule.StartTime;
            newSchedule.TimeZone = schedule.TimeZone;
        }

        foreach (var mapping in buildDefinition.Workspace.Mappings)
        {
            buildDefinitionClone.Workspace.AddMapping(
                mapping.ServerItem, mapping.LocalItem, mapping.MappingType, mapping.Depth);
        }

        buildDefinitionClone.RetentionPolicyList.Clear();

        foreach (var policy in buildDefinition.RetentionPolicyList)
        {
            buildDefinitionClone.AddRetentionPolicy(
                policy.BuildReason, policy.BuildStatus, policy.NumberToKeep, policy.DeleteOptions);
        }

        buildDefinitionClone.Save();
    }
}

}

希望对其他人有所帮助。

于 2014-01-13T10:11:11.563 回答
1

构建定义不受源代码控制。唯一的选择是依赖 TFS 数据库备份,在该备份中可以恢复或查看Tfs_DefaultCollection数据库中的tbl_BuildDefinition*表。

此功能有用户声音,您也可以使用 TFS API 来完成。

添加对 uservoice 的投票:

提供一种版本控制构建定义的方法

使用 TFS API

如何复制 TFS 2010 构建定义?

于 2013-01-31T04:26:00.233 回答