private static bool HasInProgressEnvironments(AzureDevOpsRelease release) { return(!release.Environments.Any(x => StopStatuses.Contains(x.Status)) && release.Environments.Any(x => InProgressStatuses.Contains(x.Status))); }
public async Task ProcessFinishedReleasesAsync(CancellationToken cancellationToken) { Logger.LogInformation($"Starting ProcessFinishedReleasesAsync."); var runningPipelines = await StateManager.GetOrAddAsync <IReliableDictionary <int, IList <ReleasePipelineStatusItem> > >(RunningPipelineDictionaryName); HashSet <BuildChannel> buildChannelsToAdd = new HashSet <BuildChannel>(new BuildChannelComparer()); using (ITransaction tx = StateManager.CreateTransaction()) { var runningPipelinesEnumerable = await runningPipelines.CreateEnumerableAsync(tx, EnumerationMode.Unordered); using (var asyncEnumerator = runningPipelinesEnumerable.GetAsyncEnumerator()) { while (await asyncEnumerator.MoveNextAsync(cancellationToken)) { int buildId = asyncEnumerator.Current.Key; IList <ReleasePipelineStatusItem> releaseStatuses = asyncEnumerator.Current.Value; int channelId = releaseStatuses.First().ChannelId; List <ReleasePipelineStatusItem> unfinishedReleases = new List <ReleasePipelineStatusItem>(); bool successfulRelease = true; foreach (ReleasePipelineStatusItem releaseStatus in releaseStatuses) { try { int releaseId = releaseStatus.ReleaseId; AzureDevOpsClient azdoClient = await GetAzureDevOpsClientForAccount(releaseStatus.PipelineOrganization); AzureDevOpsRelease release = await azdoClient.GetReleaseAsync(releaseStatus.PipelineOrganization, releaseStatus.PipelineProject, releaseStatus.ReleaseId); if (HasInProgressEnvironments(release)) { unfinishedReleases.Add(releaseStatus); Logger.LogInformation($"Release {releaseId} from build {buildId} and channel {channelId} is still in progress."); } else { Logger.LogInformation($"Release {releaseId}, channel {channelId} finished executing"); if (release.Environments.Any(r => r.Status != AzureDevOpsReleaseStatus.Succeeded)) { successfulRelease = false; await CreateGitHubIssueAsync(buildId, releaseId, release.Name); await StateManager.RemoveAsync(release.Name); } } } catch (TaskCanceledException tcex) when(tcex.CancellationToken == cancellationToken) { // ignore } catch (Exception ex) { // Something failed while fetching the release information so the potential created issue wouldn't have relevant information to // be notified so we just log the exception to AppInsights with not filed issue. Logger.LogError(ex, $"Processing release {releaseStatus.ReleaseId} failed. Check the exception for details."); } } if (unfinishedReleases.Count > 0) { await runningPipelines.TryUpdateAsync(tx, buildId, unfinishedReleases, releaseStatuses); } else { if (successfulRelease) { Logger.LogInformation($"All releases for build {buildId} for channel {channelId} finished. Creating BuildChannel."); buildChannelsToAdd.Add(new BuildChannel { BuildId = buildId, ChannelId = channelId }); } else { Logger.LogError($"One or more release environments of build {buildId} failed. Build id {buildId}" + $"was not added to channel {channelId}"); } await runningPipelines.TryRemoveAsync(tx, buildId); } } } if (buildChannelsToAdd.Count > 0) { List <BuildChannel> addedBuildChannels = await AddFinishedBuildChannelsIfNotPresent(buildChannelsToAdd); await TriggerDependencyUpdates(addedBuildChannels); } await tx.CommitAsync(); } }