Ejemplo n.º 1
0
        /// <summary>
        ///     Synchronizes an in progress pull request.
        ///     This will update current state if the pull request has been manually closed or merged.
        ///     This will evaluate merge policies on an in progress pull request and merge the pull request if policies allow.
        /// </summary>
        /// <returns>
        ///     A <see cref="ValueTuple{InProgressPullRequest, bool}" /> containing:
        ///     The current open pull request if one exists, and
        ///     <see langword="true" /> if the open pull request can be updated; <see langword="false" /> otherwise.
        /// </returns>
        public virtual async Task <(InProgressPullRequest pr, bool canUpdate)> SynchronizeInProgressPullRequestAsync()
        {
            ConditionalValue <InProgressPullRequest> maybePr =
                await StateManager.TryGetStateAsync <InProgressPullRequest>(PullRequest);

            if (maybePr.HasValue)
            {
                InProgressPullRequest pr = maybePr.Value;
                if (string.IsNullOrEmpty(pr.Url))
                {
                    // somehow a bad PR got in the collection, remove it
                    await StateManager.RemoveStateAsync(PullRequest);

                    return(null, false);
                }

                bool?result = await ActionRunner.ExecuteAction(() => SynchronizePullRequestAsync(pr.Url));

                if (result == true)
                {
                    return(pr, true);
                }

                if (result == false)
                {
                    return(pr, false);
                }
            }

            await Reminders.TryUnregisterReminderAsync(PullRequestCheck);

            return(null, false);
        }
Ejemplo n.º 2
0
        private async Task <string> CheckMergePolicyAsyncImpl(string prUrl)
        {
            Subscription subscription = await Context.Subscriptions.FindAsync(SubscriptionId);

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

                await StateManager.TryRemoveStateAsync(PullRequest);

                return("Action Ignored: Subscription does not exist.");
            }

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

            if (!maybePr.HasValue)
            {
                return("Action Ignored: Pull Request not found.");
            }

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

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

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

            switch (status)
            {
            case PrStatus.Open:
                string result = await CheckMergePolicyInternalAsync(darc, policy.MergePolicies, pr);

                if (result.StartsWith("Merged:"))
                {
                    subscription.LastAppliedBuildId = pr.BuildId;
                    await Context.SaveChangesAsync();

                    await StateManager.RemoveStateAsync(PullRequest);

                    return(result);
                }

                return(result);

            default:
                return("Action Ignored: Pull Request is not Open.");
            }
        }
Ejemplo n.º 3
0
        public async Task <ActionResult <bool> > ProcessPendingUpdatesAsync()
        {
            ConditionalValue <List <UpdateAssetsParameters> > maybeUpdates =
                await StateManager.TryGetStateAsync <List <UpdateAssetsParameters> >(PullRequestUpdate);

            List <UpdateAssetsParameters> updates = maybeUpdates.HasValue ? maybeUpdates.Value : null;

            if (updates == null || updates.Count < 1)
            {
                await Reminders.TryUnregisterReminderAsync(PullRequestUpdate);

                return(ActionResult.Create(false, "No Pending Updates"));
            }

            (InProgressPullRequest pr, bool canUpdate) = await SynchronizeInProgressPullRequestAsync();

            if (pr != null && !canUpdate)
            {
                return(ActionResult.Create(false, "PR cannot be updated."));
            }

            string result;

            if (pr != null)
            {
                await UpdatePullRequestAsync(pr, updates);

                result = $"Pull Request '{pr.Url}' updated.";
            }
            else
            {
                string prUrl = await CreatePullRequestAsync(updates);

                if (prUrl == null)
                {
                    result = "No changes required, no pull request created.";
                }
                else
                {
                    result = $"Pull Request '{prUrl}' created.";
                }
            }

            await StateManager.RemoveStateAsync(PullRequestUpdate);

            await Reminders.TryUnregisterReminderAsync(PullRequestUpdate);

            return(ActionResult.Create(true, "Pending updates applied. " + result));
        }
Ejemplo n.º 4
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);
        }