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