static void Main(string[] args) { OptionSet option_set = new OptionSet() .Add("?|help|h", "Prints out the options.", option => { help = option != null; }) .Add("su|source-url=", "Set the source VSTS account URL (https://[sourcerepo].visualstudio.com)", option => sourceUrl = option) .Add("sp|source-project=", "Set the source VSTS project", option => sourceProject = option) .Add("sr|source-repository=", "Set the source VSTS repository path. (ex: $/SourceRepo)", option => sourceRepo = option) .Add("du|destination-url=", "Set the destination VSTS account URL (https://[destrepo].visualstudio.com)", option => destinationUrl = option) .Add("dp|destination-project=", "Set the destination VSTS project", option => destinationProject = option) .Add("dr|destination-repository=", "Set the destination VSTS repository path. (ex: $/DestinationRepo)", option => destinationRepo = option); try { option_set.Parse(args); } catch (Exception ex) { LogGenericException(ex, "Error on commandline parse"); } if (help) { ShowHelp(usage, option_set); } if (string.IsNullOrEmpty(sourceUrl)) { Console.Write("Enter the source account url (https://<<account>>.visualstudio.com/): "); sourceUrl = Console.ReadLine(); } if (string.IsNullOrEmpty(sourceProject)) { Console.Write("Enter the source project: "); sourceProject = Console.ReadLine(); } if (string.IsNullOrEmpty(sourceRepo)) { Console.Write("Enter the source repository ($/MYSOURCEREPO): "); sourceRepo = Console.ReadLine(); } if (string.IsNullOrEmpty(destinationUrl)) { Console.Write("Enter the destination account url (https://<<account>>.visualstudio.com/): "); destinationUrl = Console.ReadLine(); } if (string.IsNullOrEmpty(destinationProject)) { Console.Write("Enter the destination project: "); destinationProject = Console.ReadLine(); } if (string.IsNullOrEmpty(destinationRepo)) { Console.Write("Enter the source repository ($/MYDESTREPO): "); destinationRepo = Console.ReadLine(); } string sourceAccount = $"{sourceUrl}DefaultCollection"; string destinationAccount = $"{destinationUrl}DefaultCollection"; // Interactively ask the user for credentials VssCredentials sourceCredentials = new VssClientCredentials(); sourceCredentials.Storage = new VssClientCredentialStorage(); VssCredentials destinationCredentials = new VssClientCredentials(); destinationCredentials.Storage = new VssClientCredentialStorage(); BuildHttpClient sourceBuildClient = null; BuildHttpClient destinationBuildClient = null; ProjectHttpClient destinationProjectClient = null; TaskAgentHttpClient destinationTaskAgentClient = null; TfvcHttpClient destinationTfvcClient = null; try { Console.WriteLine($"Creating VSTS connections and clients."); Console.WriteLine(); // Connect to VSTS Source and Destination VssConnection sourceConnection = new VssConnection(new Uri(sourceAccount), sourceCredentials); Console.WriteLine($"Authorized acccount {sourceUrl} as {sourceConnection.AuthorizedIdentity.DisplayName} <{sourceConnection.AuthorizedIdentity.Descriptor.Identifier}>"); VssConnection destinationConnection = new VssConnection(new Uri(destinationAccount), destinationCredentials); Console.WriteLine($"Authorized acccount {destinationUrl} as {destinationConnection.AuthorizedIdentity.DisplayName} <{sourceConnection.AuthorizedIdentity.Descriptor.Identifier}>"); Console.WriteLine(); // Get a number of HttpClients to read and write data Console.WriteLine("Creating source build client."); sourceBuildClient = sourceConnection.GetClient <BuildHttpClient>(); Console.WriteLine("Creating destination build client."); destinationBuildClient = destinationConnection.GetClient <BuildHttpClient>(); Console.WriteLine("Creating destination project client."); destinationProjectClient = destinationConnection.GetClient <ProjectHttpClient>(); Console.WriteLine("Creating destination task agent client."); destinationTaskAgentClient = destinationConnection.GetClient <TaskAgentHttpClient>(); Console.WriteLine("Creating destination TFVC client."); destinationTfvcClient = destinationConnection.GetClient <TfvcHttpClient>(); Console.WriteLine(); } catch (AggregateException ex) { string message = "Error creating connections."; LogAggregateException(ex, message); } catch (Exception ex) { string message = "Error creating connections."; LogGenericException(ex, message); } List <BuildDefinition> sourceBuildDefs = null; TeamProject destinationProjectObject = null; Dictionary <string, TaskAgentQueue> agentDictionary = null; try { sourceBuildDefs = sourceBuildClient.GetFullDefinitionsAsync(project: sourceProject).Result; } catch (AggregateException ex) { string message = "Error retreiving objects from source."; LogAggregateException(ex, message); } catch (Exception ex) { string message = "Error retreiving objects from source."; LogGenericException(ex, message); } try { destinationProjectObject = destinationProjectClient.GetProject(destinationProject).Result; var projectAgentQueues = destinationTaskAgentClient.GetAgentQueuesAsync(project: destinationProject).Result; agentDictionary = projectAgentQueues.ToDictionary(k => k.Name); } catch (AggregateException ex) { string message = "Error retreiving objects from destination."; LogAggregateException(ex, message); } catch (Exception ex) { string message = "Error retreiving objects from destination."; LogGenericException(ex, message); } foreach (var item in sourceBuildDefs) { if (System.Diagnostics.Debugger.IsAttached) { item.Name = item.Name + DateTime.Now.ToUnixEpochTime(); } item.Project = destinationProjectObject; item.AuthoredBy = null; // Remove any author to avoid errors in transfer FixTriggerRepositories(item); UpdateAgentPool(agentDictionary, item); ConvertRepositoryPath(item); try { Console.WriteLine($"Adding build definition: {item.Name}"); var itemOut = destinationBuildClient.CreateDefinitionAsync(item).Result; } catch (AggregateException ex) { LogAggregateException(ex, $"Error creating build {item.Name} on {destinationAccount}"); } catch (Exception ex) { LogGenericException(ex, $"Error creating build {item.Name} on {destinationAccount}"); } } if (hasErrors) { ExitWithErrors(); } ExitSuccess(); }