private async Task QueueBuildForStaleImages(Subscription subscription, IEnumerable <string> pathsToRebuild) { if (!pathsToRebuild.Any()) { this.loggerService.WriteMessage($"All images for subscription '{subscription}' are using up-to-date base images. No rebuild necessary."); return; } string formattedPathsToRebuild = pathsToRebuild .Select(path => $"{ManifestFilterOptions.FormattedPathOption} '{path}'") .Aggregate((p1, p2) => $"{p1} {p2}"); string parameters = "{\"" + subscription.PipelineTrigger.PathVariable + "\": \"" + formattedPathsToRebuild + "\"}"; this.loggerService.WriteMessage($"Queueing build for subscription {subscription} with parameters {parameters}."); if (Options.IsDryRun) { return; } using (IVssConnection connection = this.connectionFactory.Create( new Uri($"https://dev.azure.com/{Options.BuildOrganization}"), new VssBasicCredential(String.Empty, Options.BuildPersonalAccessToken))) using (IProjectHttpClient projectHttpClient = connection.GetProjectHttpClient()) using (IBuildHttpClient client = connection.GetBuildHttpClient()) { TeamProject project = await projectHttpClient.GetProjectAsync(Options.BuildProject); Build build = new Build { Project = new TeamProjectReference { Id = project.Id }, Definition = new BuildDefinitionReference { Id = subscription.PipelineTrigger.Id }, SourceBranch = subscription.RepoInfo.Branch, Parameters = parameters }; if (await HasInProgressBuildAsync(client, subscription.PipelineTrigger.Id, project.Id)) { this.loggerService.WriteMessage( $"An in-progress build was detected on the pipeline for subscription '{subscription.ToString()}'. Queueing the build will be skipped."); return; } await client.QueueBuildAsync(build); } }
private async Task QueueBuildForStaleImages(Subscription subscription, IEnumerable <string> pathsToRebuild) { if (!pathsToRebuild.Any()) { _loggerService.WriteMessage($"All images for subscription '{subscription}' are using up-to-date base images. No rebuild necessary."); return; } string formattedPathsToRebuild = pathsToRebuild .Select(path => $"{ManifestFilterOptions.FormattedPathOption} '{path}'") .Aggregate((p1, p2) => $"{p1} {p2}"); string parameters = "{\"" + subscription.PipelineTrigger.PathVariable + "\": \"" + formattedPathsToRebuild + "\"}"; _loggerService.WriteMessage($"Queueing build for subscription {subscription} with parameters {parameters}."); if (Options.IsDryRun) { return; } (Uri baseUrl, VssCredentials credentials) = Options.AzdoOptions.GetConnectionDetails(); using (IVssConnection connection = _connectionFactory.Create(baseUrl, credentials)) using (IProjectHttpClient projectHttpClient = connection.GetProjectHttpClient()) using (IBuildHttpClient client = connection.GetBuildHttpClient()) { TeamProject project = await projectHttpClient.GetProjectAsync(Options.AzdoOptions.Project); Build build = new Build { Project = new TeamProjectReference { Id = project.Id }, Definition = new BuildDefinitionReference { Id = subscription.PipelineTrigger.Id }, SourceBranch = subscription.Manifest.Branch, Parameters = parameters }; if (await HasInProgressBuildAsync(client, subscription.PipelineTrigger.Id, project.Id)) { _loggerService.WriteMessage( $"An in-progress build was detected on the pipeline for subscription '{subscription}'. Queueing the build will be skipped."); return; } await client.QueueBuildAsync(build); } }
private async Task QueueBuildForStaleImages(Subscription subscription, IEnumerable <string> pathsToRebuild) { if (!pathsToRebuild.Any()) { _loggerService.WriteMessage($"All images for subscription '{subscription}' are using up-to-date base images. No rebuild necessary."); return; } string formattedPathsToRebuild = pathsToRebuild .Select(path => $"{CliHelper.FormatAlias(ManifestFilterOptionsBuilder.PathOptionName)} '{path}'") .Aggregate((p1, p2) => $"{p1} {p2}"); string parameters = "{\"" + subscription.PipelineTrigger.PathVariable + "\": \"" + formattedPathsToRebuild + "\"}"; _loggerService.WriteMessage($"Queueing build for subscription {subscription} with parameters {parameters}."); if (Options.IsDryRun) { return; } WebApi.Build? queuedBuild = null; Exception? exception = null; IEnumerable <string>?inProgressBuilds = null; IEnumerable <string>?recentFailedBuilds = null; try { (Uri baseUrl, VssCredentials credentials) = Options.AzdoOptions.GetConnectionDetails(); using (IVssConnection connection = _connectionFactory.Create(baseUrl, credentials)) using (IProjectHttpClient projectHttpClient = connection.GetProjectHttpClient()) using (IBuildHttpClient client = connection.GetBuildHttpClient()) { TeamProject project = await projectHttpClient.GetProjectAsync(Options.AzdoOptions.Project); WebApi.Build build = new() { Project = new TeamProjectReference { Id = project.Id }, Definition = new WebApi.BuildDefinitionReference { Id = subscription.PipelineTrigger.Id }, SourceBranch = subscription.Manifest.Branch, Parameters = parameters }; inProgressBuilds = await GetInProgressBuildsAsync(client, subscription.PipelineTrigger.Id, project.Id); if (!inProgressBuilds.Any()) { (bool shouldDisallowBuild, IEnumerable <string> recentFailedBuildsLocal) = await ShouldDisallowBuildDueToRecentFailuresAsync(client, subscription.PipelineTrigger.Id, project.Id); recentFailedBuilds = recentFailedBuildsLocal; if (shouldDisallowBuild) { _loggerService.WriteMessage( PipelineHelper.FormatErrorCommand("Unable to queue build due to too many recent build failures.")); } else { queuedBuild = await client.QueueBuildAsync(build); await client.AddBuildTagAsync(project.Id, queuedBuild.Id, AzdoTags.AutoBuilder); } } } } catch (Exception ex) { exception = ex; throw; } finally { await LogAndNotifyResultsAsync( subscription, pathsToRebuild, queuedBuild, exception, inProgressBuilds, recentFailedBuilds); } }
public override async Task ExecuteAsync() { StringBuilder notificationMarkdown = new(); string buildUrl = string.Empty; Dictionary <string, TaskResult?> taskResults = Options.TaskNames .ToDictionary(name => name, name => (TaskResult?)null); Dictionary <string, string> buildParameters = new(); BuildResult overallResult = BuildResult.Succeeded; BuildReason buildReason = BuildReason.None; string? correlatedQueueNotificationUrl = null; if (!Options.IsDryRun) { (Uri baseUrl, VssCredentials credentials) = Options.AzdoOptions.GetConnectionDetails(); using (IVssConnection connection = _connectionFactory.Create(baseUrl, credentials)) using (IProjectHttpClient projectHttpClient = connection.GetProjectHttpClient()) using (IBuildHttpClient buildClient = connection.GetBuildHttpClient()) { TeamProject project = await projectHttpClient.GetProjectAsync(Options.AzdoOptions.Project); TeamFoundation.Build.WebApi.Build build = await buildClient.GetBuildAsync(project.Id, Options.BuildId); buildUrl = build.GetWebLink(); buildReason = build.Reason; // Get the build's queue-time parameters if (build.Parameters is not null) { JObject parametersJson = JsonConvert.DeserializeObject <JObject>(build.Parameters); foreach (KeyValuePair <string, JToken?> pair in parametersJson) { buildParameters.Add(pair.Key, pair.Value?.ToString() ?? string.Empty); } } overallResult = await GetBuildTaskResultsAsync(taskResults, buildClient, project); correlatedQueueNotificationUrl = await GetCorrelatedQueueNotificationUrlAsync(); } } notificationMarkdown.AppendLine($"# Publish Results"); notificationMarkdown.AppendLine(); WriteSummaryMarkdown(notificationMarkdown, buildUrl, overallResult, buildReason, correlatedQueueNotificationUrl); notificationMarkdown.AppendLine(); WriteTaskStatusesMarkdown(taskResults, notificationMarkdown); notificationMarkdown.AppendLine(); WriteBuildParameters(buildParameters, notificationMarkdown); notificationMarkdown.AppendLine(); WriteImagesMarkdown(notificationMarkdown); await _notificationService.PostAsync( $"Publish Result - {Options.SourceRepo}/{Options.SourceBranch}", notificationMarkdown.ToString(), new string[] { NotificationLabels.Publish, NotificationLabels.GetRepoLocationLabel(Options.SourceRepo, Options.SourceBranch) }.AppendIf(NotificationLabels.Failure, () => overallResult == BuildResult.Failed), Options.GitOptions.GetRepoUrl().ToString(), Options.GitOptions.AuthToken, Options.IsDryRun); }