예제 #1
0
        public async Task <ActionResult <object> > UpdateAssetsAsync(
            Guid subscriptionId,
            int buildId,
            string sourceSha,
            List <Asset> assets)
        {
            (InProgressPullRequest pr, bool canUpdate) = await SynchronizeInProgressPullRequestAsync();

            var updateParameter = new UpdateAssetsParameters
            {
                SubscriptionId = subscriptionId,
                BuildId        = buildId,
                SourceSha      = sourceSha,
                Assets         = assets
            };

            if (pr != null && !canUpdate)
            {
                await StateManager.AddOrUpdateStateAsync(
                    PullRequestUpdate,
                    new List <UpdateAssetsParameters> {
                    updateParameter
                },
                    (n, old) =>
                {
                    old.Add(updateParameter);
                    return(old);
                });

                await Reminders.TryRegisterReminderAsync(
                    PullRequestUpdate,
                    Array.Empty <byte>(),
                    TimeSpan.FromMinutes(5),
                    TimeSpan.FromMinutes(5));

                return(ActionResult.Create <object>(
                           null,
                           $"Current Pull request '{pr.Url}' cannot be updated, update queued."));
            }

            if (pr != null)
            {
                await UpdatePullRequestAsync(pr, new List <UpdateAssetsParameters> {
                    updateParameter
                });

                return(ActionResult.Create <object>(null, $"Pull Request '{pr.Url}' updated."));
            }

            string prUrl = await CreatePullRequestAsync(new List <UpdateAssetsParameters> {
                updateParameter
            });

            if (prUrl == null)
            {
                return(ActionResult.Create <object>(null, "Updates require no changes, no pull request created."));
            }

            return(ActionResult.Create <object>(null, $"Pull request '{prUrl}' created."));
        }
예제 #2
0
        public async Task UpdateAsync(int buildId)
        {
            await SynchronizeInProgressPRAsync();

            Subscription subscription = await Context.Subscriptions.FindAsync(SubscriptionId);

            Build build = await Context.Builds.Include(b => b.Assets)
                          .ThenInclude(a => a.Locations)
                          .FirstAsync(b => b.Id == buildId);

            string targetRepository = subscription.TargetRepository;
            string targetBranch     = subscription.TargetBranch;
            long   installationId   = await Context.GetInstallationId(subscription.TargetRepository);

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

            List <AssetData> assets = build.Assets.Select(a => new AssetData {
                Name = a.Name, Version = a.Version
            })
                                      .ToList();

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

            string prUrl;

            if (maybePr.HasValue)
            {
                InProgressPullRequest pr = maybePr.Value;
                await darc.UpdatePullRequestAsync(pr.Url, build.Commit, targetBranch, assets);

                prUrl = pr.Url;
            }
            else
            {
                prUrl = await darc.CreatePullRequestAsync(targetRepository, targetBranch, build.Commit, assets);
            }

            var newPr = new InProgressPullRequest {
                Url = prUrl, BuildId = build.Id
            };
            await StateManager.SetStateAsync(PullRequest, newPr);

            await Reminders.TryRegisterReminderAsync(
                PullRequestCheck,
                Array.Empty <byte>(),
                new TimeSpan(0, 5, 0),
                new TimeSpan(0, 5, 0));

            await StateManager.SaveStateAsync();
        }
예제 #3
0
        /// <summary>
        ///     Creates a pull request from the given updates.
        /// </summary>
        /// <param name="updates"></param>
        /// <returns>The pull request url when a pr was created; <see langref="null" /> if no PR is necessary</returns>
        private async Task <string> CreatePullRequestAsync(List <UpdateAssetsParameters> updates)
        {
            (string targetRepository, string targetBranch) = await GetTargetAsync();

            IRemote darc = await GetDarc();


            List <(UpdateAssetsParameters update, List <DependencyDetail> deps)> requiredUpdates =
                await GetRequiredUpdates(updates, darc, targetRepository, targetBranch);

            if (requiredUpdates.Count < 1)
            {
                return(null);
            }

            string newBranchName = $"darc-{targetBranch}-{Guid.NewGuid()}";

            await darc.CreateNewBranchAsync(targetRepository, targetBranch, newBranchName);

            using (var description = new StringWriter())
            {
                description.WriteLine("This pull request updates the following dependencies");
                description.WriteLine();

                await CommitUpdatesAsync(requiredUpdates, description, darc, targetRepository, newBranchName);

                string prUrl = await darc.CreatePullRequestAsync(
                    targetRepository,
                    new PullRequest
                {
                    Title       = "Update dependency files",
                    Description = description.ToString(),
                    BaseBranch  = targetBranch,
                    HeadBranch  = newBranchName
                });

                var inProgressPr = new InProgressPullRequest
                {
                    Url = prUrl,
                    ContainedSubscriptions = requiredUpdates.Select(
                        u => new SubscriptionPullRequestUpdate
                    {
                        SubscriptionId = u.update.SubscriptionId,
                        BuildId        = u.update.BuildId
                    })
                                             .ToList()
                };

                await StateManager.SetStateAsync(PullRequest, inProgressPr);

                await StateManager.SaveStateAsync();

                await Reminders.TryRegisterReminderAsync(
                    PullRequestCheck,
                    null,
                    TimeSpan.FromMinutes(5),
                    TimeSpan.FromMinutes(5));

                return(prUrl);
            }
        }
예제 #4
0
        /// <summary>
        ///     Creates a pull request from the given updates.
        /// </summary>
        /// <param name="updates"></param>
        /// <returns>The pull request url when a pr was created; <see langref="null" /> if no PR is necessary</returns>
        private async Task <string> CreatePullRequestAsync(List <UpdateAssetsParameters> updates)
        {
            (string targetRepository, string targetBranch) = await GetTargetAsync();

            IRemote darcRemote = await DarcRemoteFactory.GetRemoteAsync(targetRepository, Logger);

            List <(UpdateAssetsParameters update, List <DependencyDetail> deps)> requiredUpdates =
                await GetRequiredUpdates(updates, DarcRemoteFactory, targetRepository, targetBranch);

            if (requiredUpdates.Count < 1)
            {
                return(null);
            }

            string newBranchName = $"darc-{targetBranch}-{Guid.NewGuid()}";
            await darcRemote.CreateNewBranchAsync(targetRepository, targetBranch, newBranchName);

            try
            {
                using (var description = new StringWriter())
                {
                    description.WriteLine("This pull request updates the following dependencies");
                    description.WriteLine();

                    await CommitUpdatesAsync(requiredUpdates, description, darcRemote, targetRepository, newBranchName);

                    var inProgressPr = new InProgressPullRequest
                    {
                        // Calculate the subscriptions contained within the
                        // update. Coherency updates do not have subscription info.
                        ContainedSubscriptions = requiredUpdates
                                                 .Where(u => !u.update.IsCoherencyUpdate)
                                                 .Select(
                            u => new SubscriptionPullRequestUpdate
                        {
                            SubscriptionId = u.update.SubscriptionId,
                            BuildId        = u.update.BuildId
                        })
                                                 .ToList()
                    };

                    string prUrl = await darcRemote.CreatePullRequestAsync(
                        targetRepository,
                        new PullRequest
                    {
                        Title       = await ComputePullRequestTitleAsync(inProgressPr, targetBranch),
                        Description = description.ToString(),
                        BaseBranch  = targetBranch,
                        HeadBranch  = newBranchName
                    });

                    if (!string.IsNullOrEmpty(prUrl))
                    {
                        inProgressPr.Url = prUrl;

                        await StateManager.SetStateAsync(PullRequest, inProgressPr);

                        await StateManager.SaveStateAsync();

                        await Reminders.TryRegisterReminderAsync(
                            PullRequestCheck,
                            null,
                            TimeSpan.FromMinutes(5),
                            TimeSpan.FromMinutes(5));

                        return(prUrl);
                    }

                    // Something wrong happened when trying to create the PR but didn't throw an exception (probably there was no diff).
                    // We need to delete the branch also in this case.
                    await darcRemote.DeleteBranchAsync(targetRepository, newBranchName);

                    return(null);
                }
            }
            catch
            {
                await darcRemote.DeleteBranchAsync(targetRepository, newBranchName);

                throw;
            }
        }
예제 #5
0
        private async Task <string> UpdateAsyncImpl(int buildId)
        {
            await SynchronizeInProgressPRAsync();

            Subscription subscription = await Context.Subscriptions.FindAsync(SubscriptionId);

            Build build = await Context.Builds.Include(b => b.Assets)
                          .ThenInclude(a => a.Locations)
                          .FirstAsync(b => b.Id == buildId);

            string targetRepository = subscription.TargetRepository;
            string targetBranch     = subscription.TargetBranch;
            long   installationId   = await Context.GetInstallationId(subscription.TargetRepository);

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

            List <AssetData> assets = build.Assets.Select(a => new AssetData {
                Name = a.Name, Version = a.Version
            })
                                      .ToList();
            string title       = GetTitle(subscription, build);
            string description = GetDescription(subscription, build, assets);

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

            InProgressPullRequest pr;

            if (maybePr.HasValue)
            {
                pr = maybePr.Value;
                await darc.UpdatePullRequestAsync(pr.Url, build.Commit, targetBranch, assets, title, description);
            }
            else
            {
                string prUrl = await darc.CreatePullRequestAsync(
                    targetRepository,
                    targetBranch,
                    build.Commit,
                    assets,
                    pullRequestTitle : title,
                    pullRequestDescription : description);

                if (string.IsNullOrEmpty(prUrl))
                {
                    return($"No Pull request created. Darc Reports no dependencies need to be updated.");
                }

                pr = new InProgressPullRequest {
                    Url = prUrl
                };
            }

            pr.BuildId = build.Id;
            await StateManager.SetStateAsync(PullRequest, pr);

            await Reminders.TryRegisterReminderAsync(
                PullRequestCheck,
                Array.Empty <byte>(),
                new TimeSpan(0, 5, 0),
                new TimeSpan(0, 5, 0));

            await StateManager.SaveStateAsync();

            return($"Pull request '{pr.Url}' updated.");
        }