Exemplo n.º 1
0
 private Subscription CreateSubscription(MergePolicy mergePolicy)
 {
     return(new Subscription
     {
         SourceRepository = "source.repo",
         TargetRepository = "target.repo",
         TargetBranch = "target.branch",
         PolicyObject =
             new SubscriptionPolicy {
             MergePolicy = mergePolicy, UpdateFrequency = UpdateFrequency.EveryDay
         }
     });
 }
Exemplo n.º 2
0
        private async Task <bool> ShouldMergePrAsync(IRemote darc, string url, MergePolicy policy)
        {
            IList <Check> checks = await darc.GetPullRequestChecksAsync(url);

            if (checks.Count == 0)
            {
                return(false); // Don't auto merge anything that has no checks.
            }

            if (checks.All(c => c.Status == CheckState.Success))
            {
                return(true); // If every check succeeded merge the pr
            }

            return(false);
        }
Exemplo n.º 3
0
        public async Task SynchronizeInProgressPRAsync()
        {
            Subscription subscription = await Context.Subscriptions.FindAsync(SubscriptionId);

            if (subscription == null)
            {
                await Reminders.TryUnregisterReminderAsync(PullRequestCheck);

                await StateManager.TryRemoveStateAsync(PullRequest);

                return;
            }

            ConditionalValue <InProgressPullRequest> maybePr =
                await StateManager.TryGetStateAsync <InProgressPullRequest>(PullRequest);

            if (maybePr.HasValue)
            {
                InProgressPullRequest pr = maybePr.Value;
                long installationId      = await Context.GetInstallationId(subscription.TargetRepository);

                IRemote darc = await DarcFactory.CreateAsync(pr.Url, installationId);

                MergePolicy policy = subscription.PolicyObject.MergePolicy;
                PrStatus    status = await darc.GetPullRequestStatusAsync(pr.Url);

                switch (status)
                {
                case PrStatus.Open:
                    switch (policy)
                    {
                    case MergePolicy.Never:
                        return;

                    case MergePolicy.BuildSucceeded:
                    case MergePolicy.UnitTestPassed:         // for now both of these cases are the same
                        if (await ShouldMergePrAsync(darc, pr.Url, policy))
                        {
                            await darc.MergePullRequestAsync(pr.Url);

                            goto merged;
                        }

                        return;

                    default:
                        Logger.LogError("Unknown merge policy '{policy}'", policy);
                        return;
                    }

                case PrStatus.Merged:
merged:
                    subscription.LastAppliedBuildId = pr.BuildId;
                    await Context.SaveChangesAsync();

                    goto case PrStatus.Closed;

                case PrStatus.Closed:
                    await StateManager.RemoveStateAsync(PullRequest);

                    break;

                default:
                    Logger.LogError("Unknown pr status '{status}'", status);
                    return;
                }
            }

            await Reminders.TryUnregisterReminderAsync(PullRequestCheck);
        }
Exemplo n.º 4
0
        public async Task Test(
            MergePolicy mergePolicy,
            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(mergePolicy);

            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 && mergePolicy == MergePolicy.BuildSucceeded &&
                                         existingPrHasChecks && existingPrPassedChecks;

            void SetupCreatePr()
            {
                Darc.Setup(
                    d => d.CreatePullRequestAsync(
                        subscription.TargetRepository,
                        subscription.TargetBranch,
                        build.Commit,
                        It.IsAny <IList <AssetData> >(),
                        null,
                        null,
                        null))
                .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> >(),
                        null,
                        null))
                .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 (mergePolicy == MergePolicy.BuildSucceeded && prStatus == PrStatus.Open)
                {
                    if (existingPrHasChecks)
                    {
                        Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr))
                        .ReturnsAsync(
                            new List <Check>
                        {
                            new Check(
                                existingPrPassedChecks ? CheckStatus.Succeeded : CheckStatus.Failed,
                                "check",
                                "https://check.stuff/1")
                        });
                    }
                    else
                    {
                        Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>());
                    }
                }

                if (shouldMergeExistingPr)
                {
                    Darc.Setup(r => r.MergePullRequestAsync(existingPr, null, null, null, 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
                }
            });

            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))
            });
        }