Пример #1
0
        private async Task SynchronizeInstallationRepositoriesAsync(long installationId)
        {
            string token = await GitHubTokenProvider.GetTokenForInstallation(installationId);

            IReadOnlyList <Repository> gitHubRepos = await GetAllInstallationRepositories(token);

            HashSet <string> toRemove = (await Context.RepoInstallations.Where(ri => ri.InstallationId == installationId)
                                         .Select(ri => ri.Repository)
                                         .ToListAsync())
                                        .ToHashSet(StringComparer.OrdinalIgnoreCase);

            foreach (Repository repo in gitHubRepos)
            {
                toRemove.Remove(repo.HtmlUrl);

                RepoInstallation existing = await Context.RepoInstallations.FindAsync(repo.HtmlUrl);

                if (existing == null)
                {
                    Context.RepoInstallations.Add(
                        new RepoInstallation {
                        Repository = repo.HtmlUrl, InstallationId = installationId
                    });
                }
                else
                {
                    existing.InstallationId = installationId;
                }
            }

            foreach (string repository in toRemove)
            {
                Context.RepoInstallations.Remove(await Context.RepoInstallations.FindAsync(repository));
            }

            await Context.SaveChangesAsync();
        }
Пример #2
0
        public async Task Test(
            bool mergeOnPassedChecks,
            PrStatus prStatus,
            bool existingPrHasChecks,
            bool existingPrPassedChecks)
        {
            const string prCommentId   = "5";
            Channel      channel       = CreateChannel();
            Build        oldBuild      = CreateOldBuild();
            Build        build         = CreateNewBuild();
            var          buildChannels = new[]
            {
                new BuildChannel {
                    Build = oldBuild, Channel = channel
                },
                new BuildChannel {
                    Build = build, Channel = channel
                }
            };
            Subscription subscription = CreateSubscription(mergeOnPassedChecks ? new MergePolicyDefinition
            {
                Name = "AllChecksSuccessful"
            } : null);

            subscription.Channel = channel;
            var repoInstallation =
                new RepoInstallation {
                Repository = subscription.TargetRepository, InstallationId = 1
            };
            Asset asset = build.Assets[0];
            await Context.RepoInstallations.AddAsync(repoInstallation);

            await Context.Subscriptions.AddAsync(subscription);

            await Context.BuildChannels.AddRangeAsync(buildChannels);

            await Context.SaveChangesAsync();

            var actorId    = new ActorId(subscription.Id);
            var existingPr = "https://repo.pr/existing";
            var pr         = "https://repo.pr/new";


            bool shouldMergeExistingPr = prStatus == PrStatus.Open && mergeOnPassedChecks &&
                                         existingPrHasChecks && existingPrPassedChecks;

            void SetupCreatePr()
            {
                Darc.Setup(
                    d => d.CreatePullRequestAsync(
                        subscription.TargetRepository,
                        subscription.TargetBranch,
                        build.Commit,
                        It.IsAny <IList <AssetData> >(),
                        null,
                        It.IsAny <string>(),
                        It.IsAny <string>()))
                .ReturnsAsync(
                    (
                        string repo,
                        string branch,
                        string commit,
                        IList <AssetData> assets,
                        string baseBranch,
                        string title,
                        string description) =>
                {
                    assets.Should().BeEquivalentTo(new AssetData {
                        Name = asset.Name, Version = asset.Version
                    });
                    return(pr);
                });
            }

            void SetupUpdatePr()
            {
                Darc.Setup(
                    r => r.UpdatePullRequestAsync(
                        existingPr,
                        build.Commit,
                        subscription.TargetBranch,
                        It.IsAny <IList <AssetData> >(),
                        It.IsAny <string>(),
                        It.IsAny <string>()))
                .ReturnsAsync(
                    (
                        string url,
                        string commit,
                        string branch,
                        IList <AssetData> assets,
                        string title,
                        string description) =>
                {
                    return(url);
                });
            }

            void SetupExistingPr()
            {
                StateManager.Data[SubscriptionActor.PullRequest] =
                    new InProgressPullRequest {
                    BuildId = oldBuild.Id, Url = existingPr
                };
                Darc.Setup(r => r.GetPullRequestStatusAsync(existingPr)).ReturnsAsync(prStatus);
                if (mergeOnPassedChecks && prStatus == PrStatus.Open)
                {
                    if (existingPrHasChecks)
                    {
                        Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr))
                        .ReturnsAsync(
                            new List <Check>
                        {
                            new Check(
                                existingPrPassedChecks ? CheckState.Success : CheckState.Failure,
                                "check",
                                "https://check.stuff/1")
                        });
                    }
                    else
                    {
                        Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>());
                    }
                }

                if (prStatus == PrStatus.Open)
                {
                    Darc.Setup(d => d.CreatePullRequestCommentAsync(It.IsAny <string>(), It.IsAny <string>()))
                    .ReturnsAsync(prCommentId);
                }

                if (shouldMergeExistingPr)
                {
                    Darc.Setup(r => r.MergePullRequestAsync(existingPr, null))
                    .Returns(Task.CompletedTask);
                }
            }

            switch (prStatus)
            {
            case PrStatus.None:
                SetupCreatePr();
                break;

            case PrStatus.Open:
                SetupExistingPr();
                if (shouldMergeExistingPr)
                {
                    SetupCreatePr();
                }
                else
                {
                    SetupUpdatePr();
                }

                break;

            case PrStatus.Merged:
                SetupExistingPr();
                SetupCreatePr();
                break;

            case PrStatus.Closed:
                SetupExistingPr();
                SetupCreatePr();
                break;
            }


            var actor = ActivatorUtilities.CreateInstance <SubscriptionActor>(Scope.ServiceProvider, actorId);
            await actor.UpdateAsync(build.Id);

            if (shouldMergeExistingPr || prStatus == PrStatus.Merged)
            {
                subscription.LastAppliedBuildId.Should().Be(oldBuild.Id);
            }
            else
            {
                subscription.LastAppliedBuildId.Should().Be(null);
            }

            StateManager.Data.Should()
            .BeEquivalentTo(
                new Dictionary <string, object>
            {
                [SubscriptionActor.PullRequest] = new InProgressPullRequest
                {
                    BuildId         = build.Id,
                    Url             = prStatus == PrStatus.Open && !shouldMergeExistingPr ? existingPr : pr,
                    StatusCommentId = prStatus == PrStatus.Open && !shouldMergeExistingPr ? prCommentId : null
                }
            });

            Reminders.Data.Should()
            .BeEquivalentTo(
                new Dictionary <string, MockReminderManager.Reminder>
            {
                [SubscriptionActor.PullRequestCheck] = new MockReminderManager.Reminder(
                    SubscriptionActor.PullRequestCheck,
                    Array.Empty <byte>(),
                    TimeSpan.FromMinutes(5),
                    TimeSpan.FromMinutes(5))
            });
        }
Пример #3
0
        public async Task SynchronizeInProgressPRAsync(
            PrStatus prStatus,
            bool existingPrHasChecks,
            bool existingPrPassedChecks)
        {
            Channel channel       = CreateChannel();
            Build   oldBuild      = CreateOldBuild();
            Build   build         = CreateNewBuild();
            var     buildChannels = new[]
            {
                new BuildChannel {
                    Build = oldBuild, Channel = channel
                },
                new BuildChannel {
                    Build = build, Channel = channel
                }
            };
            Subscription subscription = CreateSubscription(new MergePolicyDefinition
            {
                Name = "AllChecksSuccessful",
            });

            subscription.Channel = channel;
            var repoInstallation =
                new RepoInstallation {
                Repository = subscription.TargetRepository, InstallationId = 1
            };
            await Context.RepoInstallations.AddAsync(repoInstallation);

            await Context.Subscriptions.AddAsync(subscription);

            await Context.BuildChannels.AddRangeAsync(buildChannels);

            await Context.SaveChangesAsync();

            var existingPr = "https://repo.pr/existing";
            var actorId    = new ActorId(subscription.Id);

            StateManager.Data[SubscriptionActor.PullRequest] =
                new InProgressPullRequest {
                BuildId = oldBuild.Id, Url = existingPr
            };

            Darc.Setup(d => d.GetPullRequestStatusAsync(existingPr)).ReturnsAsync(prStatus);

            if (prStatus == PrStatus.Open)
            {
                if (existingPrHasChecks)
                {
                    Darc.Setup(d => d.GetPullRequestChecksAsync(existingPr))
                    .ReturnsAsync(
                        new List <Check>
                    {
                        new Check(
                            existingPrPassedChecks ? CheckState.Success : CheckState.Failure,
                            "check",
                            "https://check.stuff/1")
                    });
                }
                else
                {
                    Darc.Setup(d => d.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>());
                }

                if (existingPrHasChecks && existingPrPassedChecks)
                {
                    Darc.Setup(d => d.MergePullRequestAsync(existingPr, null))
                    .Returns(Task.CompletedTask);
                }

                Darc.Setup(d => d.CreatePullRequestCommentAsync(It.IsAny <string>(), It.IsAny <string>()))
                .ReturnsAsync("5");
            }

            var actor = ActivatorUtilities.CreateInstance <SubscriptionActor>(Scope.ServiceProvider, actorId);
            await actor.ReceiveReminderAsync(
                SubscriptionActor.PullRequestCheck,
                Array.Empty <byte>(),
                TimeSpan.Zero,
                TimeSpan.FromMinutes(5));

            switch (prStatus)
            {
            case PrStatus.Merged:
                subscription.LastAppliedBuildId.Should().Be(oldBuild.Id);
                goto case PrStatus.Closed;

            case PrStatus.Closed:
                Reminders.Data.Should().BeEmpty();
                StateManager.Data.Should().BeEmpty();
                break;
            }
        }
Пример #4
0
        public async Task NeedsUpdateSubscription()
        {
            var channel = new Channel {
                Name = "channel", Classification = "class"
            };
            var oldBuild = new Build
            {
                Branch       = "source.branch",
                Repository   = "source.repo",
                BuildNumber  = "old.build.number",
                Commit       = "oldSha",
                DateProduced = DateTimeOffset.UtcNow.AddDays(-2)
            };
            var location = "https://source.feed/index.json";
            var build    = new Build
            {
                Branch       = "source.branch",
                Repository   = "source.repo",
                BuildNumber  = "build.number",
                Commit       = "sha",
                DateProduced = DateTimeOffset.UtcNow,
                Assets       = new List <Asset>
                {
                    new Asset
                    {
                        Name      = "source.asset",
                        Version   = "1.0.1",
                        Locations = new List <AssetLocation>
                        {
                            new AssetLocation {
                                Location = location, Type = LocationType.NugetFeed
                            }
                        }
                    }
                }
            };
            var buildChannel = new BuildChannel {
                Build = build, Channel = channel
            };
            var subscription = new Subscription
            {
                Channel          = channel,
                SourceRepository = "source.repo",
                TargetRepository = "target.repo",
                TargetBranch     = "target.branch",
                PolicyObject     =
                    new SubscriptionPolicy
                {
                    MergePolicy     = MergePolicy.Never,
                    UpdateFrequency = UpdateFrequency.EveryDay
                },
                LastAppliedBuild = oldBuild
            };
            var repoInstallation = new RepoInstallation {
                Repository = "target.repo", InstallationId = 1
            };
            await Context.RepoInstallations.AddAsync(repoInstallation);

            await Context.Subscriptions.AddAsync(subscription);

            await Context.BuildChannels.AddAsync(buildChannel);

            await Context.SaveChangesAsync();

            SubscriptionActor.Setup(a => a.UpdateAsync(build.Id)).Returns(Task.CompletedTask);

            var updater = ActivatorUtilities.CreateInstance <DependencyUpdater>(Scope.ServiceProvider);
            await updater.CheckSubscriptionsAsync(CancellationToken.None);
        }
Пример #5
0
        public async Task EveryBuildSubscriptionNotEnabled()
        {
            var channel = new Channel {
                Name = "channel", Classification = "class"
            };
            var build = new Build
            {
                Branch       = "source.branch",
                Repository   = "source.repo",
                BuildNumber  = "build.number",
                Commit       = "sha",
                DateProduced = DateTimeOffset.UtcNow.AddDays(-1)
            };
            var location = "https://repo.feed/index.json";
            var newAsset = new Asset
            {
                Name      = "source.asset",
                Version   = "1.0.1",
                Locations = new List <AssetLocation>
                {
                    new AssetLocation {
                        Location = location, Type = LocationType.NugetFeed
                    }
                }
            };
            var newBuild = new Build
            {
                Branch       = "source.branch",
                Repository   = "source.repo",
                BuildNumber  = "build.number.2",
                Commit       = "sha2",
                DateProduced = DateTimeOffset.UtcNow,
                Assets       = new List <Asset> {
                    newAsset
                }
            };
            var buildChannels = new[]
            {
                new BuildChannel {
                    Build = build, Channel = channel
                },
                new BuildChannel {
                    Build = newBuild, Channel = channel
                }
            };
            var subscription = new Subscription
            {
                Channel          = channel,
                SourceRepository = "source.repo",
                TargetRepository = "target.repo",
                TargetBranch     = "target.branch",
                Enabled          = false,
                PolicyObject     =
                    new SubscriptionPolicy
                {
                    MergePolicies   = null,
                    UpdateFrequency = UpdateFrequency.EveryBuild
                },
                LastAppliedBuild = build
            };
            var repoInstallation = new RepoInstallation {
                Repository = "target.repo", InstallationId = 1
            };
            await Context.BuildChannels.AddRangeAsync(buildChannels);

            await Context.Subscriptions.AddAsync(subscription);

            await Context.RepoInstallations.AddAsync(repoInstallation);

            await Context.SaveChangesAsync();

            SubscriptionActor.Verify(a => a.UpdateAsync(build.Id), Times.Never());

            var updater = ActivatorUtilities.CreateInstance <DependencyUpdater>(Scope.ServiceProvider);
            await updater.UpdateDependenciesAsync(newBuild.Id, channel.Id);
        }