C# 将生成定义从JSon文件导出/导入到JSon文件(TFS 2013)

C# 将生成定义从JSon文件导出/导入到JSon文件(TFS 2013),c#,tfsbuild,C#,Tfsbuild,我正在尝试从tfs2013导出和导入构建定义,如下所示,但它们都不适用于我。我知道有一些tfs插件可以做到这一点,但由于公司政策的限制,我不能使用它们中的任何一个 GetDefinitionAsync和GetFullDefinitionsAsync方法很好,但它们不检索ProcessParameters属性,因此我无法导出包含此重要信息的完整构建定义。我试图通过调用IBuildServer.QueryBuildDefinitions获取此属性,但当我尝试创建新的生成定义时,我无法获取,因为数据类

我正在尝试从tfs2013导出和导入构建定义,如下所示,但它们都不适用于我。我知道有一些tfs插件可以做到这一点,但由于公司政策的限制,我不能使用它们中的任何一个

GetDefinitionAsync和GetFullDefinitionsAsync方法很好,但它们不检索ProcessParameters属性,因此我无法导出包含此重要信息的完整构建定义。我试图通过调用IBuildServer.QueryBuildDefinitions获取此属性,但当我尝试创建新的生成定义时,我无法获取,因为数据类型是Microsoft.TeamFoundation.build.Client.IBuildDefinition,并且我无法创建Microsoft.TeamFoundation.build.Client.BuildDefinition的新实例,因为它是一个密封类。如何复制ProcessParameters和其他信息以导入完整的生成定义


感谢对于XAML构建,您需要使用方法首先获取构建定义,然后进行复制

首先,通过调用
tfstreamprojectcollection
实例上的
GetService
方法获取对构建服务器的引用。一旦您有了构建服务器引用,您就可以加载您正在制作副本的构建定义

如果要复制包含流程参数的生成定义,则还应首先复制模板。示例代码sinnper

  // Copy Process parameters
  newBuildDefinition.Process = buildDefinitionToCopy.Process;
  var processParams = WorkflowHelpers.DeserializeProcessParameters(buildDefinitionToCopy.ProcessParameters);
  var copyProcessParams = WorkflowHelpers.DeserializeProcessParameters(newBuildDefinition.ProcessParameters);
 foreach (KeyValuePair<string, object> entry in processParams)
  {
      copyProcessParams.Add(entry.Key.ToString(), entry.Value);
  }
 newBuildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(copyProcessParams);
//复制过程参数
newBuildDefinition.Process=buildDefinitionToCopy.Process;
var processParams=WorkflowHelpers.DeserializeProcessParameters(buildDefinitionToCopy.ProcessParameters);
var copyProcessParams=WorkflowHelpers.DeserializeProcessParameters(newBuildDefinition.ProcessParameters);
foreach(processParams中的KeyValuePair条目)
{
copyProcessParams.Add(entry.Key.ToString(),entry.Value);
}
NewBuilderDefinition.ProcessParameters=WorkflowHelpers.SerializeProcessParameters(copyProcessParams);

关于如何通过API实现复制的更多详细信息,您可以参考本博客--

好的,经过深入研究,我终于找到了导出/导入的方法

导出到JSon:

    public static void ExportBuildDef(Microsoft.TeamFoundation.Build.Client.IBuildDefinition buildDefinition, string project, string filePath)
    {
        Console.WriteLine($"Exporting build definition '{buildDefinition.Name}' from '{project}' project.");

        var json = JsonConvert.SerializeObject(
            buildDefinition, 
            Newtonsoft.Json.Formatting.Indented, 
            new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });

        json = removePasswords(json);

        File.WriteAllText(filePath, json);
        Console.WriteLine($"Build definition '{buildDefinition.Name}' succesfully exported to '{filePath}'.");
    }

    private static string removePasswords(string json)
    {
        string res = json;

        var searchFor = "\"Password\":";
        var startIndex = json.IndexOf(searchFor);
        if (startIndex >= 0)
        {
            var endIndex = json.IndexOf(",", startIndex);
            var pwd = json.Substring(startIndex, endIndex - startIndex);
            if (pwd.IndexOf(":") > 0)
            {
                pwd = json.Substring(startIndex, endIndex - startIndex).Split(':')[1].Trim();
                res = json.Replace(pwd, "\"{hidden}\"");
            }

        }

        return res;
    }
从JSon导入

注意:BuildDefinitionModel类是一组“POCO”类(不包括长文件),可以从从导出的JSon文件转换为C类

public static void ImportBuildDefinition(IBILDServer buildServer、string projectName、string filePath、string newBuildName、string sourceProvider)
{
如果(!File.Exists(filePath))
抛出新的FileNotFoundException(“文件不存在!”,filePath);
WriteLine($“正在将生成定义从文件“{filePath}”导入到“{projectName}”项目中。”);
var json=File.ReadAllText(文件路径);
var buildDef=JsonConvert.DeserializeObject(json);
var newBuildDefinition=CloneBuildDefinition(buildServer、buildDef、newBuildName、projectName、sourceProvider);
WriteLine($“生成定义”{buildDef.Name}已成功导入到“{projectName}”项目中。”);
}
静态IBuildDefinition CloneBuildDefinition(IBuildServer buildServer、BuildDefinitionModel buildDefinitionSource、string newBuildName、string projectName、string sourceProvider)
{
var buildDefinitionClone=buildServer.CreateBuildDefinition(projectName);
buildDefinitionClone.BuildController=GetBuildController(buildServer,“”);
buildDefinitionClone.Process=buildServer.QueryProcessTemplates(buildDefinitionSource.TeamProject).FirstOrDefault(c=>c.Id==buildDefinitionSource.Process.Id);
buildDefinitionClone.ProcessParameters=buildDefinitionSource.ProcessParameters;
buildDefinitionClone.TriggerType=buildDefinitionSource.TriggerType;
buildDefinitionClone.ContinuousIntegrationQuietPeriod=buildDefinitionSource.ContinuousIntegrationQuietPeriod;
buildDefinitionClone.DefaultDropLocation=buildDefinitionSource.DefaultDropLocation;
buildDefinitionClone.Description=buildDefinitionSource.Description;
buildDefinitionClone.QueueStatus=Microsoft.TeamFoundation.Build.Client.DefinitionQueueStatus.Enabled;
buildDefinitionClone.BatchSize=buildDefinitionSource.BatchSize;
buildDefinitionClone.Name=newBuildName;
foreach(buildDefinitionSource.Schedules中的var计划)
{
var newSchedule=buildDefinitionClone.AddSchedule();
newSchedule.DaysToBuild=schedule.DaysToBuild;
newSchedule.StartTime=schedule.StartTime;
newSchedule.TimeZone=schedule.TimeZone;
}
foreach(buildDefinitionSource.Workspace.Mappings中的变量映射)
{
buildDefinitionClone.Workspace.AddMapping(
mapping.ServerItem、mapping.LocalItem、mapping.MappingType、mapping.Depth);
}
buildDefinitionClone.RetentionPolicyList.Clear();
foreach(buildDefinitionSource.RetentionPolicyList中的var策略)
{
buildDefinitionClone.AddRetentionPolicy(
policy.BuildReason、policy.BuildStatus、policy.NumberToKeep、policy.DeleteOptions);
}
//源提供程序
IBuildDefinitionSourceProvider provider=buildDefinitionClone.CreateInitialSourceProvider(sourceProvider);
如果(sourceProvider==VersionControlType.TFGIT.ToString())
{
provider.Fields[“RepositoryName”]=“Git”;
}
buildDefinitionClone.SetSourceProvider(提供程序);
buildDefinitionClone.Save();
返回buildDefinitionClone;
}
专用静态IBuildController GetBuildController(IBuildServer buildServer、字符串buildController)
{
if(string.IsNullOrEmpty(buildController))
返回buildServer.QueryBuildControllers(false).Where(c=>c.Status==ControllerStatus.Available).First();
返回buildServer.GetBuildControl
public static void ImportBuildDefinition(IBuildServer buildServer, string projectName, string filePath, string newBuildName, string sourceProvider)
    {
        if (!File.Exists(filePath))
            throw new FileNotFoundException("File does not exist!", filePath);

        Console.WriteLine($"Importing build definition from file '{filePath}' to '{projectName}' project.");
        var json = File.ReadAllText(filePath);
        var buildDef = JsonConvert.DeserializeObject<BuildDefinitionModel>(json);

        var newBuildDefinition = CloneBuildDefinition(buildServer, buildDef, newBuildName, projectName, sourceProvider);

        Console.WriteLine($"Build definition '{buildDef.Name}' succesfully imported to '{projectName}' project.");
    }

    static IBuildDefinition CloneBuildDefinition(IBuildServer buildServer, BuildDefinitionModel buildDefinitionSource, string newBuildName, string projectName, string sourceProvider)
    {
        var buildDefinitionClone = buildServer.CreateBuildDefinition(projectName);

        buildDefinitionClone.BuildController = GetBuildController(buildServer, "");
        buildDefinitionClone.Process = buildServer.QueryProcessTemplates(buildDefinitionSource.TeamProject).FirstOrDefault(c=> c.Id == buildDefinitionSource.Process.Id);
        buildDefinitionClone.ProcessParameters = buildDefinitionSource.ProcessParameters;
        buildDefinitionClone.TriggerType = buildDefinitionSource.TriggerType;
        buildDefinitionClone.ContinuousIntegrationQuietPeriod = buildDefinitionSource.ContinuousIntegrationQuietPeriod;
        buildDefinitionClone.DefaultDropLocation = buildDefinitionSource.DefaultDropLocation;
        buildDefinitionClone.Description = buildDefinitionSource.Description;
        buildDefinitionClone.QueueStatus = Microsoft.TeamFoundation.Build.Client.DefinitionQueueStatus.Enabled;
        buildDefinitionClone.BatchSize = buildDefinitionSource.BatchSize;
        buildDefinitionClone.Name = newBuildName;

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

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

        buildDefinitionClone.RetentionPolicyList.Clear();

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

        //Source Provider
        IBuildDefinitionSourceProvider provider = buildDefinitionClone.CreateInitialSourceProvider(sourceProvider);
        if (sourceProvider == VersionControlType.TFGIT.ToString())
        {
            provider.Fields["RepositoryName"] = "Git";
        }
        buildDefinitionClone.SetSourceProvider(provider);


        buildDefinitionClone.Save();
        return buildDefinitionClone;
    }

    private static IBuildController GetBuildController(IBuildServer buildServer, string buildController)
    {
        if (string.IsNullOrEmpty(buildController))
            return buildServer.QueryBuildControllers(false).Where(c=> c.Status == ControllerStatus.Available).First();

        return buildServer.GetBuildController(buildController);
    }