diff --git a/src/Maestro/SubscriptionActorService/PullRequestActor.cs b/src/Maestro/SubscriptionActorService/PullRequestActor.cs index 9d87a786bf..aa8cbe4a4b 100644 --- a/src/Maestro/SubscriptionActorService/PullRequestActor.cs +++ b/src/Maestro/SubscriptionActorService/PullRequestActor.cs @@ -18,6 +18,7 @@ using Microsoft.Extensions.Logging; using Microsoft.ServiceFabric.Actors; using Microsoft.ServiceFabric.Actors.Runtime; +using Microsoft.VisualStudio.Services.Common; using ProductConstructionService.Client; using ProductConstructionService.Client.Models; using SubscriptionActorService.StateModel; @@ -872,8 +873,11 @@ await AddDependencyFlowEventsAsync( MergePolicyCheckResult.PendingPolicies, pr.Url); + var requiredDescriptionUpdates = + await CalculateOriginalDependencies(darcRemote, targetRepository, targetBranch, targetRepositoryUpdates); + pullRequest.Description = await _pullRequestBuilder.CalculatePRDescriptionAndCommitUpdatesAsync( - targetRepositoryUpdates.RequiredUpdates, + requiredDescriptionUpdates, pullRequest.Description, targetRepository, pullRequest.HeadBranch); @@ -1075,6 +1079,48 @@ private async Task GetRepositoryBranchUpdate() private static string GetNewBranchName(string targetBranch) => $"darc-{targetBranch}-{Guid.NewGuid()}"; + /// + /// Given a set of updates, replace the `from` version of every dependency update with the corresponding version + /// from the target branch + /// + /// Darc client used to fetch target branch dependencies. + /// Target repository to fetch the dependencies from. + /// Target branch to fetch the dependencies from. + /// Incoming updates to the repository + /// + /// Asset update and the corresponding list of altered dependencies + /// + /// + /// This method is intended for use in situations where we want to keep the information about the original dependency + /// version, such as when updating PR descriptions. + /// + private static async Task deps)>> CalculateOriginalDependencies( + IRemote darcRemote, + string targetRepository, + string targetBranch, + TargetRepoDependencyUpdate targetRepositoryUpdates) + { + List targetBranchDeps = [..await darcRemote.GetDependenciesAsync(targetRepository, targetBranch)]; + + List<(UpdateAssetsParameters update, List deps)> alteredUpdates = []; + foreach (var requiredUpdate in targetRepositoryUpdates.RequiredUpdates) + { + var updatedDependencies = requiredUpdate.deps + .Select(dependency => new DependencyUpdate() + { + From = targetBranchDeps + .Where(replace => dependency.From.Name == replace.Name) + .FirstOrDefault(dependency.From), + To = dependency.To, + }) + .ToList(); + + alteredUpdates.Add((requiredUpdate.update, updatedDependencies)); + } + + return alteredUpdates; + } + #region Code flow subscriptions /// diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs index 61b07c9f1c..7562323480 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.Net; using Maestro.Contracts; using Maestro.Data.Models; @@ -649,8 +650,11 @@ await AddDependencyFlowEventsAsync( MergePolicyCheckResult.PendingPolicies, pr.Url); + var requiredDescriptionUpdates = + await CalculateOriginalDependencies(darcRemote, targetRepository, targetBranch, targetRepositoryUpdates); + pullRequest.Description = await _pullRequestBuilder.CalculatePRDescriptionAndCommitUpdatesAsync( - targetRepositoryUpdates.RequiredUpdates, + requiredDescriptionUpdates, pullRequest.Description, targetRepository, pullRequest.HeadBranch); @@ -836,6 +840,48 @@ private async Task ClearAllStateAsync() await _pullRequestUpdateReminders.UnsetReminderAsync(); } + /// + /// Given a set of updates, replace the `from` version of every dependency update with the corresponding version + /// from the target branch + /// + /// Darc client used to fetch target branch dependencies. + /// Target repository to fetch the dependencies from. + /// Target branch to fetch the dependencies from. + /// Incoming updates to the repository + /// + /// Subscription update and the corresponding list of altered dependencies + /// + /// + /// This method is intended for use in situations where we want to keep the information about the original dependency + /// version, such as when updating PR descriptions. + /// + private static async Task deps)>> CalculateOriginalDependencies( + IRemote darcRemote, + string targetRepository, + string targetBranch, + TargetRepoDependencyUpdate targetRepositoryUpdates) + { + List targetBranchDeps = [.. await darcRemote.GetDependenciesAsync(targetRepository, targetBranch)]; + + List<(SubscriptionUpdateWorkItem update, List deps)> alteredUpdates = []; + foreach (var requiredUpdate in targetRepositoryUpdates.RequiredUpdates) + { + var updatedDependencies = requiredUpdate.deps + .Select(dependency => new DependencyUpdate() + { + From = targetBranchDeps + .Where(replace => dependency.From.Name == replace.Name) + .FirstOrDefault(dependency.From), + To = dependency.To, + }) + .ToList(); + + alteredUpdates.Add((requiredUpdate.update, updatedDependencies)); + } + + return alteredUpdates; + } + #region Code flow subscriptions /// diff --git a/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs b/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs index 94a3466004..ff19de102f 100644 --- a/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs +++ b/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs @@ -54,7 +54,7 @@ public void SetTestParameters(TestParameters parameters) if (!string.IsNullOrEmpty(_parameters.MaestroToken)) { _baseDarcRunArgs.AddRange(["-p", _parameters.MaestroToken]); - } + } } protected async Task WaitForPullRequestAsync(string targetRepo, string targetBranch) @@ -487,7 +487,10 @@ protected async Task AddDependenciesToLocalRepo(string repoPath, string name, st { using (ChangeDirectory(repoPath)) { - await RunDarcAsync(["add-dependency", "--name", name, "--type", isToolset ? "toolset" : "product", "--repo", repoUri, "--version", "0.0.1"]); + await RunDarcAsync( + [ + "add-dependency", "--name", name, "--version", "0.0.1", "--type", isToolset ? "toolset" : "product", "--repo", repoUri + ]); } } protected async Task GetTestChannelsAsync() @@ -682,7 +685,7 @@ protected async Task AddDependenciesToLocalRepo(string repoPath, List protected async Task GatherDrop(int buildId, string outputDir, bool includeReleased, string extraAssetsRegex) { - string[] args = [ "gather-drop", "--id", buildId.ToString(), "--dry-run", "--output-dir", outputDir ]; + string[] args = ["gather-drop", "--id", buildId.ToString(), "--dry-run", "--output-dir", outputDir]; if (includeReleased) { diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs index 1ab0ae4b35..d781a8d2c9 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs @@ -660,7 +660,10 @@ protected async Task AddDependenciesToLocalRepo(string repoPath, List { foreach (AssetData asset in dependencies) { - List parameters = ["add-dependency", "--name", asset.Name, "--type", "product", "--repo", repoUri]; + List parameters = + [ + "add-dependency", "--name", asset.Name,"--type", "product", "--repo", repoUri, + ]; if (!string.IsNullOrEmpty(coherentParent)) {