private async Task<TimeSpan> GetLastSuccesfulBuildTimeRest(TfsTeamProjectCollection teamProjectCollection, DefinitionReference definitionReference, BuildHttpClient httpClient) { var buildTime = new TimeSpan(); try { var lastSuccessFullList = await httpClient.GetBuildsAsync(definitions: new List<int> { definitionReference.Id }, project: definitionReference.Project.Id, resultFilter: BuildResult.Succeeded, statusFilter: Microsoft.TeamFoundation.Build.WebApi.BuildStatus.Completed, top: 1).ConfigureAwait(false); var build = lastSuccessFullList.FirstOrDefault(); if (build == null) { var lastPartiallySucceededList = await httpClient.GetBuildsAsync(definitions: new List<int> { definitionReference.Id }, project: definitionReference.Project.Id, resultFilter: BuildResult.PartiallySucceeded, statusFilter: Microsoft.TeamFoundation.Build.WebApi.BuildStatus.Completed, top: 1).ConfigureAwait(false); build = lastPartiallySucceededList.FirstOrDefault(); } if (build != null) { buildTime = build.FinishTime.GetValueOrDefault() - build.StartTime.GetValueOrDefault(); } } catch (Exception) { throw; } return buildTime; }
private static BuildDefinition GetBuildDefinition(int buildDef, string sourceProject, BuildHttpClient buildClient) { var definitionAsync = buildClient.GetDefinitionAsync(sourceProject, buildDef); definitionAsync.Wait(); var definition = (BuildDefinition) definitionAsync.Result; return definition; }
private static BuildHttpClient CreateClient(string accessToken) { var collectionUri = new Uri("https://riskfirst.visualstudio.com/DefaultCollection", UriKind.Absolute); var cred = new VssBasicCredential(string.Empty, accessToken); var buildClient = new BuildHttpClient(collectionUri, cred); return buildClient; }
public BuildServer(VssConnection connection) { ArgUtil.NotNull(connection, nameof(connection)); _buildHttpClient = connection.GetClient <BuildHttpClient>(); }
private void EnsureVersionBelongsToLinkedDefinition(ArtifactDefinition artifactDefinition, BuildHttpClient buildClient, XamlBuildHttpClient xamlBuildClient) { var buildArtifactDetails = artifactDefinition.Details as BuildArtifactDetails; if (buildArtifactDetails != null && buildArtifactDetails.DefintionId > 0) { var buildId = Convert.ToInt32(artifactDefinition.Version, CultureInfo.InvariantCulture); TeamFoundation.Build.WebApi.Build build = null; try { build = buildClient.GetBuildAsync(buildArtifactDetails.Project, buildId).Result; } catch (AggregateException ex) { if (ex.InnerException != null && ex.InnerException is BuildNotFoundException) { build = xamlBuildClient.GetBuildAsync(buildArtifactDetails.Project, buildId).Result; } } if (build != null && build.Definition.Id != buildArtifactDetails.DefintionId) { string errorMessage = StringUtil.Loc("RMBuildNotFromLinkedDefinition", artifactDefinition.Name, buildArtifactDetails.DefinitionName); throw new ArtifactDownloadException(errorMessage); } } }
private async Task <int> GetPipelineIdAsync( AgentTaskPluginExecutionContext context, string pipelineDefinition, string pipelineVersionToDownload, string project, string[] tagFilters, BuildResult resultFilter = BuildResult.Succeeded, string branchName = null, CancellationToken cancellationToken = default(CancellationToken)) { if (String.IsNullOrWhiteSpace(pipelineDefinition)) { throw new InvalidOperationException(StringUtil.Loc("CannotBeNullOrEmpty", "Pipeline Definition")); } VssConnection connection = context.VssConnection; BuildHttpClient buildHttpClient = connection.GetClient <BuildHttpClient>(); var isDefinitionNum = Int32.TryParse(pipelineDefinition, out int definition); if (!isDefinitionNum) { var definitionReferencesWithName = await AsyncHttpRetryHelper.InvokeAsync( async() => await buildHttpClient.GetDefinitionsAsync(new Guid(project), pipelineDefinition, cancellationToken: cancellationToken), maxRetries : MaxRetries, tracer : tracer, context : "GetBuildDefinitionReferencesByName", cancellationToken : cancellationToken, continueOnCapturedContext : false); var definitionRef = definitionReferencesWithName.FirstOrDefault(); if (definitionRef == null) { throw new ArgumentException(StringUtil.Loc("PipelineDoesNotExist", pipelineDefinition)); } else { definition = definitionRef.Id; } } var definitions = new List <int>() { definition }; List <Build> list; if (pipelineVersionToDownload == pipelineVersionToDownloadLatest) { list = await AsyncHttpRetryHelper.InvokeAsync( async() => await buildHttpClient.GetBuildsAsync( project, definitions, tagFilters: tagFilters, queryOrder: BuildQueryOrder.FinishTimeDescending, resultFilter: resultFilter, cancellationToken: cancellationToken), maxRetries : MaxRetries, tracer : tracer, context : "GetLatestBuild", cancellationToken : cancellationToken, continueOnCapturedContext : false); } else if (pipelineVersionToDownload == pipelineVersionToDownloadLatestFromBranch) { list = await AsyncHttpRetryHelper.InvokeAsync( async() => await buildHttpClient.GetBuildsAsync( project, definitions, branchName: branchName, tagFilters: tagFilters, queryOrder: BuildQueryOrder.FinishTimeDescending, resultFilter: resultFilter, cancellationToken: cancellationToken), maxRetries : MaxRetries, tracer : tracer, context : "GetLatestBuildFromBranch", cancellationToken : cancellationToken, continueOnCapturedContext : false); } else { throw new InvalidOperationException("Unreachable code!"); } if (list.Count > 0) { return(list.First().Id); } else { throw new ArgumentException(StringUtil.Loc("BuildsDoesNotExist")); } }
private async Task<IEnumerable<BuildInfoDto>> GetBuildInfoDtosPerBuildDefinitionRest(TfsTeamProjectCollection teamProjectCollection, IList<DefinitionReference> definitionReferences, BuildHttpClient httpClient) { try { var buildInfoDtos = new List<BuildInfoDto>(); foreach (var definitionReference in definitionReferences) { var builds = await httpClient.GetBuildsAsync(top: 1, project: definitionReference.Project.Id, minFinishTime: DateTime.Now.AddMonths(-6), definitions: new[] { definitionReference.Id }).ConfigureAwait(false); var build = builds.FirstOrDefault(); if (build == null) continue; var buildInfoDto = new BuildInfoDto(); buildInfoDto.Builddefinition = definitionReference.Name; buildInfoDto.FinishBuildDateTime = build.FinishTime.GetValueOrDefault(); buildInfoDto.LastBuildTime = new TimeSpan(); buildInfoDto.PassedNumberOfTests = 0; buildInfoDto.RequestedByName = build.RequestedFor.DisplayName; buildInfoDto.RequestedByPictureUrl = build.RequestedFor.ImageUrl; buildInfoDto.StartBuildDateTime = build.StartTime.GetValueOrDefault(); buildInfoDto.Status = build.Result.HasValue ? Char.ToLowerInvariant(build.Result.ToString()[0]) + build.Result.ToString().Substring(1) : Char.ToLowerInvariant(build.Status.ToString()[0]) + build.Status.ToString().Substring(1); buildInfoDto.TeamProject = definitionReference.Project.Name; buildInfoDto.TeamProjectCollection = teamProjectCollection.DisplayName; buildInfoDto.TotalNumberOfTests = 0; buildInfoDto.Id = "TFS" + definitionReference.Project.Id + definitionReference.Id; if (build.Uri == null) { continue; } buildInfoDto.BuildReportUrl = _helperClass.GetReportUrl(teamProjectCollection.Uri != null ? teamProjectCollection.Uri.ToString() : "", definitionReference.Project.Name, build.Uri.ToString()); if (build.Result.HasValue && build.Result.Value == BuildResult.PartiallySucceeded) { var testResults = GetTestResultsRest(teamProjectCollection, definitionReference, build); if (testResults.ContainsKey("PassedTests")) { buildInfoDto.PassedNumberOfTests = testResults["PassedTests"]; buildInfoDto.TotalNumberOfTests = testResults["TotalTests"]; } } //Add last succeeded build if in progress if (build.Status.HasValue && build.Status.Value == Microsoft.TeamFoundation.Build.WebApi.BuildStatus.InProgress) { buildInfoDto.LastBuildTime = await GetLastSuccesfulBuildTimeRest(teamProjectCollection, definitionReference, httpClient).ConfigureAwait(false); } lock (buildInfoDtos) { buildInfoDtos.Add(buildInfoDto); } } return buildInfoDtos; } catch (Exception exception) { LogService.WriteError(exception); throw; } }
public static async Task <BuildInfo> GetArtifactsInfoAsync(this BuildHttpClient azureDevOpsClient, string commit, Build build, CancellationToken cancellationToken) { if (azureDevOpsClient == null) { return(null); } var result = new BuildInfo { Commit = commit, StartTime = build.StartTime, FinishTime = build.FinishTime, Status = build.Status, Result = build.Result, }; var artifacts = await azureDevOpsClient.GetArtifactsAsync(Config.AzureDevOpsProjectId, build.Id, cancellationToken : cancellationToken).ConfigureAwait(false); // windows build var windowsBuildArtifact = artifacts.FirstOrDefault(a => a.Name.Contains("Windows")); var windowsBuild = windowsBuildArtifact?.Resource; if (windowsBuild?.DownloadUrl is string winDownloadUrl) { result.WindowsBuildDownloadLink = winDownloadUrl; if (windowsBuild.DownloadUrl.Contains("format=zip", StringComparison.InvariantCultureIgnoreCase)) { try { using var httpClient = HttpClientFactory.Create(); using var stream = await httpClient.GetStreamAsync(winDownloadUrl).ConfigureAwait(false); using var zipStream = ReaderFactory.Open(stream); while (zipStream.MoveToNextEntry() && !cancellationToken.IsCancellationRequested) { if (zipStream.Entry.Key.EndsWith(".7z", StringComparison.InvariantCultureIgnoreCase)) { result.WindowsFilename = Path.GetFileName(zipStream.Entry.Key); break; } } } catch (Exception e2) { Config.Log.Error(e2, "Failed to get windows build filename"); } } } // linux build var linuxBuildArtifact = artifacts.FirstOrDefault(a => a.Name.EndsWith(".GCC") || a.Name.EndsWith("Linux")); var linuxBuild = linuxBuildArtifact?.Resource; if (linuxBuild?.DownloadUrl is string linDownloadUrl) { result.LinuxBuildDownloadLink = linDownloadUrl; if (linuxBuild.DownloadUrl.Contains("format=zip", StringComparison.InvariantCultureIgnoreCase)) { try { using var httpClient = HttpClientFactory.Create(); using var stream = await httpClient.GetStreamAsync(linDownloadUrl).ConfigureAwait(false); using var zipStream = ReaderFactory.Open(stream); while (zipStream.MoveToNextEntry() && !cancellationToken.IsCancellationRequested) { if (zipStream.Entry.Key.EndsWith(".AppImage", StringComparison.InvariantCultureIgnoreCase)) { result.LinuxFilename = Path.GetFileName(zipStream.Entry.Key); break; } } } catch (Exception e2) { Config.Log.Error(e2, "Failed to get linux build filename"); } } } return(result); }
static async Task <int> Main(string[] args) { string clientId = ""; string clientSecret = ""; bool showHelp = false; var parser = new OptionSet { { "h|?|help", "Show help.", h => showHelp = h != null }, { "ci=|clientid=", "The client ID to use for authentication token retreival.", id => clientId = id }, { "cs=|clientsecret=", "The client secret to use for authentication token retreival.", secret => clientSecret = secret }, }; List <string> extraArguments = null; try { extraArguments = parser.Parse(args); } catch (Exception e) { Console.WriteLine("Failed to parse arguments."); Console.WriteLine(e.Message); return(1); } if (extraArguments.Count > 0) { Console.WriteLine($"Unknown arguments: {string.Join(" ", extraArguments)}"); return(1); } if (showHelp) { parser.WriteOptionDescriptions(Console.Out); return(0); } try { var authToken = await GetSecret("vslsnap-vso-auth-token", clientId, clientSecret); var client = new BuildHttpClient(new Uri("https://devdiv.visualstudio.com"), new VssBasicCredential("", authToken)); int buildsProcessed = 0; var definitions = new List <BuildDefinitionReference>(); definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed-Legacy-15.6AndEarlier")); definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed")); definitions.AddRange(await client.GetDefinitionsAsync(project: "DevDiv", name: "TestImpact-Signed")); foreach (var definition in definitions) { var folderName = definition.Name == "Roslyn-Signed-Legacy-15.6AndEarlier" ? "Roslyn-Signed" : definition.Name; string dropBase = $@"\\cpvsbuild\drops\roslyn\{folderName}"; var builds = await client.GetBuildsAsync(definition.Project.Id, definitions : new[] { definition.Id }, deletedFilter : QueryDeletedOption.IncludeDeleted); foreach (var build in builds) { if (build.Status == BuildStatus.Completed) { string dropPath = Path.Combine(dropBase, Path.GetFileName(build.SourceBranch), "Release", build.BuildNumber); if (Directory.Exists(dropPath)) { bool deleted = build.Deleted; if (!deleted) { // HACK: if your retention policy says to keep the build record (but delete everything else), // you can't rely on build.Deleted. var logs = await client.GetBuildLogsAsync(definition.Project.Id, build.Id); var artifacts = await client.GetArtifactsAsync(definition.Project.Id, build.Id); if (logs == null && artifacts.Count == 0) { deleted = true; } } if (deleted) { buildsProcessed++; Console.WriteLine($"Deleting {dropPath}..."); try { Directory.Delete(dropPath, recursive: true); } catch (UnauthorizedAccessException) { Console.WriteLine("ACCESS EXCEPTION!"); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } catch (IOException e) { Console.WriteLine(e.ToString()); } } } } } /* * // Also clean up any now empty branch folders * foreach (var branchFolder in new DirectoryInfo(dropBase).GetDirectories()) * { * var releaseFolder = branchFolder.GetDirectories("Release").SingleOrDefault(); * * if (releaseFolder != null) * { * releaseFolder.DeleteIfEmpty(); * } * * branchFolder.DeleteIfEmpty(); * } */ } Console.WriteLine($"Builds processed: {buildsProcessed}"); return(0); } catch (Exception e) { Console.WriteLine(e); return(1); } }
public BlobUploadProcessor(ILogger <BlobUploadProcessor> logger, BuildLogProvider logProvider, BlobServiceClient blobServiceClient, BuildHttpClient buildClient, TestResultsHttpClient testResultsClient) { if (blobServiceClient == null) { throw new ArgumentNullException(nameof(blobServiceClient)); } this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.logProvider = logProvider ?? throw new ArgumentNullException(nameof(logProvider)); this.buildClient = buildClient ?? throw new ArgumentNullException(nameof(buildClient)); this.testResultsClient = testResultsClient ?? throw new ArgumentNullException(nameof(testResultsClient)); this.buildsContainerClient = blobServiceClient.GetBlobContainerClient(BuildsContainerName); this.buildTimelineRecordsContainerClient = blobServiceClient.GetBlobContainerClient(BuildTimelineRecordsContainerName); this.buildLogLinesContainerClient = blobServiceClient.GetBlobContainerClient(BuildLogLinesContainerName); this.testRunsContainerClient = blobServiceClient.GetBlobContainerClient(TestRunsContainerNameTestRunsContainerName); }
public BuildServer(VssConnection connection) { connection.Settings.SendTimeout = TimeSpan.FromSeconds(300); ArgUtil.NotNull(connection, nameof(connection)); _buildHttpClient = connection.GetClient<BuildHttpClient>(); }
public static void AddScreenshots(string tfsURL, string tfsToken, string projectId, string buildDefinitionName, string projectName, string nameOfProjectWithTests) { var dictionary = DictionaryInteractions.ReadFromPropertiesFile(ReturnPath.SolutionFolderPath() + nameOfProjectWithTests + "/ExtentReport/ReportProperties.txt"); string[] fileArray = Directory.GetFiles(dictionary["ReportPath"]); var onlyScreenshots = fileArray.Where(s => s.IndexOf(".png") != -1); if (onlyScreenshots.ToList().Count != 0) { VssConnection vc = new VssConnection(new Uri(tfsURL), new VssBasicCredential(string.Empty, tfsToken)); BuildHttpClient bhc = vc.GetClient <BuildHttpClient>(); ProjectHttpClient ddd = vc.GetClient <ProjectHttpClient>(); //ITestManagementTeamProject ddd1 = ddd.GetProject("hgfyjh"); var buildsPerProject = bhc.GetBuildsAsync(projectId).GetAwaiter().GetResult(); var lastBuildId = buildsPerProject.Where <Build>(x => x.Definition.Name == buildDefinitionName).Max <Build>(z => z.Id); Build lastBuild = buildsPerProject.FirstOrDefault <Build>(x => x.Id == lastBuildId); Console.Write("Last Build Number: " + lastBuildId); TestManagementHttpClient ithc = vc.GetClient <TestManagementHttpClient>(); QueryModel qm = new QueryModel("Select * From TestRun Where BuildNumber Contains '" + lastBuild.BuildNumber + "'"); List <TestRun> testruns = ithc.GetTestRunsByQueryAsync(qm, projectName).Result; Console.Write("testruns.Count: " + testruns.Count); foreach (TestRun testrun in testruns) { List <TestCaseResult> testresults = ithc.GetTestResultsAsync(projectName, testrun.Id).Result; Console.Write("testresults.Count: " + testresults.Count); foreach (TestCaseResult tcr in testresults) { var testNamesFromScreents = onlyScreenshots.Select(s => s.ToLower().Split(new string[] { "sec\\" }, StringSplitOptions.None)[1].Split(new string[] { "20" }, StringSplitOptions.None)[0]).Distinct(); //var screentsShotPerTest = onlyScreenshots.Where(s => s.Split(new string[] { "sec\\" }, StringSplitOptions.None)[1].Split(new string[] { "20" }, StringSplitOptions.None)[0] == scenarioName.Replace(" ", string.Empty)); Console.WriteLine("tcr.Id: " + tcr.Id); if (testNamesFromScreents.ToList().Contains(tcr.AutomatedTestName.Split('.').Last().ToLower())) { Console.WriteLine("recognize Test: " + tcr.AutomatedTestName.Split('.').Last().ToLower()); using (var client = new HttpClient()) { string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", tfsToken))); client.BaseAddress = new Uri(tfsURL); //url of our account client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials); var screentsShotPerTest = onlyScreenshots.Where(s => s.Split(new string[] { "sec\\" }, StringSplitOptions.None)[1].Split(new string[] { "20" }, StringSplitOptions.None)[0].ToLower() == tcr.AutomatedTestName.Split('.').Last().ToLower()); foreach (var screenshot in screentsShotPerTest) { Console.WriteLine("screentsShotPerTest: " + screenshot); var post = new PostImageTfs() { Stream = Convert.ToBase64String(File.ReadAllBytes(screenshot)), AttachmentType = "GeneralAttachment", Comment = "screenshot of error", FileName = screenshot.Split(new string[] { "sec\\" }, StringSplitOptions.None)[1] }; Console.WriteLine("tcr.TestRun.Id: " + tcr.TestRun.Id); Console.WriteLine("tcr.Id: " + tcr.Id); Console.WriteLine("screenshot.Split(new string[] { DateTime.Now.Year.ToString() }, StringSplitOptions.None)[2] " + screenshot.Split(new string[] { DateTime.Now.Year.ToString() }, StringSplitOptions.None)[2]); var test = new StringContent($"{{\"stream\": \"{post.Stream}\",\"fileName\": \"{post.FileName}\",\"comment\": \"{post.Comment}\",\"attachmentType\": \"{post.AttachmentType}\"}}", Encoding.UTF8, "application/json"); HttpResponseMessage response = client.PostAsync("/DefaultCollection/" + projectName + "/_apis/test/runs/" + tcr.TestRun.Id + "/results/" + tcr.Id + "/attachments?api-version=2.0-preview.1", test).Result; Console.WriteLine("response: " + response.StatusCode); } } } } } } }
/// <summary> /// Connect to TFS - this may ask the user for credentials, depending on the status of the connection /// </summary> /// <returns></returns> public async Task Connect() { /* * eg: https://company.visualstudio.com/defaultcollection/_apis/projects?api-version=1.0 * * // Create instance of VssConnection using AD Credentials for AD backed account * VssConnection connection = new VssConnection(new Uri(collectionUri), new VssAadCredential()); * * // VssCredentials - NTLM against an on-prem server * VssConnection connection = new VssConnection(new Uri(tfsUri), new VssCredentials()); * * // VssConnection - VS sign in prompt * VssConnection connection = new VssConnection(new Uri(collectionUri), new VssClientCredentials()); * */ var tfsUri = _configManager.TfsDefaultCollectionUrl; if (tfsUri == null) { return; } // Use VS client credentails, including default windows credential store for caching VssClientCredentialStorage storage = new VssClientCredentialStorage(); var creds = new VssClientCredentials(); creds.Storage = storage; // attempt to connect try { _currentConnection = new VssConnection(tfsUri, creds); await _currentConnection.ConnectAsync(VssConnectMode.Automatic); } catch (TaskCanceledException) { //todo - set some application state to reflect not logged in status return; } catch (VssServiceException) { // something bad happened - can't do a lot here... return; } if (_currentConnection.HasAuthenticated) { // update app with logged in credentials, if present. var details = new UserDetails(); details.DisplayName = _currentConnection.AuthorizedIdentity?.DisplayName; string connectedAccount = null; if (_currentConnection.AuthorizedIdentity?.Properties?.TryGetValue("Account", out connectedAccount) == true) { details.Account = connectedAccount; } _configManager.SetUserDetails(details); // get an REST wrapper for the build APIs _BuildClient = await _currentConnection.GetClientAsync <Microsoft.TeamFoundation.Build.WebApi.BuildHttpClient>(); } }
internal TfsBuildHelper(Uri tpcUrl) { this.connection = new VssConnection(tpcUrl, new VssClientCredentials(true)); this.client = connection.GetClient <BuildHttpClient>(); }
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(); }
static void Main(string[] args) { var client = new BuildHttpClient(new Uri("https://devdiv.visualstudio.com"), new VssBasicCredential("", GetSecret("vslsnap-vso-auth-token").Result)); int buildsProcessed = 0; var definitions = new List <BuildDefinitionReference>(); definitions.AddRange(client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed-Legacy-15.6AndEarlier").Result); definitions.AddRange(client.GetDefinitionsAsync(project: "DevDiv", name: "Roslyn-Signed").Result); definitions.AddRange(client.GetDefinitionsAsync(project: "DevDiv", name: "TestImpact-Signed").Result); foreach (var definition in definitions) { var folderName = definition.Name == "Roslyn-Signed-Legacy-15.6AndEarlier" ? "Roslyn-Signed" : definition.Name; string dropBase = $@"\\cpvsbuild\drops\roslyn\{folderName}"; var builds = client.GetBuildsAsync(definition.Project.Id, definitions: new[] { definition.Id }, deletedFilter: QueryDeletedOption.IncludeDeleted).Result; foreach (var build in builds) { if (build.Status == BuildStatus.Completed) { string dropPath = Path.Combine(dropBase, Path.GetFileName(build.SourceBranch), "Release", build.BuildNumber); if (Directory.Exists(dropPath)) { bool deleted = build.Deleted; if (!deleted) { // HACK: if your retention policy says to keep the build record (but delete everything else), // you can't rely on build.Deleted. var logs = client.GetBuildLogsAsync(definition.Project.Id, build.Id).Result; var artifacts = client.GetArtifactsAsync(definition.Project.Id, build.Id).Result; if (logs == null && artifacts.Count == 0) { deleted = true; } } if (deleted) { buildsProcessed++; Console.WriteLine($"Deleting {dropPath}..."); try { Directory.Delete(dropPath, recursive: true); } catch (UnauthorizedAccessException) { Console.WriteLine("ACCESS EXCEPTION!"); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } catch (IOException e) { Console.WriteLine(e.ToString()); } } } } } /* * // Also clean up any now empty branch folders * foreach (var branchFolder in new DirectoryInfo(dropBase).GetDirectories()) * { * var releaseFolder = branchFolder.GetDirectories("Release").SingleOrDefault(); * * if (releaseFolder != null) * { * releaseFolder.DeleteIfEmpty(); * } * * branchFolder.DeleteIfEmpty(); * } */ } Console.WriteLine($"Builds processed: {buildsProcessed}"); }
private async Task DownloadArtifactAsync( IExecutionContext executionContext, ServerBuildArtifact buildArtifact, ArtifactDefinition artifactDefinition, string localFolderPath, BuildHttpClient buildClient, XamlBuildHttpClient xamlBuildClient, DefinitionType definitionType, int buildId) { var downloadFolderPath = Path.Combine(localFolderPath, buildArtifact.Name); var buildArtifactDetails = artifactDefinition.Details as BuildArtifactDetails; if ((buildArtifact.Resource.Type == null && buildArtifact.Id == 0) // bug on build API Bug 378900 || string.Equals(buildArtifact.Resource.Type, WellKnownArtifactResourceTypes.FilePath, StringComparison.OrdinalIgnoreCase)) { executionContext.Output("Artifact Type: FileShare"); string fileShare; if (buildArtifact.Id == 0) { fileShare = new Uri(buildArtifact.Resource.DownloadUrl).LocalPath; } else { fileShare = new Uri(Path.Combine(buildArtifact.Resource.DownloadUrl, buildArtifact.Name)).LocalPath; if (!Directory.Exists(fileShare)) { // download path does not exist, log and fall back var parenthPath = new Uri(buildArtifact.Resource.DownloadUrl).LocalPath; executionContext.Output(StringUtil.Loc("RMArtifactNameDirectoryNotFound", fileShare, parenthPath)); fileShare = parenthPath; } } if (!Directory.Exists(fileShare)) { // download path does not exist, raise exception throw new ArtifactDownloadException(StringUtil.Loc("RMArtifactDirectoryNotFoundError", fileShare)); } executionContext.Output(StringUtil.Loc("RMDownloadingArtifactFromFileShare", fileShare)); var fileShareArtifact = new FileShareArtifact(); await fileShareArtifact.DownloadArtifactAsync(executionContext, HostContext, artifactDefinition, fileShare, downloadFolderPath); } else if (string.Equals(buildArtifact.Resource.Type, WellKnownArtifactResourceTypes.Container, StringComparison.OrdinalIgnoreCase)) { executionContext.Output("Artifact Type: ServerDrop"); // TODO:Get VssBinFetchclient and get away from zipstream downloader Stream contentStream; if (definitionType == DefinitionType.Xaml) { contentStream = await xamlBuildClient.GetArtifactContentZipAsync(buildArtifactDetails.Project, buildId, buildArtifact.Name); } else { contentStream = await buildClient.GetArtifactContentZipAsync(buildArtifactDetails.Project, buildId, buildArtifact.Name); } var zipStreamDownloader = HostContext.GetService<IZipStreamDownloader>(); string artifactRootFolder = StringUtil.Format("/{0}", buildArtifact.Name); await zipStreamDownloader.DownloadFromStream(contentStream, artifactRootFolder, buildArtifactDetails.RelativePath, downloadFolderPath); } else { executionContext.Warning(StringUtil.Loc("RMArtifactTypeNotSupported", buildArtifact.Resource.Type)); } }
private async Task DownloadArtifactAsync( IExecutionContext executionContext, ServerBuildArtifact buildArtifact, ArtifactDefinition artifactDefinition, string localFolderPath, BuildHttpClient buildClient, XamlBuildHttpClient xamlBuildClient, DefinitionType definitionType, int buildId) { var downloadFolderPath = Path.Combine(localFolderPath, buildArtifact.Name); var buildArtifactDetails = artifactDefinition.Details as BuildArtifactDetails; if ((buildArtifact.Resource.Type == null && buildArtifact.Id == 0) || // bug on build API Bug 378900 string.Equals(buildArtifact.Resource.Type, WellKnownArtifactResourceTypes.FilePath, StringComparison.OrdinalIgnoreCase)) { executionContext.Output("Artifact Type: FileShare"); string fileShare; if (buildArtifact.Id == 0) { fileShare = new Uri(buildArtifact.Resource.DownloadUrl).LocalPath; } else { fileShare = new Uri(Path.Combine(buildArtifact.Resource.DownloadUrl, buildArtifact.Name)).LocalPath; if (!Directory.Exists(fileShare)) { // download path does not exist, log and fall back var parenthPath = new Uri(buildArtifact.Resource.DownloadUrl).LocalPath; executionContext.Output(StringUtil.Loc("RMArtifactNameDirectoryNotFound", fileShare, parenthPath)); fileShare = parenthPath; } } if (!Directory.Exists(fileShare)) { // download path does not exist, raise exception throw new ArtifactDownloadException(StringUtil.Loc("RMArtifactDirectoryNotFoundError", fileShare)); } executionContext.Output(StringUtil.Loc("RMDownloadingArtifactFromFileShare", fileShare)); var fileShareArtifact = new FileShareArtifact(); await fileShareArtifact.DownloadArtifactAsync(executionContext, HostContext, artifactDefinition, fileShare, downloadFolderPath); } else if (string.Equals(buildArtifact.Resource.Type, WellKnownArtifactResourceTypes.Container, StringComparison.OrdinalIgnoreCase)) { executionContext.Output("Artifact Type: ServerDrop"); // TODO:Get VssBinFetchclient and get away from zipstream downloader Stream contentStream; if (definitionType == DefinitionType.Xaml) { contentStream = await xamlBuildClient.GetArtifactContentZipAsync(buildArtifactDetails.Project, buildId, buildArtifact.Name); } else { contentStream = await buildClient.GetArtifactContentZipAsync(buildArtifactDetails.Project, buildId, buildArtifact.Name); } var zipStreamDownloader = HostContext.GetService <IZipStreamDownloader>(); string artifactRootFolder = StringUtil.Format("/{0}", buildArtifact.Name); await zipStreamDownloader.DownloadFromStream(contentStream, artifactRootFolder, buildArtifactDetails.RelativePath, downloadFolderPath); } else { executionContext.Warning(StringUtil.Loc("RMArtifactTypeNotSupported", buildArtifact.Resource.Type)); } }