Пример #1
0
        private async Task <ActionResult <bool?> > CheckMergePolicyAsync(string prUrl, IRemote darc)
        {
            IReadOnlyList <MergePolicyDefinition> policyDefinitions = await GetMergePolicyDefinitions();

            MergePolicyEvaluationResult result = await MergePolicyEvaluator.EvaluateAsync(
                prUrl,
                darc,
                policyDefinitions);

            if (result.Failed || result.Pending)
            {
                await UpdateStatusCommentAsync(
                    darc,
                    prUrl,
                    $@"## Auto-Merge Status
This pull request has not been merged because Maestro++ is waiting on the following merge policies.

{string.Join("\n", result.Results.OrderBy(r => r.Policy == null ? " " : r.Policy.Name).Select(DisplayPolicy))}");

                return(ActionResult.Create(
                           result.Pending ? (bool?)null : false,
                           $"NOT Merged: PR '{prUrl}' failed policies {string.Join(", ", result.Results.Where(r => r.Success == null || r.Success == false).Select(r => r.Policy?.Name + r.Message))}"));
            }

            if (result.Succeeded)
            {
                var merged = false;
                try
                {
                    await darc.MergePullRequestAsync(prUrl, new MergePullRequestParameters());

                    merged = true;
                }
                catch
                {
                    // Failure to merge is not exceptional, report on it.
                }

                await UpdateStatusCommentAsync(
                    darc,
                    prUrl,
                    $@"## Auto-Merge Status
This pull request {(merged ? "has been merged" : "will be merged")} because the following merge policies have succeeded.

{string.Join("\n", result.Results.OrderBy(r => r.Policy == null ? " " : r.Policy.Name).Select(DisplayPolicy))}");

                if (merged)
                {
                    return(ActionResult.Create(
                               (bool?)true,
                               $"Merged: PR '{prUrl}' passed policies {string.Join(", ", policyDefinitions.Select(p => p.Name))}"));
                }

                return(ActionResult.Create((bool?)false, $"NOT Merged: PR '{prUrl}' has merge conflicts."));
            }

            return(ActionResult.Create((bool?)false, "NOT Merged: There are no merge policies"));
        }
Пример #2
0
        private async Task <string> CheckMergePolicyInternalAsync(
            IRemote darc,
            IList <MergePolicyDefinition> policyDefinitions,
            InProgressPullRequest pr)
        {
            var results = new List <(MergePolicy policy, MergePolicyEvaluationResult result)>();

            if (policyDefinitions != null)
            {
                foreach (MergePolicyDefinition policyDefinition in policyDefinitions)
                {
                    var context = new MergePolicyEvaluationContext(pr.Url, darc, Logger, policyDefinition.Properties);
                    if (PolicyEvaluators.TryGetValue(policyDefinition.Name, out MergePolicy policyEvaluator))
                    {
                        MergePolicyEvaluationResult result = await policyEvaluator.EvaluateAsync(context);

                        results.Add((policyEvaluator, result));
                    }
                    else
                    {
                        results.Add((null, context.Fail($"Unknown Merge Policy '{policyDefinition.Name}'")));
                    }
                }
            }

            if (results.Count == 0)
            {
                await UpdateStatusCommentAsync(
                    darc,
                    pr,
                    $@"## Auto-Merge Status
This pull request will not be merged automatically because the subscription with id '{SubscriptionId}' does not have any merge policies.");

                return(NotMergedNoPolicies());
            }

            string DisplayPolicy((MergePolicy policy, MergePolicyEvaluationResult result) p)
            {
                (MergePolicy policy, MergePolicyEvaluationResult result) = p;
                if (policy == null)
                {
                    return($"- ❌ **{result.Message}**");
                }

                if (result.Succeeded)
                {
                    return($"- ✔️ **{policy.DisplayName}** Succeeded");
                }

                return($"- ❌ **{policy.DisplayName}** {result.Message}");
            }

            if (results.Any(r => !r.result.Succeeded))
            {
                await UpdateStatusCommentAsync(
                    darc,
                    pr,
                    $@"## Auto-Merge Status
This pull request has not been merged because the subscription with id '{SubscriptionId}' is waiting on the following merge policies.

{string.Join("\n", results.OrderBy(r => r.policy == null ? " " : r.policy.Name).Select(DisplayPolicy))}");

                return(NotMergedFailedPolicies(results.Where(r => !r.result.Succeeded), pr.Url));
            }

            await UpdateStatusCommentAsync(
                darc,
                pr,
                $@"## Auto-Merge Status
This pull request has been merged because the following merge policies have succeeded.

{string.Join("\n", results.OrderBy(r => r.policy == null ? " " : r.policy.Name).Select(DisplayPolicy))}");

            await darc.MergePullRequestAsync(pr.Url, null);

            return(Merged(policyDefinitions, pr.Url));
        }
Пример #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);
        }