private static bool ChangeDefinition(IBuildDefinition definition, Options options) { try { var buildType = GetBuildType(definition); //// for now, skip CDN build definitions if (buildType == CustomBuildType.Cdn) return false; if (!CheckTemplates(buildType)) return false; var messages = new StringBuilder(); var changed = SetTemplate(definition, buildType, messages) || SetDropLocation(definition, options, buildType, messages); var paramValues = WorkflowHelpers.DeserializeProcessParameters(definition.ProcessParameters); var config = GetConfiguration(definition, options, buildType); foreach (var c in config) { if (options.SkipParameters != null && options.SkipParameters.Contains(c.Key)) { if (options.Verbose) messages.AppendFormat("Skip parameter '{0}' ('{1}')\r\n", c.Key, Helpers.ObjectToString(c.Value)); } else { changed = changed | AddOrUpdate(paramValues, c.Key, c.Value, messages); } } if (!changed) return false; definition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(paramValues); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Build definition '{0}' ({1}) has changes", definition.Name, buildType); Console.ResetColor(); Console.WriteLine(messages); return true; } catch (Exception ex) { Console.WriteLine(ex); return false; } }
/// <summary> /// Set the default drop location for the builddef according to its type /// </summary> /// <param name="definition"></param> /// <param name="options"></param> /// <param name="buildType"></param> /// <param name="messages"></param> /// <returns></returns> private static bool SetDropLocation(IBuildDefinition definition, Options options, CustomBuildType buildType, StringBuilder messages) { var newLocation = String.Empty; switch (buildType) { case CustomBuildType.StandardDev: case CustomBuildType.NoCompileDev: newLocation = Path.Combine(options.SharedTfsLocation, Constants.DropFolder, Constants.DevFolder); break; case CustomBuildType.StandardMain: case CustomBuildType.NoCompileMain: newLocation = Path.Combine(options.SharedTfsLocation, Constants.DropFolder, Constants.MainFolder); break; case CustomBuildType.StandardRelease: newLocation = "#/"; break; case CustomBuildType.WindowsService: case CustomBuildType.NoCompileRelease: newLocation = ""; break; } if (newLocation == definition.DefaultDropLocation) return false; messages.AppendFormat("[#] DefaultDropLocation: '{0}' => '{1}'\r\n", definition.DefaultDropLocation, newLocation); definition.DefaultDropLocation = newLocation; return true; }
private static Dictionary<string, object> GetConfiguration(IBuildGroupItem definition, Options options, CustomBuildType buildType) { var isMain = buildType == CustomBuildType.StandardMain || buildType == CustomBuildType.NoCompileMain; var isRelease = buildType == CustomBuildType.StandardRelease || buildType == CustomBuildType.NoCompileRelease || buildType == CustomBuildType.WindowsService; string subfolder; if (isRelease) subfolder = Constants.ReleaseFolder; else if (isMain) subfolder = Constants.MainFolder; else subfolder = Constants.DevFolder; Dictionary<string, object> config; switch (buildType) { case CustomBuildType.NoCompileDev: case CustomBuildType.NoCompileMain: case CustomBuildType.NoCompileRelease: config = new Dictionary<string, object> { {"CreateWorkItem", false}, {"IsRelease", isRelease}, {"DeploymentPackagesLocation", buildType == CustomBuildType.NoCompileRelease ? CommonData.DeploymentPackagesLocation : null} }; break; case CustomBuildType.WindowsService: config = new Dictionary<string, object> { {"CreateWorkItem", false}, {"PerformTestImpactAnalysis", false}, {"CreateLabel", true}, {"AssociateChangesetsAndWorkItems", false}, {"ConfigurationsToBuild", (isMain || isRelease) ? new[] {Constants.AnyCpuRelease} : new[] {Constants.AnyCpuDebug}}, {"DisableTests", !isRelease}, {"DropBuild", false}, {"IsRelease", isRelease}, {"CustomBinariesReferencePath", Path.Combine(options.SharedTfsLocation, Constants.AssembliesFolder, isRelease ? Constants.ReleaseFolder : Constants.MainFolder)}, {"CustomBinariesDestination", Path.Combine(options.SharedTfsLocation, Constants.AssembliesFolder, subfolder)}, {"SymbolStorePath", Path.Combine(options.SharedTfsLocation, Constants.SymbolsFolder, subfolder)}, }; break; default: config = new Dictionary<string, object> { {"CreateWorkItem", false}, {"PerformTestImpactAnalysis", false}, {"CreateLabel", true}, {"AssociateChangesetsAndWorkItems", false}, {"ConfigurationsToBuild", (isMain || isRelease) ? new[] {Constants.AnyCpuRelease} : new[] {Constants.AnyCpuDebug}}, {"DisableTests", !isRelease}, {"DropBuild", (isMain || isRelease)}, {"IsRelease", isRelease}, {"DeploymentPackagesLocation", buildType == CustomBuildType.StandardRelease ? CommonData.DeploymentPackagesLocation : null}, {"CustomBinariesReferencePath",Path.Combine(options.SharedTfsLocation, Constants.AssembliesFolder, isRelease ? Constants.ReleaseFolder : Constants.MainFolder)}, {"CustomBinariesDestination", Path.Combine(options.SharedTfsLocation, Constants.AssembliesFolder, subfolder)}, {"SymbolStorePath", Path.Combine(options.SharedTfsLocation, Constants.SymbolsFolder, subfolder)}, }; break; } if (!_externalConfiguration.ContainsKey(definition.Name)) return config; var customConfig = _externalConfiguration[definition.Name]; foreach (var customConfigItem in customConfig) { if (config.ContainsKey(customConfigItem.Key)) config[customConfigItem.Key] = customConfigItem.Value; else { config.Add(customConfigItem.Key, customConfigItem.Value); } } return config; }
static void Main(string[] args) { Console.WriteLine(); Console.WriteLine("-------------------------------------------------------------------------------"); Console.WriteLine("\tTfsUpdateBuildDefinition"); Console.WriteLine(); // Try to parse options from command line var options = new Options(); if (Parser.Default.ParseArguments(args, options)) { try { CommonData = new CommonStructure(options); Console.WriteLine("\tTeam Project Collection: {0}", options.TeamCollection); Console.WriteLine("\tTeam Project: {0}", options.TeamProject); Console.WriteLine("\tShared TFS location: {0}", options.SharedTfsLocation); Console.WriteLine("\tTemplates Team Project: {0}", options.TemplatesTeamProject); Console.WriteLine("\tStandard Template: {0}", CommonData.StandardTemplatePath); Console.WriteLine("\tServices Template: {0}", CommonData.ServicesTemplatePath); Console.WriteLine("\tNo-compile Template: {0}", CommonData.NoCompileFullTemplatePath); Console.WriteLine("\tParallel processing: {0}", options.Parallel); Console.WriteLine("\tData file: {0}", options.DataFile); Console.WriteLine("\tSkip Params: {0}", options.SkipParameters); Console.WriteLine("\tSave build definitions: {0}", options.Save); Console.WriteLine("\tDeployment packages UNC: {0}", CommonData.DeploymentPackagesLocation); _externalConfiguration = ReadDataFile(options.DataFile); if (_externalConfiguration.Any()) { Console.WriteLine("\t{0} build definition configurations read from file", _externalConfiguration.Count); } Console.WriteLine("-------------------------------------------------------------------------------"); var buildDefinitionsToSave = ChangeDefinitions(options); if (buildDefinitionsToSave.Count == 0) Console.WriteLine("All build definitions are up to date!"); else { if (options.Save) { CommonData.BuildServer.SaveBuildDefinitions(buildDefinitionsToSave.ToArray()); Console.WriteLine("Updating {0} build definitions...", buildDefinitionsToSave.Count); } else { Console.WriteLine("The simulation was OK. {0} build definition(s) to update. Use --save to actually update the build definition.", buildDefinitionsToSave.Count); } } } catch (Exception ex) { Console.WriteLine("\nAn error occured:\n{0}\n", ex.Message); } } else { Console.WriteLine("Couldn't read options!"); Console.WriteLine(); } }
private static List<IBuildDefinition> ChangeDefinitions(Options options) { var buildDefinitionResults = Helpers.QueryBuildDefinitions(CommonData.CommonStructureService, CommonData.BuildServer, options.TeamProject, options.BuildName); var buildDefinitionsToSave = new List<IBuildDefinition>(); foreach (var buildDefinitionResult in buildDefinitionResults) { if (buildDefinitionResult.Failures != null && buildDefinitionResult.Failures.Length > 0) { // print out the errors foreach (var f in buildDefinitionResult.Failures) Console.WriteLine(f.Code + ": " + f.Message); } // There still might be some definitions to modify in this result var nonNullBuildDefs = buildDefinitionResult.Definitions.Where(buildDefinition => buildDefinition != null); if (options.Parallel) Parallel.ForEach(nonNullBuildDefs, buildDefinition => { if (ChangeDefinition(buildDefinition, options)) buildDefinitionsToSave.Add(buildDefinition); }); else foreach (var buildDefinition in nonNullBuildDefs) { if (ChangeDefinition(buildDefinition, options)) buildDefinitionsToSave.Add(buildDefinition); } } return buildDefinitionsToSave; }