public async Task <bool> AddAdditionalIntegrationBranches(BranchGroupCompleteData details, IUnitOfWork unitOfWork)
        {
            var branches = await branchSettings.GetIntegrationBranches(details.UpstreamBranchGroups);

            var toAdd = branches.Except(details.UpstreamBranchGroups).Except(new [] { details.GroupName }).ToImmutableList();

            if (toAdd.Any())
            {
                foreach (var upstreamBranch in toAdd)
                {
                    branchSettings.AddBranchPropagation(upstreamBranch, details.GroupName, unitOfWork);
                }
                return(true);
            }
            return(false);
        }
Beispiel #2
0
        public async Task <IntegrationBranchResult> FindAndCreateIntegrationBranches(BranchGroupCompleteData downstreamDetails, IEnumerable <string> initialUpstreamBranchGroups, AttemptMergeDelegate doMerge)
        {
            // 1. Find branches that conflict
            // 2. Create integration branches for them
            // 3. Add the integration branch for ourselves

            foreach (var upstream in initialUpstreamBranchGroups)
            {
                if (await repository.IsBadBranch(upstream))
                {
                    // A branch that was directly upstream had updates pending
                    return(new IntegrationBranchResult {
                        PendingUpdates = true
                    });
                }
            }

            var result = await FindConflicts(downstreamDetails.GroupName, initialUpstreamBranchGroups, doMerge);

            if (result.PendingUpdates)
            {
                return(result);
            }

            var newIntegrationBranches = new List <string>();

            using (var work = workFactory.CreateUnitOfWork())
            {
                foreach (var conflict in result.Conflicts)
                {
                    // I need an integration branch!
                    var integrationBranch = await settings.FindIntegrationBranchForConflict(conflict.BranchA.GroupName, conflict.BranchB.GroupName, downstreamDetails.UpstreamBranchGroups);

                    if (downstreamDetails.UpstreamBranchGroups.Contains(integrationBranch))
                    {
                        // You already have one! - Maz Kanata
                        continue;
                    }
                    var originalIntegrationBranch = integrationBranch;
                    if (integrationBranch == null)
                    {
                        if (conflict.BranchA.GroupName == downstreamDetails.GroupName || conflict.BranchB.GroupName == downstreamDetails.GroupName)
                        {
                            continue;
                        }
                        integrationBranch = await integrationNaming.GetIntegrationBranchName(conflict.BranchA.GroupName, conflict.BranchB.GroupName);

                        settings.CreateIntegrationBranch(conflict.BranchA.GroupName, conflict.BranchB.GroupName, integrationBranch, work);
#pragma warning disable CS4014
                        orchestration.EnqueueAction(new MergeDownstreamAction(integrationBranch));
#pragma warning restore
                    }
                    if (originalIntegrationBranch != null && (conflict.BranchA.GroupName == downstreamDetails.GroupName || conflict.BranchB.GroupName == downstreamDetails.GroupName))
                    {
                        // There was an integration branch with the current branch and an upstream branch. Flip it around and consolidate!
                        newIntegrationBranches.Add(integrationBranch);
                        settings.AddBranchPropagation(integrationBranch, downstreamDetails.GroupName, work);
                        settings.RemoveBranchPropagation(downstreamDetails.GroupName, integrationBranch, work);

#pragma warning disable CS4014
                        orchestration.EnqueueAction(new MergeDownstreamAction(downstreamDetails.GroupName));
                        orchestration.EnqueueAction(new ConsolidateMergedAction(integrationBranch, downstreamDetails.GroupName));
#pragma warning restore
                    }
                    else if (!downstreamDetails.UpstreamBranchGroups.Any(b => b == integrationBranch))
                    {
                        newIntegrationBranches.Add(integrationBranch);
                        settings.AddBranchPropagation(integrationBranch, downstreamDetails.GroupName, work);
                    }
                }
                await work.CommitAsync();
            }

            return(new IntegrationBranchResult
            {
                Conflicts = result.Conflicts,
                AddedBranches = newIntegrationBranches,
            });
        }
            protected override async Task RunProcess()
            {
                if (isReadOnly)
                {
                    return;
                }

                // either:
                // 1. create new service line from release candidate
                // 2. merge --ff-only from release candidate to service line

                // if it passes:
                //   collect upstream branches
                //   push service line

                var upstreamLines = await repository.DetectShallowUpstreamServiceLines(releaseCandidateBranch).FirstOrDefaultAsync();

                var disposable = new CompositeDisposable();

                var readyToFinalize = await CreateOrFastForwardServiceLine(releaseCandidateBranch, repository, cli);

                if (!readyToFinalize)
                {
                    await AppendMessage($"{serviceLineBranch} unable to be fast-forwarded from {releaseCandidateBranch}; aborting", isError : true);
                }
                else
                {
                    if (!string.IsNullOrEmpty(tagName))
                    {
                        await AppendProcess(cli.AnnotatedTag(tagName, $"Automated release to service line {serviceLineBranch} from {releaseCandidateBranch}")).WaitUntilComplete();
                    }

                    var serviceLine = await settings.GetBranchBasicDetails(serviceLineBranch).FirstOrDefaultAsync();

                    // possible TODO for the future: give option to add missing upstream lines always
                    if (serviceLine == null)
                    {
                        // We need to set it up as a service line
                        using (var work = unitOfWorkFactory.CreateUnitOfWork())
                        {
                            settings.UpdateBranchSetting(serviceLineBranch, UpstreamMergePolicy.None, BranchGroupType.ServiceLine, work);
                            foreach (var upstreamServiceLine in upstreamLines)
                            {
                                settings.AddBranchPropagation(upstreamServiceLine, serviceLineBranch, work);
                            }

                            await work.CommitAsync();
                        }
                    }

                    if (autoConsolidate)
                    {
                        var consolidating = (await repository.GetBranchDetails(releaseCandidateBranch).FirstOrDefaultAsync()).UpstreamBranchGroups;
                        foreach (var upstreamServiceLine in upstreamLines)
                        {
                            var upstreamDetails = await repository.GetBranchDetails(upstreamServiceLine).FirstOrDefaultAsync();

                            consolidating = consolidating.Except(upstreamDetails.UpstreamBranchGroups).Except(new[] { upstreamServiceLine }).ToImmutableList();
                        }
                        var releasedCandidate = await settings.GetConfiguredBranches().Select(branches => branches.Find(branch => branchIteration.IsBranchIteration(branch.GroupName, releaseCandidateBranch)).GroupName).FirstOrDefaultAsync();

#pragma warning disable CS4014
                        orchestration.EnqueueAction(new ConsolidateMergedAction(releasedCandidate, serviceLineBranch));
#pragma warning restore
                    }

                    if (!string.IsNullOrEmpty(tagName))
                    {
                        await AppendProcess(cli.Push(tagName)).WaitUntilComplete();
                    }

                    await AppendProcess(cli.Push(serviceLineBranch)).WaitUntilComplete();
                }
            }