Example #1
0
 private static bool HasInProgressEnvironments(AzureDevOpsRelease release)
 {
     return(!release.Environments.Any(x => StopStatuses.Contains(x.Status)) &&
            release.Environments.Any(x => InProgressStatuses.Contains(x.Status)));
 }
Example #2
0
        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();
            }
        }