diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 87e9dfbb48..76c258146e 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "microsoft.dnceng.secretmanager": { - "version": "1.1.0-beta.24555.1", + "version": "1.1.0-beta.24562.1", "commands": [ "secret-manager" ] @@ -15,7 +15,7 @@ ] }, "microsoft.dnceng.configuration.bootstrap": { - "version": "1.1.0-beta.24555.1", + "version": "1.1.0-beta.24562.1", "commands": [ "bootstrap-dnceng-configuration" ] diff --git a/.vault-config/product-construction-prod.yaml b/.vault-config/product-construction-prod.yaml index 7a41820e10..d79bb0467d 100644 --- a/.vault-config/product-construction-prod.yaml +++ b/.vault-config/product-construction-prod.yaml @@ -28,7 +28,7 @@ secrets: name: BotAccount-dotnet-bot gitHubBotAccountName: dotnet-bot - dotnet-bot-maestro-auth-test-content-rw: + dotnet-bot-maestro-auth-test-content-rw-pr-rw: type: github-access-token parameters: gitHubBotAccountSecret: diff --git a/Directory.Packages.props b/Directory.Packages.props index 4e2d87c600..b525ffdcd0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -102,19 +102,19 @@ - - + + - - + + - + - - + + @@ -160,4 +160,4 @@ - \ No newline at end of file + diff --git a/azure-pipelines-product-construction-service.yml b/azure-pipelines-product-construction-service.yml index 8bdc12edf8..919def75d1 100644 --- a/azure-pipelines-product-construction-service.yml +++ b/azure-pipelines-product-construction-service.yml @@ -268,4 +268,10 @@ stages: parameters: name: scenarioTests_Other displayName: Other tests - testFilter: 'TestCategory!=GitHub&TestCategory!=AzDO' + testFilter: 'TestCategory!=GitHub&TestCategory!=AzDO&TestCategory!=CodeFlow' + + - template: /eng/templates/jobs/e2e-pcs-tests.yml + parameters: + name: scenarioTests_CodeFlow + displayName: Code Flow tests + testFilter: 'TestCategory=CodeFlow' diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9d089373ad..fcd6d546c0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -91,37 +91,37 @@ - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/arcade - 24e02f80c5458d1f75240ae57fc2a98fb8a9022a + 3c7e11bf80279cde53a6251c4d0fa10e613fc739 - + https://github.com/dotnet/dnceng - 64878fb972e889fc51b1f2e80a1ad2285fbd896c + b61ece47324607e2ab69de0b6e8cf2d19cef2570 - + https://github.com/dotnet/dnceng - 64878fb972e889fc51b1f2e80a1ad2285fbd896c + b61ece47324607e2ab69de0b6e8cf2d19cef2570 diff --git a/eng/Versions.props b/eng/Versions.props index 620c005968..00991bf1e4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,11 +9,11 @@ true 1.0.0-preview.1 - 8.0.0-beta.24525.2 - 8.0.0-beta.24525.2 - 8.0.0-beta.24525.2 - 8.0.0-beta.24525.2 - 8.0.0-beta.24525.2 + 8.0.0-beta.24570.5 + 8.0.0-beta.24570.5 + 8.0.0-beta.24570.5 + 8.0.0-beta.24570.5 + 8.0.0-beta.24570.5 17.4.1 1.1.0-beta.24376.1 1.1.0-beta.24376.1 @@ -37,8 +37,8 @@ 1.1.0-beta.24376.1 1.1.0-beta.24376.1 1.1.0-beta.24376.1 - 1.1.0-beta.24555.1 - 1.1.0-beta.24555.1 + 1.1.0-beta.24562.1 + 1.1.0-beta.24562.1 diff --git a/eng/templates/jobs/e2e-pcs-tests.yml b/eng/templates/jobs/e2e-pcs-tests.yml index a88d5fbd4d..7319270766 100644 --- a/eng/templates/jobs/e2e-pcs-tests.yml +++ b/eng/templates/jobs/e2e-pcs-tests.yml @@ -107,7 +107,7 @@ jobs: env: PCS_BASEURI: ${{ variables.PcsTestEndpoint }} PCS_TOKEN: $(GetAuthInfo.Token) - GITHUB_TOKEN: $(dotnet-bot-maestro-auth-test-content-rw) + GITHUB_TOKEN: $(dotnet-bot-maestro-auth-test-content-rw-pr-rw) AZDO_TOKEN: $(AzdoToken) DARC_PACKAGE_SOURCE: $(Pipeline.Workspace)\PackageArtifacts DARC_DIR: $(Build.SourcesDirectory)\darc diff --git a/global.json b/global.json index 06c842e071..2643ca11b4 100644 --- a/global.json +++ b/global.json @@ -15,6 +15,6 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24525.2" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24570.5" } } diff --git a/src/Maestro/Client/src/GlobalSuppressions.cs b/src/Maestro/Client/src/GlobalSuppressions.cs index 5bad91fbe7..248cabdb3a 100644 --- a/src/Maestro/Client/src/GlobalSuppressions.cs +++ b/src/Maestro/Client/src/GlobalSuppressions.cs @@ -7,3 +7,4 @@ [assembly: SuppressMessage("Performance", "CA1834:Consider using 'StringBuilder.Append(char)' when applicable", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:Microsoft.DotNet.Maestro.Client")] [assembly: SuppressMessage("Performance", "CA1844:Provide memory-based overrides of async methods when subclassing 'Stream'", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:Microsoft.DotNet.Maestro.Client")] [assembly: SuppressMessage("Style", "IDE0034:Simplify 'default' expression", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:Microsoft.DotNet.Maestro.Client")] +[assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:Microsoft.DotNet.Maestro.Client")] diff --git a/src/Maestro/DependencyUpdater/DependencyUpdater.cs b/src/Maestro/DependencyUpdater/DependencyUpdater.cs index f34e74734b..e011f4bcb9 100644 --- a/src/Maestro/DependencyUpdater/DependencyUpdater.cs +++ b/src/Maestro/DependencyUpdater/DependencyUpdater.cs @@ -11,6 +11,7 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Internal.Logging; using Microsoft.DotNet.ServiceFabric.ServiceHost; using Microsoft.EntityFrameworkCore; @@ -296,7 +297,7 @@ public async Task UpdateLongestBuildPathAsync(CancellationToken cancellationToke }; _logger.LogInformation($"Will update {channel.Name} to best case time {lbp.BestCaseTimeInMinutes} and worst case time {lbp.WorstCaseTimeInMinutes}"); - await _context.LongestBuildPaths.AddAsync(lbp); + await _context.LongestBuildPaths.AddAsync(lbp, cancellationToken); } else { @@ -304,7 +305,7 @@ public async Task UpdateLongestBuildPathAsync(CancellationToken cancellationToke } } - await _context.SaveChangesAsync(); + await _context.SaveChangesAsync(cancellationToken); } } diff --git a/src/Maestro/FeedCleanerService/FeedCleanerService.cs b/src/Maestro/FeedCleanerService/FeedCleanerService.cs index 441026fd74..dc584841ae 100644 --- a/src/Maestro/FeedCleanerService/FeedCleanerService.cs +++ b/src/Maestro/FeedCleanerService/FeedCleanerService.cs @@ -14,6 +14,7 @@ using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.DotNet.ServiceFabric.ServiceHost; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -291,7 +292,7 @@ await _azureDevOpsClient.DeleteNuGetPackageVersionFromFeedAsync(feed.Account, /// Version to search for /// Feeds to search /// List of feeds in the package mappings where the provided package and version are available - private List GetReleaseFeedsWherePackageIsAvailable( + private static List GetReleaseFeedsWherePackageIsAvailable( string name, string version, Dictionary>> packageMappings) diff --git a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowEdge.cs b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowEdge.cs index 33a01a0d90..a96536ee8f 100644 --- a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowEdge.cs +++ b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowEdge.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.Api.Model.v2018_07_16; diff --git a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowGraph.cs b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowGraph.cs index 67d3f4fa56..64a40f27e0 100644 --- a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowGraph.cs +++ b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowGraph.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.Api.Model.v2018_07_16; diff --git a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowRef.cs b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowRef.cs index 8ca15a1cc2..2b68f27500 100644 --- a/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowRef.cs +++ b/src/Maestro/Maestro.Api.Model/v2018_07_16/FlowRef.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Newtonsoft.Json; namespace Maestro.Api.Model.v2018_07_16; diff --git a/src/Maestro/Maestro.Api.Model/v2018_07_16/SubscriptionPolicy.cs b/src/Maestro/Maestro.Api.Model/v2018_07_16/SubscriptionPolicy.cs index cba500be66..fc9e417e67 100644 --- a/src/Maestro/Maestro.Api.Model/v2018_07_16/SubscriptionPolicy.cs +++ b/src/Maestro/Maestro.Api.Model/v2018_07_16/SubscriptionPolicy.cs @@ -23,7 +23,7 @@ public SubscriptionPolicy(Data.Models.SubscriptionPolicy other) UpdateFrequency = (UpdateFrequency)(int)other.UpdateFrequency; MergePolicies = other.MergePolicies != null ? other.MergePolicies.Select(p => new MergePolicy(p)).ToImmutableList() - : ImmutableList.Empty; + : []; } public bool Batchable { get; set; } = false; diff --git a/src/Maestro/Maestro.Api.Model/v2019_01_16/Build.cs b/src/Maestro/Maestro.Api.Model/v2019_01_16/Build.cs index 2a1cd00d8b..e65a56070c 100644 --- a/src/Maestro/Maestro.Api.Model/v2019_01_16/Build.cs +++ b/src/Maestro/Maestro.Api.Model/v2019_01_16/Build.cs @@ -58,7 +58,7 @@ public Build(Data.Models.Build other) public string GitHubBranch { get; set; } - public bool PublishUsingPipelines + public static bool PublishUsingPipelines { get { diff --git a/src/Maestro/Maestro.Api.Model/v2019_01_16/BuildData.cs b/src/Maestro/Maestro.Api.Model/v2019_01_16/BuildData.cs index 30ebf5a179..d16e26742c 100644 --- a/src/Maestro/Maestro.Api.Model/v2019_01_16/BuildData.cs +++ b/src/Maestro/Maestro.Api.Model/v2019_01_16/BuildData.cs @@ -41,7 +41,7 @@ public class BuildData public string GitHubBranch { get; set; } - public bool PublishUsingPipelines + public static bool PublishUsingPipelines { get { diff --git a/src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs b/src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs index 866a4ed932..9555c4f774 100644 --- a/src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs +++ b/src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs @@ -11,7 +11,7 @@ namespace Maestro.Common.AppCredentials; /// public class AppCredential : TokenCredential { - public static string AUTH_CACHE = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".darc"); + public static readonly string AUTH_CACHE = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".darc"); private static readonly string AUTH_RECORD_PREFIX = ".auth-record"; diff --git a/src/Maestro/Maestro.Data/BuildAssetRegistryContext.cs b/src/Maestro/Maestro.Data/BuildAssetRegistryContext.cs index c79fb3e590..080ec061d8 100644 --- a/src/Maestro/Maestro.Data/BuildAssetRegistryContext.cs +++ b/src/Maestro/Maestro.Data/BuildAssetRegistryContext.cs @@ -379,7 +379,7 @@ where buildIds.Contains(build.Id) b.DateProduced > build.DateProduced); dict[id].Staleness = newer.Count(); } - return dict.Values.ToList(); + return [.. dict.Values]; } public bool IsProductDependency( diff --git a/src/Maestro/Maestro.Data/Models/Build.cs b/src/Maestro/Maestro.Data/Models/Build.cs index 07914a7616..55669747ac 100644 --- a/src/Maestro/Maestro.Data/Models/Build.cs +++ b/src/Maestro/Maestro.Data/Models/Build.cs @@ -136,7 +136,7 @@ public override bool Equals(object obj) public override int GetHashCode() { - return (BuildId, ChannelId).GetHashCode(); + return HashCode.Combine(BuildId, ChannelId); } } diff --git a/src/Maestro/Maestro.DataProviders/SqlBarClient.cs b/src/Maestro/Maestro.DataProviders/SqlBarClient.cs index cd3b8fd569..3aaa6254aa 100644 --- a/src/Maestro/Maestro.DataProviders/SqlBarClient.cs +++ b/src/Maestro/Maestro.DataProviders/SqlBarClient.cs @@ -13,6 +13,7 @@ using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.DataProviders; diff --git a/src/Maestro/Maestro.MergePolicies/AllChecksSuccessfulMergePolicy.cs b/src/Maestro/Maestro.MergePolicies/AllChecksSuccessfulMergePolicy.cs index 8ae6b09c6d..a9b5342f52 100644 --- a/src/Maestro/Maestro.MergePolicies/AllChecksSuccessfulMergePolicy.cs +++ b/src/Maestro/Maestro.MergePolicies/AllChecksSuccessfulMergePolicy.cs @@ -8,6 +8,7 @@ using Maestro.Contracts; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; namespace Maestro.MergePolicies; diff --git a/src/Maestro/Maestro.MergePolicies/NoRequestedChangesMergePolicy.cs b/src/Maestro/Maestro.MergePolicies/NoRequestedChangesMergePolicy.cs index d77b7a4cbb..bb000faf06 100644 --- a/src/Maestro/Maestro.MergePolicies/NoRequestedChangesMergePolicy.cs +++ b/src/Maestro/Maestro.MergePolicies/NoRequestedChangesMergePolicy.cs @@ -4,6 +4,7 @@ using Maestro.Contracts; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Maestro/Maestro.Web/Api/v2018_07_16/Controllers/ChannelsController.cs b/src/Maestro/Maestro.Web/Api/v2018_07_16/Controllers/ChannelsController.cs index 02e9a9db1a..0d5d4addf3 100644 --- a/src/Maestro/Maestro.Web/Api/v2018_07_16/Controllers/ChannelsController.cs +++ b/src/Maestro/Maestro.Web/Api/v2018_07_16/Controllers/ChannelsController.cs @@ -18,6 +18,7 @@ using Channel = Maestro.Api.Model.v2018_07_16.Channel; using FlowGraph = Maestro.Api.Model.v2018_07_16.FlowGraph; using ReleasePipeline = Maestro.Api.Model.v2018_07_16.ReleasePipeline; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.Web.Api.v2018_07_16.Controllers; diff --git a/src/Maestro/Maestro.Web/Api/v2020_02_20/Controllers/BuildsController.cs b/src/Maestro/Maestro.Web/Api/v2020_02_20/Controllers/BuildsController.cs index 67cd0d39cd..1610872e91 100644 --- a/src/Maestro/Maestro.Web/Api/v2020_02_20/Controllers/BuildsController.cs +++ b/src/Maestro/Maestro.Web/Api/v2020_02_20/Controllers/BuildsController.cs @@ -18,6 +18,7 @@ using Microsoft.Extensions.Internal; using Newtonsoft.Json.Linq; using Maestro.Api.Model.v2020_02_20; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.Web.Api.v2020_02_20.Controllers; diff --git a/src/Maestro/Maestro.Web/BackgroundQueue.cs b/src/Maestro/Maestro.Web/BackgroundQueue.cs index 778ebcc8de..e02d031754 100644 --- a/src/Maestro/Maestro.Web/BackgroundQueue.cs +++ b/src/Maestro/Maestro.Web/BackgroundQueue.cs @@ -69,7 +69,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) _workItems.CompleteAdding(); } - if (_workItems.TryTake(out (Type type, JToken args) item, 1000)) + if (_workItems.TryTake(out (Type type, JToken args) item, 1000, stoppingToken)) { using (Operation op = _operations.BeginOperation("Executing background work: {item} ({args})", item.type.Name, item.args.ToString(Formatting.None))) { diff --git a/src/Maestro/Maestro.Web/Pages/DependencyFlow/Incoming.cshtml.cs b/src/Maestro/Maestro.Web/Pages/DependencyFlow/Incoming.cshtml.cs index 699b13f777..32334d5c79 100644 --- a/src/Maestro/Maestro.Web/Pages/DependencyFlow/Incoming.cshtml.cs +++ b/src/Maestro/Maestro.Web/Pages/DependencyFlow/Incoming.cshtml.cs @@ -22,7 +22,7 @@ namespace Maestro.Web.Pages.DependencyFlow; public class IncomingModel : PageModel { - private static readonly Regex _repoParser = new Regex(@"https?://(www\.)?github.com/(?[A-Za-z0-9-_\.]+)/(?[A-Za-z0-9-_\.]+)"); + private static readonly Regex _repoParser = new(@"https?://(www\.)?github.com/(?[A-Za-z0-9-_\.]+)/(?[A-Za-z0-9-_\.]+)"); private readonly BuildAssetRegistryContext _context; private readonly IGitHubClient _github; @@ -180,7 +180,7 @@ public string GetBuildUrl(Build? build) ? "(unknown)" : $"https://dev.azure.com/{build.AzureDevOpsAccount}/{build.AzureDevOpsProject}/_build/results?buildId={build.AzureDevOpsBuildId}&view=results"; - private bool IncludeRepo(GitHubInfo? gitHubInfo) + private static bool IncludeRepo(GitHubInfo? gitHubInfo) { if (string.Equals(gitHubInfo?.Owner, "dotnet", StringComparison.OrdinalIgnoreCase) && string.Equals(gitHubInfo?.Repo, "blazor", StringComparison.OrdinalIgnoreCase)) diff --git a/src/Maestro/Maestro.Web/Startup.cs b/src/Maestro/Maestro.Web/Startup.cs index 907230808e..ecb9f4ab1d 100644 --- a/src/Maestro/Maestro.Web/Startup.cs +++ b/src/Maestro/Maestro.Web/Startup.cs @@ -49,7 +49,6 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; @@ -293,12 +292,12 @@ public override void ConfigureServices(IServiceCollection services) (doc, req) => { bool http = HostingEnvironment.IsDevelopment(); - doc.Servers = new List - { + doc.Servers = + [ new() { Url = $"{req.Scheme}://{req.Host.Value}/", }, - }; + ]; req.HttpContext.Response.Headers["Access-Control-Allow-Origin"] = "*"; }); diff --git a/src/Maestro/Microsoft.DotNet.Maestro.Tasks/src/PushMetadataToBuildAssetRegistry.cs b/src/Maestro/Microsoft.DotNet.Maestro.Tasks/src/PushMetadataToBuildAssetRegistry.cs index a2d3b74165..ed83a5cd6c 100644 --- a/src/Maestro/Microsoft.DotNet.Maestro.Tasks/src/PushMetadataToBuildAssetRegistry.cs +++ b/src/Maestro/Microsoft.DotNet.Maestro.Tasks/src/PushMetadataToBuildAssetRegistry.cs @@ -3,6 +3,7 @@ using Microsoft.Build.Framework; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.DotNet.Maestro.Tasks.Proxies; @@ -274,7 +275,7 @@ private async Task> GetBuildDependenciesAsync( { if (!buildCache.TryGetValue(asset.BuildId, out Client.Models.Build producingBuild)) { - producingBuild = await client.Builds.GetBuildAsync(asset.BuildId); + producingBuild = await client.Builds.GetBuildAsync(asset.BuildId, cancellationToken); buildCache.Add(asset.BuildId, producingBuild); } diff --git a/src/Maestro/SubscriptionActorService/BatchedPullRequestActorImplementation.cs b/src/Maestro/SubscriptionActorService/BatchedPullRequestActorImplementation.cs index ab3d7dca97..230bd9e893 100644 --- a/src/Maestro/SubscriptionActorService/BatchedPullRequestActorImplementation.cs +++ b/src/Maestro/SubscriptionActorService/BatchedPullRequestActorImplementation.cs @@ -13,7 +13,6 @@ using Microsoft.Extensions.Logging; using Microsoft.ServiceFabric.Actors; using Microsoft.ServiceFabric.Actors.Runtime; -using ProductConstructionService.Client; namespace SubscriptionActorService; @@ -42,7 +41,6 @@ public BatchedPullRequestActorImplementation( ICoherencyUpdateResolver updateResolver, BuildAssetRegistryContext context, IRemoteFactory remoteFactory, - IProductConstructionServiceApi pcsClient, IPullRequestBuilder pullRequestBuilder, ILoggerFactory loggerFactory, IActionRunner actionRunner, @@ -54,7 +52,6 @@ public BatchedPullRequestActorImplementation( updateResolver, context, remoteFactory, - pcsClient, pullRequestBuilder, loggerFactory, actionRunner, diff --git a/src/Maestro/SubscriptionActorService/DarcRemoteFactory.cs b/src/Maestro/SubscriptionActorService/DarcRemoteFactory.cs index 375273931c..87138e96d3 100644 --- a/src/Maestro/SubscriptionActorService/DarcRemoteFactory.cs +++ b/src/Maestro/SubscriptionActorService/DarcRemoteFactory.cs @@ -24,7 +24,6 @@ public class DarcRemoteFactory : IRemoteFactory private readonly BuildAssetRegistryContext _context; private readonly DarcRemoteMemoryCache _cache; private readonly TemporaryFiles _tempFiles; - private readonly ILocalGit _localGit; private readonly IVersionDetailsParser _versionDetailsParser; private readonly IProcessManager _processManager; private readonly OperationManager _operations; @@ -36,13 +35,11 @@ public DarcRemoteFactory( DarcRemoteMemoryCache memoryCache, BuildAssetRegistryContext context, TemporaryFiles tempFiles, - ILocalGit localGit, IVersionDetailsParser versionDetailsParser, IProcessManager processManager, OperationManager operations) { _tempFiles = tempFiles; - _localGit = localGit; _versionDetailsParser = versionDetailsParser; _processManager = processManager; _operations = operations; diff --git a/src/Maestro/SubscriptionActorService/NonBatchedPullRequestActorImplementation.cs b/src/Maestro/SubscriptionActorService/NonBatchedPullRequestActorImplementation.cs index 6e5d835729..abea8785ef 100644 --- a/src/Maestro/SubscriptionActorService/NonBatchedPullRequestActorImplementation.cs +++ b/src/Maestro/SubscriptionActorService/NonBatchedPullRequestActorImplementation.cs @@ -13,7 +13,6 @@ using Microsoft.Extensions.Logging; using Microsoft.ServiceFabric.Actors; using Microsoft.ServiceFabric.Actors.Runtime; -using ProductConstructionService.Client; using SubscriptionActorService.StateModel; namespace SubscriptionActorService; @@ -45,7 +44,6 @@ public NonBatchedPullRequestActorImplementation( ICoherencyUpdateResolver updateResolver, BuildAssetRegistryContext context, IRemoteFactory darcFactory, - IProductConstructionServiceApi pcsClient, IPullRequestBuilder pullRequestBuilder, ILoggerFactory loggerFactory, IActionRunner actionRunner, @@ -58,7 +56,6 @@ public NonBatchedPullRequestActorImplementation( updateResolver, context, darcFactory, - pcsClient, pullRequestBuilder, loggerFactory, actionRunner, diff --git a/src/Maestro/SubscriptionActorService/PullRequestActor.cs b/src/Maestro/SubscriptionActorService/PullRequestActor.cs index aa8cbe4a4b..b250673817 100644 --- a/src/Maestro/SubscriptionActorService/PullRequestActor.cs +++ b/src/Maestro/SubscriptionActorService/PullRequestActor.cs @@ -6,21 +6,20 @@ using System.Linq; using System.Net; using System.Net.Http; -using System.Security.Policy; using System.Threading.Tasks; using Maestro.Contracts; using Maestro.Data; using Maestro.Data.Models; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.ServiceFabric.ServiceHost; using Microsoft.DotNet.ServiceFabric.ServiceHost.Actors; 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; using Asset = Maestro.Contracts.Asset; @@ -65,7 +64,6 @@ internal class PullRequestActor : IPullRequestActor, IRemindable, IActionTracker private readonly IMergePolicyEvaluator _mergePolicyEvaluator; private readonly BuildAssetRegistryContext _context; private readonly IRemoteFactory _darcFactory; - private readonly IProductConstructionServiceApi _pcsClient; private readonly ICoherencyUpdateResolver _coherencyUpdateResolver; private readonly IPullRequestBuilder _pullRequestBuilder; private readonly ILoggerFactory _loggerFactory; @@ -80,7 +78,6 @@ public PullRequestActor( IMergePolicyEvaluator mergePolicyEvaluator, BuildAssetRegistryContext context, IRemoteFactory darcFactory, - IProductConstructionServiceApi pcsClient, ICoherencyUpdateResolver coherencyUpdateResolver, IPullRequestBuilder pullRequestBuilder, ILoggerFactory loggerFactory, @@ -91,7 +88,6 @@ public PullRequestActor( _mergePolicyEvaluator = mergePolicyEvaluator; _context = context; _darcFactory = darcFactory; - _pcsClient = pcsClient; _coherencyUpdateResolver = coherencyUpdateResolver; _pullRequestBuilder = pullRequestBuilder; _loggerFactory = loggerFactory; @@ -116,7 +112,6 @@ private PullRequestActorImplementation GetImplementation(ActorId actorId, IActor _coherencyUpdateResolver, _context, _darcFactory, - _pcsClient, _pullRequestBuilder, _loggerFactory, _actionRunner, @@ -131,7 +126,6 @@ private PullRequestActorImplementation GetImplementation(ActorId actorId, IActor _coherencyUpdateResolver, _context, _darcFactory, - _pcsClient, _pullRequestBuilder, _loggerFactory, _actionRunner, @@ -190,7 +184,6 @@ internal abstract class PullRequestActorImplementation : IPullRequestActor, IAct private readonly IMergePolicyEvaluator _mergePolicyEvaluator; private readonly BuildAssetRegistryContext _context; private readonly IRemoteFactory _remoteFactory; - private readonly IProductConstructionServiceApi _pcsClient; private readonly IPullRequestBuilder _pullRequestBuilder; private readonly IActionRunner _actionRunner; private readonly IActorProxyFactory _subscriptionActorFactory; @@ -208,7 +201,6 @@ protected PullRequestActorImplementation( ICoherencyUpdateResolver coherencyUpdateResolver, BuildAssetRegistryContext context, IRemoteFactory darcFactory, - IProductConstructionServiceApi pcsClient, IPullRequestBuilder pullRequestBuilder, ILoggerFactory loggerFactory, IActionRunner actionRunner, @@ -218,7 +210,6 @@ protected PullRequestActorImplementation( _coherencyUpdateResolver = coherencyUpdateResolver; _context = context; _remoteFactory = darcFactory; - _pcsClient = pcsClient; _pullRequestBuilder = pullRequestBuilder; _actionRunner = actionRunner; _subscriptionActorFactory = subscriptionActorFactory; @@ -298,7 +289,7 @@ public async Task> ProcessPendingUpdatesAsync() // Code flow updates are handled separetely if (updates.Any(u => u.Type == SubscriptionType.DependenciesAndSources)) { - return await ProcessCodeFlowUpdatesAsync(updates, pr); + return await ProcessCodeFlowUpdatesAsync(); } var subscriptionIds = updates.Count > 1 @@ -563,12 +554,18 @@ private async Task> CheckMergePolicyAsync(I { await remote.MergeDependencyPullRequestAsync(pr.Url, new MergePullRequestParameters()); } - catch + catch (PullRequestNotMergeableException notMergeableException) + { + _logger.LogInformation("NOT Merged: PR '{url}' is not mergeable - {message}", pr.Url, notMergeableException.Message); + return ActionResult.Create(MergePolicyCheckResult.FailedToMerge, $"NOT Merged: PR '{pr.Url}' cannot be merged."); + } + catch (Exception ex) { - _logger.LogInformation("NOT Merged: PR '{url}' has merge conflicts.", pr.Url); - return ActionResult.Create(MergePolicyCheckResult.FailedToMerge, $"NOT Merged: PR '{pr.Url}' has merge conflicts."); + _logger.LogError(ex, "NOT Merged: Failed to merge PR '{url}' - {message}", pr.Url, ex.Message); + return ActionResult.Create(MergePolicyCheckResult.FailedToMerge, $"NOT Merged: PR '{pr.Url}' cannot be merged."); } + string passedPolicies = string.Join(", ", policyDefinitions.Select(p => p.Name)); _logger.LogInformation("Merged: PR '{url}' passed policies {passedPolicies}", pr.Url, passedPolicies); return ActionResult.Create( @@ -672,7 +669,7 @@ public async Task> UpdateAssetsAsync( if (type == SubscriptionType.DependenciesAndSources) { - var result = await ProcessCodeFlowUpdatesAsync([updateParameter], pr); + var result = await ProcessCodeFlowUpdatesAsync(); return ActionResult.Create(result.Message); } @@ -1126,9 +1123,7 @@ private async Task GetRepositoryBranchUpdate() /// /// Alternative to ProcessPendingUpdatesAsync that is used in the code flow (VMR) scenario. /// - private Task> ProcessCodeFlowUpdatesAsync( - List updates, - InProgressPullRequest? pr) + private Task> ProcessCodeFlowUpdatesAsync() { _logger.LogWarning("Code flow updates cannot be batched with other updates. Will process the last update only."); return Task.FromResult(ActionResult.Create(false, $"Code flow subscriptions are not supported in Maestro")); diff --git a/src/Maestro/SubscriptionActorService/PullRequestBuilder.cs b/src/Maestro/SubscriptionActorService/PullRequestBuilder.cs index 31f249408a..8788a69741 100644 --- a/src/Maestro/SubscriptionActorService/PullRequestBuilder.cs +++ b/src/Maestro/SubscriptionActorService/PullRequestBuilder.cs @@ -10,6 +10,8 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using SubscriptionActorService.StateModel; diff --git a/src/Maestro/SubscriptionActorService/PullRequestPolicyFailureNotifier.cs b/src/Maestro/SubscriptionActorService/PullRequestPolicyFailureNotifier.cs index 982cd8860c..a1a6ca32a4 100644 --- a/src/Maestro/SubscriptionActorService/PullRequestPolicyFailureNotifier.cs +++ b/src/Maestro/SubscriptionActorService/PullRequestPolicyFailureNotifier.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.Extensions.Logging; using SubscriptionActorService.StateModel; diff --git a/src/Microsoft.DotNet.Darc/Darc/Helpers/CancellationKeyListener.cs b/src/Microsoft.DotNet.Darc/Darc/Helpers/CancellationKeyListener.cs index 6b2dc477ac..728ae286f1 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Helpers/CancellationKeyListener.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Helpers/CancellationKeyListener.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging; #nullable enable -namespace Microsoft.DotNet.Darc; +namespace Microsoft.DotNet.Darc.Helpers; /// /// Listens for user's key presses and triggers a cancellation when ESC / Space is pressed. @@ -42,7 +42,7 @@ void CancelRun() cancellationSource.Cancel(); } - Console.CancelKeyPress += new ConsoleCancelEventHandler((object? sender, ConsoleCancelEventArgs args) => + Console.CancelKeyPress += new ConsoleCancelEventHandler((sender, args) => { args.Cancel = true; listener.CancelledByKeyPress = true; diff --git a/src/Microsoft.DotNet.Darc/Darc/Helpers/CompactConsoleLoggerFormatter.cs b/src/Microsoft.DotNet.Darc/Darc/Helpers/CompactConsoleLoggerFormatter.cs index 1ef9bc5c20..0becba649a 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Helpers/CompactConsoleLoggerFormatter.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Helpers/CompactConsoleLoggerFormatter.cs @@ -11,7 +11,7 @@ // TODO (https://github.com/dotnet/arcade/issues/8836): Use the formatter from Arcade.Common once we're able to consume latest Arcade #nullable enable -namespace Microsoft.Arcade.Common; +namespace Microsoft.DotNet.Darc.Helpers; /// /// Copied over from SimpleConsoleFormatter. Leaves out the logger name and new line, turning diff --git a/src/Microsoft.DotNet.Darc/Darc/Helpers/RemoteFactory.cs b/src/Microsoft.DotNet.Darc/Darc/Helpers/RemoteFactory.cs index f077080842..cb748a5e6b 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Helpers/RemoteFactory.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Helpers/RemoteFactory.cs @@ -25,7 +25,7 @@ public static IRemote GetRemote(ICommandLineOptions options, string repoUrl, ILo return new Remote(gitClient, new VersionDetailsParser(), logger); } - public static IBarApiClient GetBarClient(ICommandLineOptions options, ILogger logger) + public static IBarApiClient GetBarClient(ICommandLineOptions options) => new BarApiClient( options.BuildAssetRegistryToken, managedIdentityId: null, diff --git a/src/Microsoft.DotNet.Darc/Darc/Helpers/UxHelpers.cs b/src/Microsoft.DotNet.Darc/Darc/Helpers/UxHelpers.cs index da0365d3a2..bdae13f1fa 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Helpers/UxHelpers.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Helpers/UxHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.DotNet.Services.Utility; using Newtonsoft.Json.Linq; @@ -12,7 +13,7 @@ using System.Text; using System.Threading.Tasks; -namespace Microsoft.DotNet.Darc; +namespace Microsoft.DotNet.Darc.Helpers; public static class UxHelpers { @@ -187,7 +188,7 @@ public static string GetMergePoliciesDescription(IEnumerable mergeP { var indentString = new string(' ', keyString.Length); builder.AppendLine(); - foreach (string line in valueLines) + foreach (var line in valueLines) { builder.AppendLine($"{indent}{indentString}{line}"); } @@ -270,7 +271,7 @@ public static string DependencyToString(DependencyDetail dependency) public static string GetSimpleRepoName(string repoUri) { var lastSlash = repoUri.LastIndexOf("/"); - if ((lastSlash != -1) && (lastSlash < (repoUri.Length - 1))) + if (lastSlash != -1 && lastSlash < repoUri.Length - 1) { return repoUri.Substring(lastSlash + 1); } @@ -341,7 +342,7 @@ public static StreamWriter GetOutputFileStreamOrConsole(string outputFile) { return new StreamWriter(Console.OpenStandardOutput()); } - + var fullPath = Path.GetFullPath(outputFile); var directory = Path.GetDirectoryName(fullPath); if (!Directory.Exists(directory)) @@ -360,8 +361,9 @@ public static StreamWriter GetOutputFileStreamOrConsole(string outputFile) /// Repository that the branch should be in /// Branch to check the existence of /// Prompt the user to verify that they want to continue + /// In some cases we only care if a branch exists, for example, we don't need Version.Details.xml for source enable subscriptions /// True if the branch exists, prompting is not desired, or if the user confirms that they want to continue. False otherwise. - public static async Task VerifyAndConfirmBranchExistsAsync(IRemote remote, string repo, string branch, bool prompt) + public static async Task VerifyAndConfirmBranchExistsAsync(IRemote remote, string repo, string branch, bool prompt, bool onlyCheckBranch = false) { const string regexPrefix = "-regex:"; // IRemote doesn't currently provide a way for enumerating all branches in a repo, and the purpose of supporting regex is to allow new ones to match @@ -377,7 +379,14 @@ public static async Task VerifyAndConfirmBranchExistsAsync(IRemote remote, { branch = GitHelpers.NormalizeBranchName(branch); - await remote.GetDependenciesAsync(repo, branch); + if (onlyCheckBranch) + { + await remote.GetLatestCommitAsync(repo, branch); + } + else + { + await remote.GetDependenciesAsync(repo, branch); + } } catch (DependencyFileNotFoundException) { @@ -400,7 +409,7 @@ public static async Task VerifyAndConfirmBranchExistsAsync(IRemote remote, /// True if the repository exists, prompting is not desired, or if the user confirms that they want to continue. False otherwise. public static async Task VerifyAndConfirmRepositoryExistsAsync(IRemote remote, string repo, bool prompt) { - if (!(await remote.RepositoryExistsAsync(repo))) + if (!await remote.RepositoryExistsAsync(repo)) { Console.WriteLine($"Warning: Could not locate repository '{repo}'. Dependency updates may not happen as expected."); if (prompt) @@ -420,7 +429,7 @@ public static async Task VerifyAndConfirmRepositoryExistsAsync(IRemote rem public static bool PromptForYesNo(string message) { char keyChar; - int triesRemaining = 3; + var triesRemaining = 3; do { if (triesRemaining == 0) diff --git a/src/Microsoft.DotNet.Darc/Darc/Models/PopUps/SubscriptionPopUp.cs b/src/Microsoft.DotNet.Darc/Darc/Models/PopUps/SubscriptionPopUp.cs index 3a447fd456..3f025af843 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Models/PopUps/SubscriptionPopUp.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Models/PopUps/SubscriptionPopUp.cs @@ -165,7 +165,7 @@ protected int ParseAndValidateData(SubscriptionData outputYamlData) if (sourceEnabled) { - if (string.IsNullOrEmpty(outputYamlData.SourceDirectory ?? outputYamlData.TargetDirectory)) + if (string.IsNullOrEmpty(outputYamlData.SourceDirectory) && string.IsNullOrEmpty(outputYamlData.TargetDirectory)) { _logger.LogError("Source or target directory must be provided for source-enabled subscriptions"); return Constants.ErrorCode; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/AddBuildToChannelOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/AddBuildToChannelOperation.cs index 086b3c25bb..6171a1de04 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/AddBuildToChannelOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/AddBuildToChannelOperation.cs @@ -11,6 +11,8 @@ using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.DotNet.Services.Utility; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/AddDependencyOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/AddDependencyOperation.cs index 3835efa756..09d634ab6a 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/AddDependencyOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/AddDependencyOperation.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Darc.Operations; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/AddSubscriptionOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/AddSubscriptionOperation.cs index 9abaa8a187..06cc997280 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/AddSubscriptionOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/AddSubscriptionOperation.cs @@ -238,7 +238,7 @@ public override async Task ExecuteAsync() // Verify the target IRemote targetVerifyRemote = RemoteFactory.GetRemote(_options, targetRepository, _logger); - if (!(await UxHelpers.VerifyAndConfirmBranchExistsAsync(targetVerifyRemote, targetRepository, targetBranch, !_options.Quiet))) + if (!(await UxHelpers.VerifyAndConfirmBranchExistsAsync(targetVerifyRemote, targetRepository, targetBranch, !_options.Quiet, onlyCheckBranch: sourceEnabled))) { Console.WriteLine("Aborting subscription creation."); return Constants.ErrorCode; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/CloneOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/CloneOperation.cs index d417c11bd7..47132dc37a 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/CloneOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/CloneOperation.cs @@ -3,6 +3,7 @@ using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -520,8 +521,6 @@ private StrippedDependency(string repoUrl, string commit) Dependencies = [this]; } - private StrippedDependency(DependencyDetail d) : this(d.RepoUri, d.Commit) { } - internal void AddDependency(StrippedDependency dep) { StrippedDependency other = GetDependency(dep); diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteBuildFromChannelOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteBuildFromChannelOperation.cs index 7debde2739..7ec30c4f14 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteBuildFromChannelOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteBuildFromChannelOperation.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteSubscriptionsOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteSubscriptionsOperation.cs index 73597b5f3d..dbb55d2536 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteSubscriptionsOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/DeleteSubscriptionsOperation.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GatherDropOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GatherDropOperation.cs index 8bb9cb50ae..8ffeeb8c8b 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GatherDropOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GatherDropOperation.cs @@ -633,7 +633,11 @@ private async Task GatherDropForBuildAsync(Build build, string mustDownloadAssets.AddRange(assets.Where(asset => Regex.IsMatch(Path.GetFileName(asset.Name), nameMatchRegex))); } - (bool success, bool anyShipping, ConcurrentBag downloadedMainAssets) primaryAssetDownloadResult = await DownloadAssetsToDirectories(assets, build, releaseOutputDirectory, unifiedOutputDirectory); + (bool success, bool anyShipping, ConcurrentBag downloadedMainAssets) primaryAssetDownloadResult = await DownloadAssetsToDirectories( + assets, + releaseOutputDirectory, + unifiedOutputDirectory); + success &= primaryAssetDownloadResult.success; anyShipping |= primaryAssetDownloadResult.anyShipping; downloadedAssets = primaryAssetDownloadResult.downloadedMainAssets; @@ -648,7 +652,11 @@ private async Task GatherDropForBuildAsync(Build build, string var extraAssetsDirectory = Path.Join(rootOutputDirectory, "extra-assets"); Directory.CreateDirectory(extraAssetsDirectory); - (bool success, bool _, ConcurrentBag downloadedExtraAssets) extraAssetDownloadResult = await DownloadAssetsToDirectories(mustDownloadAssets, build, extraAssetsDirectory, unifiedOutputDirectory); + (bool success, bool _, ConcurrentBag downloadedExtraAssets) extraAssetDownloadResult = await DownloadAssetsToDirectories( + mustDownloadAssets, + extraAssetsDirectory, + unifiedOutputDirectory); + extraDownloadedAssets = extraAssetDownloadResult.downloadedExtraAssets; success &= extraAssetDownloadResult.success; if (!success && !_options.ContinueOnError) @@ -676,7 +684,10 @@ private async Task GatherDropForBuildAsync(Build build, string } - private async Task<(bool success, bool anyShipping, ConcurrentBag downloadedAssets)> DownloadAssetsToDirectories(IEnumerable assets, Build build, string specificAssetDirectory, string unifiedOutputDirectory) + private async Task<(bool success, bool anyShipping, ConcurrentBag downloadedAssets)> DownloadAssetsToDirectories( + IEnumerable assets, + string specificAssetDirectory, + string unifiedOutputDirectory) { var success = true; var downloaded = new ConcurrentBag(); @@ -692,7 +703,7 @@ await Task.WhenAll(assets.Select(async asset => try { - DownloadedAsset downloadedAsset = await DownloadAssetAsync(client, build, asset, specificAssetDirectory, unifiedOutputDirectory); + DownloadedAsset downloadedAsset = await DownloadAssetAsync(client, asset, specificAssetDirectory, unifiedOutputDirectory); if (downloadedAsset == null) { // Do nothing, decided not to download. @@ -742,8 +753,8 @@ await Task.WhenAll(assets.Select(async asset => /// {root dir}\{repo}\{build id}\nonshipping\assets - blobs /// {root dir}\{repo}\{build id}\nonshipping\packages - blobs /// - private async Task DownloadAssetAsync(HttpClient client, - Build build, + private async Task DownloadAssetAsync( + HttpClient client, Asset asset, string releaseOutputDirectory, string unifiedOutputDirectory) @@ -812,11 +823,11 @@ private async Task DownloadAssetAsync(HttpClient client, { if (_options.LatestLocation) { - downloadedAsset = await DownloadAssetFromLatestLocation(client, build, asset, assetLocations, releaseOutputDirectory, unifiedOutputDirectory, errors, downloadOutput); + downloadedAsset = await DownloadAssetFromLatestLocation(client, asset, assetLocations, releaseOutputDirectory, unifiedOutputDirectory, errors, downloadOutput); } else { - downloadedAsset = await DownloadAssetFromAnyLocationAsync(client, build, asset, assetLocations, releaseOutputDirectory, unifiedOutputDirectory, errors, downloadOutput); + downloadedAsset = await DownloadAssetFromAnyLocationAsync(client, asset, assetLocations, releaseOutputDirectory, unifiedOutputDirectory, errors, downloadOutput); } if (downloadedAsset.Successful) @@ -842,8 +853,8 @@ private async Task DownloadAssetAsync(HttpClient client, /// Download a single asset from any of its locations. Iterate over the asset's locations /// until the asset download succeed or all locations have been tested. /// - private async Task DownloadAssetFromAnyLocationAsync(HttpClient client, - Build build, + private async Task DownloadAssetFromAnyLocationAsync( + HttpClient client, Asset asset, List assetLocations, string releaseOutputDirectory, @@ -855,8 +866,8 @@ private async Task DownloadAssetFromAnyLocationAsync(HttpClient // path based on the type. Stops at the first successfull download. foreach (AssetLocation location in assetLocations) { - var downloadedAsset = await DownloadAssetFromLocation(client, - build, + var downloadedAsset = await DownloadAssetFromLocation( + client, asset, location, releaseOutputDirectory, @@ -880,8 +891,8 @@ private async Task DownloadAssetFromAnyLocationAsync(HttpClient /// /// Download a single asset from the latest asset location registered. /// - private async Task DownloadAssetFromLatestLocation(HttpClient client, - Build build, + private async Task DownloadAssetFromLatestLocation( + HttpClient client, Asset asset, List assetLocations, string releaseOutputDirectory, @@ -891,8 +902,8 @@ private async Task DownloadAssetFromLatestLocation(HttpClient c { AssetLocation latestLocation = assetLocations.OrderByDescending(al => al.Id).First(); - return await DownloadAssetFromLocation(client, - build, + return await DownloadAssetFromLocation( + client, asset, latestLocation, releaseOutputDirectory, @@ -904,8 +915,8 @@ private async Task DownloadAssetFromLatestLocation(HttpClient c /// /// Download an asset from the asset location provided. /// - private async Task DownloadAssetFromLocation(HttpClient client, - Build build, + private async Task DownloadAssetFromLocation( + HttpClient client, Asset asset, AssetLocation location, string releaseOutputDirectory, @@ -1448,7 +1459,7 @@ private async Task DownloadFileImplAsync(HttpClient client, using (var response = await manager.ExecuteAsync()) { - using (var inStream = await response.Content.ReadAsStreamAsync()) + using (var inStream = await response.Content.ReadAsStreamAsync(cancellationToken)) { downloadOutput.AppendLine($" {sourceUri} =>"); foreach (var targetFile in targetFiles) diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetAssetOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetAssetOperation.cs index 06a28da1fe..03cb027138 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetAssetOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetAssetOperation.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetBuildOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetBuildOperation.cs index 77e2c4e826..af5f3fd91d 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetBuildOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetBuildOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDefaultChannelsOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDefaultChannelsOperation.cs index 40ec1a80a3..266d2762a1 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDefaultChannelsOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDefaultChannelsOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependenciesOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependenciesOperation.cs index 1d708ae2aa..715da138fe 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependenciesOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependenciesOperation.cs @@ -5,8 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Darc.Operations; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyFlowGraphOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyFlowGraphOperation.cs index dcaa0665b1..056806f15a 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyFlowGraphOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyFlowGraphOperation.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyGraphOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyGraphOperation.cs index 9a7d893d21..0add4dd641 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyGraphOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetDependencyGraphOperation.cs @@ -7,9 +7,12 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetHealthOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetHealthOperation.cs index 730efd70e2..8fd606162e 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetHealthOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetHealthOperation.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.HealthMetrics; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetLatestBuildOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetLatestBuildOperation.cs index ba6ab5a9c3..6fe4a821b4 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetLatestBuildOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetLatestBuildOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetRepositoryMergePoliciesOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetRepositoryMergePoliciesOperation.cs index 1ebeaaa553..5b638a0cae 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetRepositoryMergePoliciesOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetRepositoryMergePoliciesOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/GetSubscriptionsOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/GetSubscriptionsOperation.cs index 3bfa26f9ea..f5195eef18 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/GetSubscriptionsOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/GetSubscriptionsOperation.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/SetRepositoryMergePoliciesOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/SetRepositoryMergePoliciesOperation.cs index 618fc801a6..9c314d6f5e 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/SetRepositoryMergePoliciesOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/SetRepositoryMergePoliciesOperation.cs @@ -138,7 +138,6 @@ public override async Task ExecuteAsync() } IRemote verifyRemote = RemoteFactory.GetRemote(_options, repository, _logger); - IEnumerable targetRepository = await _barClient.GetRepositoriesAsync(repository, branch: null); if (!await UxHelpers.VerifyAndConfirmBranchExistsAsync(verifyRemote, repository, branch, !_options.Quiet)) { diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/SubscriptionsStatusOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/SubscriptionsStatusOperation.cs index d2658d6366..4148fb9c5d 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/SubscriptionsStatusOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/SubscriptionsStatusOperation.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/TriggerSubscriptionsOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/TriggerSubscriptionsOperation.cs index 3f8c68ce11..659892bcaf 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/TriggerSubscriptionsOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/TriggerSubscriptionsOperation.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateBuildOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateBuildOperation.cs index bbfe65f810..fdddef0b39 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateBuildOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateBuildOperation.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDefaultChannelBaseOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDefaultChannelBaseOperation.cs index b80f107c3e..c59220df52 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDefaultChannelBaseOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDefaultChannelBaseOperation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Maestro.Client.Models; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs index 3bf1ca5811..0ebf3726dc 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/UpdateDependenciesOperation.cs @@ -11,6 +11,7 @@ using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/BackflowOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/BackflowOperation.cs index 4316460299..287f62b6f9 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/BackflowOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/BackflowOperation.cs @@ -36,8 +36,9 @@ protected override async Task FlowAsync( return await vmrBackFlower.FlowBackAsync( mappingName, targetRepo, - null, + shaToFlow: null, _options.Build, + excludedAssets: null, await GetBaseBranch(targetRepo), await GetTargetBranch(_vmrInfo.VmrPath), _options.DiscardPatches, diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ForwardFlowOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ForwardFlowOperation.cs index 8fdb710b9c..71eac3fd43 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ForwardFlowOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ForwardFlowOperation.cs @@ -35,8 +35,9 @@ protected override async Task FlowAsync( return await vmrForwardFlower.FlowForwardAsync( mappingName, sourceRepo, - null, + shaToFlow: null, _options.Build, + excludedAssets: null, await GetBaseBranch(new NativePath(_options.VmrPath)), await GetTargetBranch(sourceRepo), _options.DiscardPatches, diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/PushOperation.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/PushOperation.cs index 4747ce75ef..3164a1f0db 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/PushOperation.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/PushOperation.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ScanOperationBase.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ScanOperationBase.cs index c74255135c..5bc921cd93 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ScanOperationBase.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/ScanOperationBase.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/VmrOperationBase.cs b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/VmrOperationBase.cs index 6d324df48d..03200970a6 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/VmrOperationBase.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Operations/VirtualMonoRepo/VmrOperationBase.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Options.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/Darc/Options/AddBuildToChannelCommandLineOptions.cs b/src/Microsoft.DotNet.Darc/Darc/Options/AddBuildToChannelCommandLineOptions.cs index 0b932133e1..a213fa0178 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Options/AddBuildToChannelCommandLineOptions.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Options/AddBuildToChannelCommandLineOptions.cs @@ -58,6 +58,9 @@ internal class AddBuildToChannelCommandLineOptions : CommandLineOptions(); services.TryAddSingleton(); services.TryAddTransient(sp => new ProcessManager(sp.GetRequiredService>(), GitLocation)); - services.TryAddSingleton(sp => RemoteFactory.GetBarClient(this, sp.GetRequiredService>())); + services.TryAddSingleton(sp => RemoteFactory.GetBarClient(this)); services.TryAddSingleton(sp => sp.GetRequiredService()); services.TryAddTransient(sp => sp.GetRequiredService>()); services.TryAddTransient(); diff --git a/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/InitializeCommandLineOptions.cs b/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/InitializeCommandLineOptions.cs index a45b47ad45..6127dd2b38 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/InitializeCommandLineOptions.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/InitializeCommandLineOptions.cs @@ -3,7 +3,7 @@ using CommandLine; using Microsoft.DotNet.Darc.Operations.VirtualMonoRepo; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; namespace Microsoft.DotNet.Darc.Options.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/UpdateCommandLineOptions.cs b/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/UpdateCommandLineOptions.cs index 18d5ed6b12..408f8040b1 100644 --- a/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/UpdateCommandLineOptions.cs +++ b/src/Microsoft.DotNet.Darc/Darc/Options/VirtualMonoRepo/UpdateCommandLineOptions.cs @@ -3,7 +3,7 @@ using CommandLine; using Microsoft.DotNet.Darc.Operations.VirtualMonoRepo; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; namespace Microsoft.DotNet.Darc.Options.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/AssetLocationResolver.cs b/src/Microsoft.DotNet.Darc/DarcLib/AssetLocationResolver.cs index 96a3894e34..aea2f6725d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/AssetLocationResolver.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/AssetLocationResolver.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/AzureDevOpsClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/AzureDevOpsClient.cs index cbf1e77e60..ec4724e993 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/AzureDevOpsClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/AzureDevOpsClient.cs @@ -13,6 +13,7 @@ using Maestro.Common.AzureDevOpsTokens; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.DotNet.Services.Utility; using Microsoft.Extensions.Logging; @@ -428,11 +429,12 @@ await client.UpdatePullRequestAsync( /// All the commits related to the pull request public async Task> GetPullRequestCommitsAsync(string pullRequestUrl) { - (string accountName, _, string repoName, int id) = ParsePullRequestUri(pullRequestUrl); + (string accountName, string project, string repoName, int id) = ParsePullRequestUri(pullRequestUrl); using VssConnection connection = CreateVssConnection(accountName); using GitHttpClient client = await connection.GetClientAsync(); - var pullRequest = await client.GetPullRequestAsync(repoName, id, includeCommits: true); + GitPullRequest pullRequest = await client.GetPullRequestAsync(project, repoName, id, includeCommits: true); + IList commits = new List(pullRequest.Commits.Length); foreach (var commit in pullRequest.Commits) { @@ -452,26 +454,36 @@ public async Task MergeDependencyPullRequestAsync(string pullRequestUrl, MergePu using VssConnection connection = CreateVssConnection(accountName); using GitHttpClient client = await connection.GetClientAsync(); - var pullRequest = await client.GetPullRequestAsync(repoName, id, includeCommits: true); + var pullRequest = await client.GetPullRequestAsync(projectName, repoName, id, includeCommits: true); - await client.UpdatePullRequestAsync( - new GitPullRequest - { - Status = PullRequestStatus.Completed, - CompletionOptions = new GitPullRequestCompletionOptions + try + { + await client.UpdatePullRequestAsync( + new GitPullRequest { - MergeCommitMessage = mergeCommitMessage, - BypassPolicy = true, - BypassReason = "All required checks were successful", - SquashMerge = parameters.SquashMerge, - DeleteSourceBranch = parameters.DeleteSourceBranch - }, - LastMergeSourceCommit = new GitCommitRef + Status = PullRequestStatus.Completed, + CompletionOptions = new GitPullRequestCompletionOptions + { + MergeCommitMessage = mergeCommitMessage, + BypassPolicy = true, + BypassReason = "All required checks were successful", + SquashMerge = parameters.SquashMerge, + DeleteSourceBranch = parameters.DeleteSourceBranch + }, + LastMergeSourceCommit = new GitCommitRef { CommitId = pullRequest.LastMergeSourceCommit.CommitId, Comment = mergeCommitMessage } - }, - projectName, - repoName, - id); + }, + projectName, + repoName, + id); + } + catch (Exception ex) when ( + ex.Message.StartsWith("The pull request needs a minimum number of approvals") || + ex.Message == "Proof of presence is required" || + ex.Message == "Failure while attempting to queue Build.") + { + throw new PullRequestNotMergeableException(ex.Message); + } } /// @@ -531,10 +543,7 @@ private async Task CreateOrUpdatePullRequestCommentAsync(string pullRequestUrl, // No threads found, create a new one with the comment var newCommentThread = new GitPullRequestCommentThread() { - Comments = new List() - { - prComment - } + Comments = [ prComment ] }; await client.CreateThreadAsync(newCommentThread, repoName, id); } @@ -749,7 +758,7 @@ public async Task> GetPullRequestChecksAsync(string pullRequestUrl) var values = JArray.Parse(content["value"].ToString()); - IList statuses = new List(); + IList statuses = []; foreach (JToken status in values) { bool isEnabled = status["configuration"]["isEnabled"].Value(); @@ -793,7 +802,7 @@ public async Task> GetLatestPullRequestReviewsAsync(string pullReq var values = JArray.Parse(content["value"].ToString()); - IList reviews = new List(); + IList reviews = []; foreach (JToken review in values) { // Azure DevOps uses an integral "vote" value to identify review state diff --git a/src/Microsoft.DotNet.Darc/DarcLib/BarApiClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/BarApiClient.cs index 4a3d29fc99..035cfdd203 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/BarApiClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/BarApiClient.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Azure; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; using AsyncEnumerable = Microsoft.DotNet.Maestro.Client.AsyncEnumerable; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/CoherencyUpdateResolver.cs b/src/Microsoft.DotNet.Darc/DarcLib/CoherencyUpdateResolver.cs index f5ae65a6de..809f9e4062 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/CoherencyUpdateResolver.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/CoherencyUpdateResolver.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/DarcCoherencyException.cs b/src/Microsoft.DotNet.Darc/DarcLib/DarcCoherencyException.cs index 4befe70648..e836e6cbca 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/DarcCoherencyException.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/DarcCoherencyException.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/GitHubClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/GitHubClient.cs index d8ada19fea..92f7fda594 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/GitHubClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/GitHubClient.cs @@ -15,6 +15,8 @@ using Maestro.Common; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.GitHub; using Microsoft.DotNet.Services.Utility; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; @@ -424,7 +426,10 @@ public async Task> GetPullRequestCommitsAsync(string pullRequestUr public async Task MergeDependencyPullRequestAsync(string pullRequestUrl, MergePullRequestParameters parameters, string mergeCommitMessage) { (string owner, string repo, int id) = ParsePullRequestUri(pullRequestUrl); - Octokit.PullRequest pr = await GetClient(owner, repo).PullRequest.Get(owner, repo, id); + + IGitHubClient gitHubClient = GetClient(owner, repo); + + Octokit.PullRequest pr = await gitHubClient.PullRequest.Get(owner, repo, id); var mergePullRequest = new MergePullRequest { @@ -433,11 +438,25 @@ public async Task MergeDependencyPullRequestAsync(string pullRequestUrl, MergePu MergeMethod = parameters.SquashMerge ? PullRequestMergeMethod.Squash : PullRequestMergeMethod.Merge }; - await GetClient(owner, repo).PullRequest.Merge(owner, repo, id, mergePullRequest); + try + { + await gitHubClient.PullRequest.Merge(owner, repo, id, mergePullRequest); + } + catch (Octokit.PullRequestNotMergeableException notMergeableException) + { + throw new PullRequestNotMergeableException(notMergeableException.Message); + } if (parameters.DeleteSourceBranch) { - await GetClient(owner, repo).Git.Reference.Delete(owner, repo, $"heads/{pr.Head.Ref}"); + try + { + await gitHubClient.Git.Reference.Delete(owner, repo, $"heads/{pr.Head.Ref}"); + } + catch (Exception ex) + { + _logger.LogInformation("Couldn't delete branch {sourceBranch} - {message}", pr.Head.Ref, ex.Message); + } } } @@ -928,9 +947,11 @@ public async Task> GetPullRequestChecksAsync(string pullRequestUrl) var commits = await GetClient(owner, repo).Repository.PullRequest.Commits(owner, repo, id); var lastCommitSha = commits[commits.Count - 1].Sha; - return (await GetChecksFromStatusApiAsync(owner, repo, lastCommitSha)) - .Concat(await GetChecksFromChecksApiAsync(owner, repo, lastCommitSha)) - .ToList(); + return + [ + .. await GetChecksFromStatusApiAsync(owner, repo, lastCommitSha), + .. await GetChecksFromChecksApiAsync(owner, repo, lastCommitSha), + ]; } /// diff --git a/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/ProductDependencyCyclesHealthMetric.cs b/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/ProductDependencyCyclesHealthMetric.cs index acafbe615d..5b5130ea56 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/ProductDependencyCyclesHealthMetric.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/ProductDependencyCyclesHealthMetric.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.DarcLib.HealthMetrics; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/SubscriptionHealthMetric.cs b/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/SubscriptionHealthMetric.cs index c5b06add2d..8d8ccab872 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/SubscriptionHealthMetric.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/HealthMetrics/SubscriptionHealthMetric.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 Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; using System; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyExtensions.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyExtensions.cs index 07c25f1a64..c7bf3ccaa0 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyExtensions.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.DotNet.DarcLib.Models.Darc; #nullable enable namespace Microsoft.DotNet.DarcLib.Helpers; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyFileManager.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyFileManager.cs index ad2d0a2b5f..8707493e84 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyFileManager.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/DependencyFileManager.cs @@ -9,13 +9,13 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml; -using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using NuGet.Versioning; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; public class DependencyFileManager : IDependencyFileManager { @@ -100,7 +100,7 @@ public async Task ReadGlobalJsonAsync(string repoUri, string branch) _logger.LogInformation( $"Reading '{VersionFiles.GlobalJson}' in repo '{repoUri}' and branch '{branch}'..."); - string fileContent = await GetGitClient(repoUri).GetFileContentsAsync(VersionFiles.GlobalJson, repoUri, branch); + var fileContent = await GetGitClient(repoUri).GetFileContentsAsync(VersionFiles.GlobalJson, repoUri, branch); return JObject.Parse(fileContent); } @@ -112,7 +112,7 @@ public async Task ReadDotNetToolsConfigJsonAsync(string repoUri, string try { - string fileContent = await GetGitClient(repoUri).GetFileContentsAsync(VersionFiles.DotnetToolsConfigJson, repoUri, branch); + var fileContent = await GetGitClient(repoUri).GetFileContentsAsync(VersionFiles.DotnetToolsConfigJson, repoUri, branch); return JObject.Parse(fileContent); } catch (DependencyFileNotFoundException) @@ -181,7 +181,7 @@ public async Task AddDependencyAsync( // Should the dependency go to Versions.props or global.json? if (_knownAssetNames.ContainsKey(dependency.Name)) { - if (!_sdkMapping.TryGetValue(dependency.Name, out string parent)) + if (!_sdkMapping.TryGetValue(dependency.Name, out var parent)) { throw new Exception($"Dependency '{dependency.Name}' has no parent mapping defined."); } @@ -318,7 +318,7 @@ public async Task UpdateDependencyFiles( { if (!itemsToUpdateLocations.ContainsKey(dependency.Name) && dependency.Locations != null) { - itemsToUpdateLocations.Add(dependency.Name, new HashSet(dependency.Locations)); + itemsToUpdateLocations.Add(dependency.Name, [.. dependency.Locations]); } } } @@ -425,7 +425,7 @@ public XmlDocument UpdatePackageSources(XmlDocument nugetConfig, Dictionary(); foreach (var repoName in maestroManagedFeedsByRepo.Keys) @@ -563,9 +563,9 @@ private void CreateOrUpdateDisabledSourcesBlock(XmlDocument nugetConfig, Diction } XmlComment endCommentBlock = GetFirstMatchingComment(disabledSourcesNode, MaestroEndComment); - bool introducedAStartCommentBlock = false; + var introducedAStartCommentBlock = false; - foreach (string repoName in maestroManagedFeedsByRepo.Keys.OrderBy(t => t)) + foreach (var repoName in maestroManagedFeedsByRepo.Keys.OrderBy(t => t)) { var managedSources = GetManagedPackageSources(maestroManagedFeedsByRepo[repoName]).OrderBy(t => t.feed).ToList(); @@ -586,7 +586,7 @@ private void CreateOrUpdateDisabledSourcesBlock(XmlDocument nugetConfig, Diction { insertAfterNode = disabledSourcesNode.InsertAfter(nugetConfig.CreateComment(MaestroBeginComment), disabledSourcesNode.FirstChild); } - startCommentBlock = (XmlComment) insertAfterNode; + startCommentBlock = (XmlComment)insertAfterNode; introducedAStartCommentBlock = true; } @@ -626,7 +626,7 @@ private void CreateOrUpdateDisabledSourcesBlock(XmlDocument nugetConfig, Diction // For a config that doesn't already have the end comment, create it. if (endCommentBlock == null && introducedAStartCommentBlock) { - endCommentBlock = (XmlComment) disabledSourcesNode.InsertAfter(nugetConfig.CreateComment(MaestroEndComment), insertAfterNode); + endCommentBlock = (XmlComment)disabledSourcesNode.InsertAfter(nugetConfig.CreateComment(MaestroEndComment), insertAfterNode); } } @@ -648,11 +648,11 @@ private void InsertManagedPackagesBlock(XmlDocument nugetConfig, XmlNode package var repoList = maestroManagedFeedsByRepo.Keys.OrderBy(t => t).ToList(); XmlComment blockBeginComment = GetFirstMatchingComment(packageSourcesNode, MaestroBeginComment); - blockBeginComment ??= (XmlComment) packageSourcesNode.InsertAfter(nugetConfig.CreateComment(MaestroBeginComment), clearNode); + blockBeginComment ??= (XmlComment)packageSourcesNode.InsertAfter(nugetConfig.CreateComment(MaestroBeginComment), clearNode); currentNode = blockBeginComment; - foreach (string repository in repoList) + foreach (var repository in repoList) { var managedSources = GetManagedPackageSources(maestroManagedFeedsByRepo[repository]).OrderByDescending(t => t.feed).ToList(); @@ -667,7 +667,7 @@ private void InsertManagedPackagesBlock(XmlDocument nugetConfig, XmlNode package currentNode = startBlockComment; } - foreach ((string key, string feed) in managedSources) + foreach ((var key, var feed) in managedSources) { var newElement = nugetConfig.CreateElement(VersionDetailsParser.AddElement); @@ -704,7 +704,7 @@ private static XmlComment GetFirstMatchingComment(XmlNode nodeToCheck, string co while (currentNode != null) { if (currentNode.NodeType == XmlNodeType.Comment && - (currentNode.Value.Equals(commentText, StringComparison.OrdinalIgnoreCase))) + currentNode.Value.Equals(commentText, StringComparison.OrdinalIgnoreCase)) { return (XmlComment)currentNode; } @@ -776,10 +776,10 @@ await GetGitClient(repo).CommitFilesAsync([file], repo, branch, $"Add {dependenc private async Task AddDependencyToVersionsPropsAsync(string repo, string branch, DependencyDetail dependency) { XmlDocument versionProps = await ReadVersionPropsAsync(repo, null); - string documentNamespaceUri = versionProps.DocumentElement.NamespaceURI; + var documentNamespaceUri = versionProps.DocumentElement.NamespaceURI; - string packageVersionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(dependency.Name); - string packageVersionAlternateElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName( + var packageVersionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(dependency.Name); + var packageVersionAlternateElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName( dependency.Name); // Attempt to find the element name or alternate element name under @@ -797,7 +797,7 @@ private async Task AddDependencyToVersionsPropsAsync(string repo, string branch, // xmlns set. XmlNodeList propertyGroupNodes = versionProps.DocumentElement.SelectNodes($"//*[local-name()='PropertyGroup']"); - bool addedPackageVersionElement = false; + var addedPackageVersionElement = false; // There can be more than one property group. Find the appropriate one containing an existing element of // the same type, and add it to the parent. foreach (XmlNode propertyGroupNode in propertyGroupNodes) @@ -913,7 +913,7 @@ private async Task ReadXmlFileAsync(string filePath, string repoUri { _logger.LogInformation($"Reading '{filePath}' in repo '{repoUri}' and branch '{branch}'..."); - string fileContent = await GetGitClient(repoUri).GetFileContentsAsync(filePath, repoUri, branch); + var fileContent = await GetGitClient(repoUri).GetFileContentsAsync(filePath, repoUri, branch); try { @@ -942,14 +942,14 @@ private async Task ReadXmlFileAsync(string filePath, string repoUri /// private void UpdateVersionFiles(XmlDocument versionProps, JToken globalJsonToken, JToken dotNetToolJsonToken, DependencyDetail itemToUpdate) { - string versionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(itemToUpdate.Name); - string alternateVersionElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName(itemToUpdate.Name); + var versionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(itemToUpdate.Name); + var alternateVersionElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName(itemToUpdate.Name); // Select nodes case insensitively, then update the name. XmlNode packageVersionNode = versionProps.DocumentElement.SelectSingleNode( $"//*[translate(local-name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')=" + $"'{versionElementName.ToLower()}']"); - string foundElementName = versionElementName; + var foundElementName = versionElementName; // Find alternate names if (packageVersionNode == null) @@ -991,7 +991,7 @@ private void UpdateVersionFiles(XmlDocument versionProps, JToken globalJsonToken private static void UpdateVersionGlobalJson(DependencyDetail itemToUpdate, JToken token) { - string versionElementName = VersionFiles.CalculateGlobalJsonElementName(itemToUpdate.Name); + var versionElementName = VersionFiles.CalculateGlobalJsonElementName(itemToUpdate.Name); foreach (JProperty property in token.Children()) { @@ -1007,7 +1007,7 @@ private static void UpdateVersionGlobalJson(DependencyDetail itemToUpdate, JToke private void UpdateDotNetToolsManifest(DependencyDetail itemToUpdate, JToken token) { - string versionElementName = itemToUpdate.Name; + var versionElementName = itemToUpdate.Name; var toolsNode = (JObject)token["tools"]; @@ -1117,15 +1117,15 @@ await utilizedGlobalJsonDependencies public static void NormalizeAttributes(string directoryPath) { - string[] filePaths = Directory.GetFiles(directoryPath); - string[] subdirectoryPaths = Directory.GetDirectories(directoryPath); + var filePaths = Directory.GetFiles(directoryPath); + var subdirectoryPaths = Directory.GetDirectories(directoryPath); - foreach (string filePath in filePaths) + foreach (var filePath in filePaths) { File.SetAttributes(filePath, FileAttributes.Normal); } - foreach (string subdirectoryPath in subdirectoryPaths) + foreach (var subdirectoryPath in subdirectoryPaths) { NormalizeAttributes(subdirectoryPath); } @@ -1140,7 +1140,7 @@ public static void NormalizeAttributes(string directoryPath) /// True if there are no duplicated properties. public Task VerifyNoDuplicatedProperties(XmlDocument versionProps) { - bool hasNoDuplicatedProperties = true; + var hasNoDuplicatedProperties = true; HashSet existingProperties = []; XmlNodeList propertyGroups = versionProps.GetElementsByTagName("PropertyGroup"); @@ -1181,7 +1181,7 @@ public Task VerifyNoDuplicatedProperties(XmlDocument versionProps) /// True if there are no duplicated dependencies. private Task VerifyNoDuplicatedDependencies(IEnumerable dependencies) { - bool result = true; + var result = true; HashSet dependenciesBitVector = []; foreach (var dependency in dependencies) { @@ -1205,11 +1205,11 @@ private Task VerifyNoDuplicatedDependencies(IEnumerable private Task VerifyMatchingVersionProps(IEnumerable dependencies, XmlDocument versionProps, out Task> utilizedDependencies) { HashSet utilizedSet = []; - bool result = true; + var result = true; foreach (var dependency in dependencies) { - string versionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(dependency.Name); - string alternateVersionElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName(dependency.Name); + var versionElementName = VersionFiles.GetVersionPropsPackageVersionElementName(dependency.Name); + var alternateVersionElementName = VersionFiles.GetVersionPropsAlternatePackageVersionElementName(dependency.Name); XmlNode versionNode = versionProps.DocumentElement.SelectSingleNode($"//*[local-name()='{versionElementName}']"); if (versionNode == null) { @@ -1255,10 +1255,10 @@ private Task VerifyMatchingGlobalJson( out Task> utilizedDependencies) { HashSet utilizedSet = []; - bool result = true; + var result = true; foreach (var dependency in dependencies) { - string versionedName = VersionFiles.CalculateGlobalJsonElementName(dependency.Name); + var versionedName = VersionFiles.CalculateGlobalJsonElementName(dependency.Name); JToken dependencyNode = FindDependency(rootToken, versionedName); if (dependencyNode != null) { @@ -1280,7 +1280,7 @@ private Task VerifyMatchingGlobalJson( result = false; } // Validate version - JToken value = (JToken)property.Value; + var value = property.Value; if (value.Value() != dependency.Version) { _logger.LogError($"The dependency '{dependency.Name}' has a version mismatch between " + @@ -1306,13 +1306,13 @@ private Task VerifyMatchingDotNetToolsJson( IEnumerable dependencies, JObject rootToken) { - bool result = true; + var result = true; // If there isn't a .config/dotnet-tools.json, skip checking if (rootToken != null) { foreach (var dependency in dependencies) { - string versionedName = VersionFiles.CalculateDotnetToolsJsonElementName(dependency.Name); + var versionedName = VersionFiles.CalculateDotnetToolsJsonElementName(dependency.Name); JToken dependencyNode = FindDependency(rootToken, versionedName); if (dependencyNode != null) { @@ -1383,7 +1383,7 @@ private Task VerifyUtilizedDependencies( IEnumerable dependencies, IEnumerable> utilizedDependencySets) { - bool result = true; + var result = true; foreach (var dependency in dependencies) { if (!utilizedDependencySets.Where(set => set.Contains(dependency.Name)).Any()) @@ -1405,7 +1405,7 @@ private Task VerifyUtilizedDependencies( public Dictionary> FlattenLocationsAndSplitIntoGroups(Dictionary> assetLocationMap) { HashSet allManagedFeeds = []; - foreach (string asset in assetLocationMap.Keys) + foreach (var asset in assetLocationMap.Keys) { if (IsOnlyPresentInMaestroManagedFeed(assetLocationMap[asset])) { @@ -1413,11 +1413,11 @@ public Dictionary> FlattenLocationsAndSplitIntoGroups(Di } } - string unableToResolveName = "unknown"; + var unableToResolveName = "unknown"; Dictionary> result = []; - foreach (string feedUri in allManagedFeeds) + foreach (var feedUri in allManagedFeeds) { - string repoNameFromFeed = string.Empty; + var repoNameFromFeed = string.Empty; try { var match = Regex.Match(feedUri, FeedConstants.MaestroManagedFeedNamePattern); @@ -1474,11 +1474,11 @@ public Dictionary> FlattenLocationsAndSplitIntoGroups(Di { var sources = new List<(string key, string feed)>(); - foreach (string feed in feeds) + foreach (var feed in feeds) { var parsedFeed = ParseMaestroManagedFeed(feed); - string key = $"darc-{parsedFeed.type}-{parsedFeed.repoName}-{parsedFeed.sha.Substring(0, 7)}"; + var key = $"darc-{parsedFeed.type}-{parsedFeed.repoName}-{parsedFeed.sha.Substring(0, 7)}"; if (!string.IsNullOrEmpty(parsedFeed.subVersion)) { key += "-" + parsedFeed.subVersion; @@ -1491,7 +1491,7 @@ public Dictionary> FlattenLocationsAndSplitIntoGroups(Di private (string org, string repoName, string type, string sha, string subVersion) ParseMaestroManagedFeed(string feed) { Match match = null; - foreach (string pattern in FeedConstants.MaestroManagedFeedPatterns) + foreach (var pattern in FeedConstants.MaestroManagedFeedPatterns) { match = Regex.Match(feed, pattern); if (match.Success) @@ -1506,11 +1506,11 @@ public Dictionary> FlattenLocationsAndSplitIntoGroups(Di if (match.Success) { - string org = match.Groups["organization"].Value; - string repo = match.Groups["repository"].Value; - string type = match.Groups["type"].Value; - string sha = match.Groups["sha"].Value; - string subVersion = match.Groups["subversion"].Value; + var org = match.Groups["organization"].Value; + var repo = match.Groups["repository"].Value; + var type = match.Groups["type"].Value; + var sha = match.Groups["sha"].Value; + var subVersion = match.Groups["subversion"].Value; return (org, repo, type, sha, subVersion); } else diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFile.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFile.cs index eb5366ba46..00ce28bcdf 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFile.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFile.cs @@ -9,7 +9,7 @@ using Newtonsoft.Json.Linq; using Formatting = Newtonsoft.Json.Formatting; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; public class GitFile { @@ -25,7 +25,7 @@ public GitFile(string filePath, string content) : this(filePath, content, Conten { } - public GitFile(string filePath, JObject jsonObject, Dictionary metadata) + public GitFile(string filePath, JObject jsonObject, Dictionary metadata) : this(filePath, jsonObject.ToString(Formatting.Indented)) { Metadata = metadata; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFileContentContainer.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFileContentContainer.cs index b790417692..95a6f339b9 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFileContentContainer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/GitFileContentContainer.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; public class GitFileContentContainer { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/HttpRequestManager.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/HttpRequestManager.cs index 2bcde8f6d1..6f59b3d25d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/HttpRequestManager.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/HttpRequestManager.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; public class HttpRequestManager { @@ -49,7 +49,7 @@ public HttpRequestManager( public async Task ExecuteAsync(int retryCount = 3) { - int retriesRemaining = retryCount; + var retriesRemaining = retryCount; // Add a bit of randomness to the retry delay. var rng = new Random(); @@ -66,7 +66,7 @@ public async Task ExecuteAsync(int retryCount = 3) try { - using (HttpRequestMessage message = new HttpRequestMessage(_method, _requestUri)) + using (var message = new HttpRequestMessage(_method, _requestUri)) { if (!string.IsNullOrEmpty(_body)) { @@ -78,10 +78,7 @@ public async Task ExecuteAsync(int retryCount = 3) message.Headers.Authorization = _authHeader; } - if (_configureRequestMessage != null) - { - _configureRequestMessage(message); - } + _configureRequestMessage?.Invoke(message); response = await _client.SendAsync(message, _httpCompletionOption); @@ -117,8 +114,8 @@ public async Task ExecuteAsync(int retryCount = 3) // For CLI users this will look normal, but translating to a DarcAuthenticationFailureException means it opts in to automated failure logging. if (ex is HttpRequestException && ex.Message.Contains(((int)HttpStatusCode.Unauthorized).ToString())) { - int queryParamIndex = _requestUri.IndexOf('?'); - string sanitizedRequestUri = queryParamIndex < 0 ? _requestUri : $"{_requestUri.Substring(0, queryParamIndex)}?***"; + var queryParamIndex = _requestUri.IndexOf('?'); + var sanitizedRequestUri = queryParamIndex < 0 ? _requestUri : $"{_requestUri.Substring(0, queryParamIndex)}?***"; _logger.LogError(ex, "Non-continuable HTTP 401 error encountered while making request against URI '{sanitizedRequestUri}'", sanitizedRequestUri); throw new DarcAuthenticationFailureException($"Failure to authenticate: {ex.Message}"); } @@ -147,7 +144,7 @@ public async Task ExecuteAsync(int retryCount = 3) } } --retriesRemaining; - int delay = (retryCount - retriesRemaining) * rng.Next(1, 7); + var delay = (retryCount - retriesRemaining) * rng.Next(1, 7); await Task.Delay(delay * 1000); } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/IDependencyFileManager.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/IDependencyFileManager.cs index 6aa481161d..c12de1b6f5 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/IDependencyFileManager.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/IDependencyFileManager.cs @@ -6,11 +6,12 @@ using System.Threading.Tasks; using System.Xml; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Newtonsoft.Json.Linq; using NuGet.Versioning; #nullable enable -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; /// /// Represents various actions around files in git that can be performed on a local repository or even remotely. diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/PackagesHelper.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/PackagesHelper.cs index 6189567d55..b12665882d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/PackagesHelper.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/PackagesHelper.cs @@ -24,7 +24,7 @@ public static ManifestMetadata GetManifestMetadata(string packagePath) { using (Stream stream = new MemoryStream(File.ReadAllBytes(nuspecPath))) { - Manifest manifest = Manifest.ReadFrom(stream, false); + var manifest = Manifest.ReadFrom(stream, false); manifestMetadata = manifest.Metadata; } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionDetailsParser.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionDetailsParser.cs index 40bc219d09..a3bbfbbdc4 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionDetailsParser.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionDetailsParser.cs @@ -7,9 +7,10 @@ using System.Linq; using System.Xml; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; #nullable enable -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; public interface IVersionDetailsParser { @@ -106,7 +107,7 @@ private static List ParseDependencyDetails(XmlNodeList depende }; // If the 'Pinned' attribute does not exist or if it is set to false we just not update it - bool isPinned = ParseBooleanAttribute(dependency.Attributes, PinnedAttributeName); + var isPinned = ParseBooleanAttribute(dependency.Attributes, PinnedAttributeName); XmlNode? sourceBuildNode = dependency.SelectSingleNode(SourceBuildElementName) ?? dependency.SelectSingleNode(SourceBuildOldElementName); // Workaround for https://github.com/dotnet/source-build/issues/2481 @@ -114,7 +115,7 @@ private static List ParseDependencyDetails(XmlNodeList depende SourceBuildInfo? sourceBuildInfo = null; if (sourceBuildNode is XmlElement sourceBuildElement) { - string repoName = sourceBuildElement.Attributes[RepoNameAttributeName]?.Value + var repoName = sourceBuildElement.Attributes[RepoNameAttributeName]?.Value ?? throw new DarcException($"{RepoNameAttributeName} of {SourceBuildElementName} " + $"null or empty in '{dependency.Attributes[NameAttributeName]?.Value}'"); @@ -159,7 +160,7 @@ private static List ParseDependencyDetails(XmlNodeList depende return new SourceDependency(uri, sha); } - + private static bool ParseBooleanAttribute(XmlAttributeCollection attributes, string attributeName) { var result = false; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionFiles.cs b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionFiles.cs index 54a577b198..723a833835 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionFiles.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Helpers/VersionFiles.cs @@ -4,7 +4,7 @@ using NuGet.Versioning; using System; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Helpers; /// /// Generic helpers for dealing with version files. @@ -90,7 +90,7 @@ public static (string BuildId, string ReleaseLabel) DeriveBuildInfo(string repoN { return (releaseParts[2], $"{releaseParts[0]}.{releaseParts[1]}"); } - + return (VersionToDate(datePart, buildPart), releaseParts[0]); } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IAzureDevOpsClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/IAzureDevOpsClient.cs index 221f924480..d4284f8ff4 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IAzureDevOpsClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IAzureDevOpsClient.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Newtonsoft.Json.Linq; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IBasicBarClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/IBasicBarClient.cs index 079e9a5801..5efb644632 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IBasicBarClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IBasicBarClient.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 Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using System; using System.Collections.Generic; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/ICoherencyUpdateResolver.cs b/src/Microsoft.DotNet.Darc/DarcLib/ICoherencyUpdateResolver.cs index 5d6dd8423c..722d86c0ba 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/ICoherencyUpdateResolver.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/ICoherencyUpdateResolver.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IGitRepo.cs b/src/Microsoft.DotNet.Darc/DarcLib/IGitRepo.cs index 760c608128..ee8da8d868 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IGitRepo.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IGitRepo.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.DotNet.DarcLib.Helpers; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IRemote.cs b/src/Microsoft.DotNet.Darc/DarcLib/IRemote.cs index 932088ca68..7ae30fe800 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IRemote.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IRemote.cs @@ -4,6 +4,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Maestro.MergePolicyEvaluation; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Microsoft.DotNet.DarcLib; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IRemoteFactory.cs b/src/Microsoft.DotNet.Darc/DarcLib/IRemoteFactory.cs index 9852e51d3b..91760abdba 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IRemoteFactory.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IRemoteFactory.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 Microsoft.DotNet.DarcLib.Helpers; using Microsoft.Extensions.Logging; using System.Threading.Tasks; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/IRemoteGitRepo.cs b/src/Microsoft.DotNet.Darc/DarcLib/IRemoteGitRepo.cs index 62df62bcf2..d61fb75113 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/IRemoteGitRepo.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/IRemoteGitRepo.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Maestro.MergePolicyEvaluation; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Actions/Local.cs b/src/Microsoft.DotNet.Darc/DarcLib/Local.cs similarity index 97% rename from src/Microsoft.DotNet.Darc/DarcLib/Actions/Local.cs rename to src/Microsoft.DotNet.Darc/DarcLib/Local.cs index 5f04abefa5..950151b201 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Actions/Local.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Local.cs @@ -10,6 +10,7 @@ using Maestro.Common; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using NuGet.Versioning; @@ -107,7 +108,7 @@ public async Task UpdateDependenciesAsync(List dependencies, I } } } - catch (Exception exc) when + catch (Exception exc) when (exc.Message == "Not Found") { _logger.LogWarning("Could not update 'eng/common'. Most likely this is a scenario " + @@ -166,14 +167,14 @@ public void Checkout(string commit, bool force = false) /// The remote URL to add public async Task AddRemoteIfMissingAsync(string repoDir, string repoUrl) { - string remoteName = await _gitClient.AddRemoteIfMissingAsync(repoDir, repoUrl); + var remoteName = await _gitClient.AddRemoteIfMissingAsync(repoDir, repoUrl); await _gitClient.UpdateRemoteAsync(repoDir, remoteName); return remoteName; } private List GetFilesAtRelativeRepoPathAsync(string path) { - string sourceFolder = Path.Combine(_repoRootDir.Value, path); + var sourceFolder = Path.Combine(_repoRootDir.Value, path); var files = Directory.GetFiles(sourceFolder, "*.*", SearchOption.AllDirectories); return files .Select(file => new GitFile( diff --git a/src/Microsoft.DotNet.Darc/DarcLib/LocalGitClient.cs b/src/Microsoft.DotNet.Darc/DarcLib/LocalGitClient.cs index 38780f034f..25530465d8 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/LocalGitClient.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/LocalGitClient.cs @@ -253,9 +253,10 @@ public async Task AddRemoteIfMissingAsync(string repoPath, string repoUr string? remoteName = null; - foreach (var line in result.StandardOutput.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) + foreach (var line in result.StandardOutput.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { - var parts = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + // This doesn't work if the repo path has a whitespace + var parts = line.Split([' ', '\t'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var name = parts[0]; var url = parts[1]; @@ -319,7 +320,7 @@ public async Task> GetGitSubmodulesAsync(string repoPath, GitSubmoduleInfo? currentSubmodule = null; var lines = submoduleFile - .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries) .Select(l => l.Trim()); var submoduleRegex = new Regex("^\\[submodule \"(?.+)\"\\]$"); @@ -392,7 +393,7 @@ public async Task GetStagedFiles(string repoPath) var result = await _processManager.ExecuteGit(repoPath, "diff", "--name-only", "--cached"); result.ThrowIfFailed($"Failed to get staged files in {repoPath}"); - return result.StandardOutput.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + return result.StandardOutput.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); } public async Task GetFileFromGitAsync(string repoPath, string relativeFilePath, string revision = "HEAD", string? outputPath = null) diff --git a/src/Microsoft.DotNet.Darc/DarcLib/LocalLibGit2Client.cs b/src/Microsoft.DotNet.Darc/DarcLib/LocalLibGit2Client.cs index aeb1e8271d..00f1adee8f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/LocalLibGit2Client.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/LocalLibGit2Client.cs @@ -345,11 +345,8 @@ public async Task Push( var remoteName = await AddRemoteIfMissingAsync(repoPath, remoteUrl); var remote = repo.Network.Remotes[remoteName]; - var branch = repo.Branches[branchName]; - if (branch == null) - { - throw new Exception($"No branch {branchName} found in repo. {repo.Info.Path}"); - } + var branch = repo.Branches[branchName] + ?? throw new Exception($"No branch {branchName} found in repo. {repo.Info.Path}"); var pushOptions = new PushOptions { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifact.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifact.cs index 565564e4d2..d00ec3af54 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifact.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifact.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsArtifact { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifactSourceReference.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifactSourceReference.cs index 56f03fe18f..7073eb4394 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifactSourceReference.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsArtifactSourceReference.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsArtifactSourceReference { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuild.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuild.cs index e92f9a3122..3f026c5f90 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuild.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuild.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsBuild { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildArtifact.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildArtifact.cs index 9bb8f61339..26c712525a 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildArtifact.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildArtifact.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsBuildArtifact { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildDefinition.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildDefinition.cs index 70a3ea750d..a3c0be783c 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildDefinition.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsBuildDefinition.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsBuildDefinition : AzureDevOpsIdNamePair { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChange.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChange.cs index ffde14b853..906b840e22 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChange.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChange.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsChange { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChangeType.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChangeType.cs index 8554fc19ad..bc6357faa9 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChangeType.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsChangeType.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsChangeType { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCheckState.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCheckState.cs index 5a481c9cb1..663fb9ca13 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCheckState.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCheckState.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public enum AzureDevOpsCheckState { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsComment.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsComment.cs index 99e6f2eca5..24d7fb2ea3 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsComment.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsComment.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsComment { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCommit.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCommit.cs index 682cf6a0b8..e832eb17fa 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCommit.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsCommit.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsCommit { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsFeed.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsFeed.cs index a535e9843e..3f72f15b56 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsFeed.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsFeed.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; -public class AzureDevOpsFeed: AzureDevOpsIdNamePair +public class AzureDevOpsFeed : AzureDevOpsIdNamePair { public List Packages { get; set; } @@ -13,7 +13,7 @@ public class AzureDevOpsFeed: AzureDevOpsIdNamePair public string Account { get; set; } - public AzureDevOpsFeed(string account, string id, string name, AzureDevOpsProject project = null) + public AzureDevOpsFeed(string account, string id, string name, AzureDevOpsProject project = null) { Account = account; Name = name; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsIdNamePair.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsIdNamePair.cs index 7fe6bae71a..51ef5fd52b 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsIdNamePair.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsIdNamePair.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsIdNamePair { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsItem.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsItem.cs index c0e0b51b7a..37767b3d5f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsItem.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsItem.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsItem { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPackage.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPackage.cs index f0f9d72a83..651455b684 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPackage.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPackage.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsPackage { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPrStatus.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPrStatus.cs index 776d1b2f3c..310e809a81 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPrStatus.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPrStatus.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public enum AzureDevOpsPrStatus { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsProject.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsProject.cs index 07d3ccbf20..5dc3801ced 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsProject.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsProject.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public partial class AzureDevOpsProject : AzureDevOpsIdNamePair { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPush.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPush.cs index 4b47e3ec7e..78e108a1f2 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPush.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsPush.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsPush { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRef.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRef.cs index 763683ced9..fc233f7b8f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRef.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRef.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsRef { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRefUpdate.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRefUpdate.cs index 8972659efa..b7fde43ae2 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRefUpdate.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRefUpdate.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsRefUpdate { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRelease.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRelease.cs index 373d252097..35c17a6a6a 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRelease.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsRelease.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public partial class AzureDevOpsRelease { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseDefinition.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseDefinition.cs index 65747b672d..964b909ab6 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseDefinition.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseDefinition.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public class AzureDevOpsReleaseDefinition { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseEnvironment.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseEnvironment.cs index a9dd2a0f43..765bea235c 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseEnvironment.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseEnvironment.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public partial class AzureDevOpsReleaseEnvironment { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseStatus.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseStatus.cs index 577fc8268b..fd40c25422 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseStatus.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/AzureDevOps/AzureDevOpsReleaseStatus.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.AzureDevOps; public static class AzureDevOpsReleaseStatus { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Check.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Check.cs index 5588547ef1..0874333b92 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Check.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Check.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public class Check { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/CheckState.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/CheckState.cs index 07dd95d10f..dcbd77eef6 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/CheckState.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/CheckState.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public enum CheckState { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/AssetComparer.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/AssetComparer.cs index fc74f0d231..1d87e04284 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/AssetComparer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/AssetComparer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; /// /// Compares assets based on name and version. diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/BuildComparer.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/BuildComparer.cs index 4b226ad362..817192efa7 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/BuildComparer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/BuildComparer.cs @@ -4,7 +4,7 @@ using Microsoft.DotNet.Maestro.Client.Models; using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class BuildComparer : IEqualityComparer { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/CoherencyMode.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/CoherencyMode.cs index 8aadf532f5..32a808123f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/CoherencyMode.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/CoherencyMode.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; /// /// Method of coherency. diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetail.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetail.cs index f8f8ee8f8f..9c00771e70 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetail.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetail.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyDetail { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetailComparer.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetailComparer.cs index 675672f26e..ceb4daea79 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetailComparer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyDetailComparer.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyDetailComparer : IEqualityComparer { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowEdge.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowEdge.cs index 37e8958c85..27504afd68 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowEdge.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowEdge.cs @@ -3,7 +3,7 @@ using Microsoft.DotNet.Maestro.Client.Models; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyFlowEdge { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowGraph.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowGraph.cs index f513c4f211..4b85fc0670 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowGraph.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowGraph.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Threading.Tasks; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; /// /// This graph build @@ -51,7 +51,7 @@ public void RemoveNode(DependencyFlowNode node) /// Node to calculate the input edges for. private static void RecalculateInputChannels(DependencyFlowNode node) { - node.InputChannels = new HashSet(node.IncomingEdges.Select(e => e.Subscription.Channel.Name)); + node.InputChannels = [.. node.IncomingEdges.Select(e => e.Subscription.Channel.Name)]; } public void RemoveEdge(DependencyFlowEdge edge) @@ -153,7 +153,7 @@ public void MarkBackEdges() Dictionary> dominators = []; foreach (DependencyFlowNode node in Nodes) { - dominators.Add(node, new HashSet(Nodes)); + dominators.Add(node, [.. Nodes]); } var workList = new Queue(); @@ -175,7 +175,7 @@ public void MarkBackEdges() { if (newDom == null) { - newDom = new HashSet(dominators[predNode]); + newDom = [.. dominators[predNode]]; } else { @@ -228,7 +228,7 @@ public void MarkBackEdges() /// public void CalculateLongestBuildPaths() { - List roots = Nodes.Where(n => n.OutgoingEdges.Count == 0).ToList(); + var roots = Nodes.Where(n => n.OutgoingEdges.Count == 0).ToList(); Dictionary> visitedNodes = []; var nodesToVisit = new Queue(); @@ -261,7 +261,7 @@ public void CalculateLongestBuildPaths() } else { - visitedNodes.Add(child, new HashSet(visitedNodes[node])); + visitedNodes.Add(child, [.. visitedNodes[node]]); } nodesToVisit.Enqueue(child); diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowNode.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowNode.cs index dfe346c6b1..2a348b6e04 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowNode.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyFlowNode.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyFlowNode { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraph.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraph.cs index 60ab96ea33..d1ed1562b1 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraph.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraph.cs @@ -10,7 +10,7 @@ using System.Linq; using System.Threading.Tasks; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public enum NodeDiff { @@ -292,7 +292,7 @@ private static async Task DoLatestInChannelGraphNodeDiffAsync( // a build, then no diff from latest. if (newestBuildWithChannel != null) { - int channelId = newestBuildWithChannel.Channels[0].Id; + var channelId = newestBuildWithChannel.Channels[0].Id; // Just choose the first channel. This algorithm is mostly just heuristic. var latestCommitKey = $"{node.Repository}@{channelId}"; if (!latestCommitCache.TryGetValue(latestCommitKey, out var latestCommit)) @@ -339,10 +339,10 @@ private static async Task DoLatestInGraphNodeDiffAsync( // Find the build of each repo in the graph, then // get the diff info from the latest - foreach (string repo in visitedRepoUriNodes.Keys) + foreach (var repo in visitedRepoUriNodes.Keys) { // Get all nodes with this value - List nodes = nodeCache.Values.Where(n => n.Repository == repo).ToList(); + var nodes = nodeCache.Values.Where(n => n.Repository == repo).ToList(); // If only one, determine latest if (nodes.Count > 1) { @@ -410,8 +410,8 @@ private static async Task BuildDependencyGraphImplAsync( IEnumerable remotesMap, string testPath) { - List rootDependencyList = rootDependencies?.ToList(); - List remotesList = remotesMap?.ToList(); + var rootDependencyList = rootDependencies?.ToList(); + var remotesList = remotesMap?.ToList(); ValidateBuildOptions(remoteFactory, rootDependencyList, options, remote); if (rootDependencies != null) @@ -696,7 +696,7 @@ private static bool BuildContributesToNode(DependencyGraphNode node, Build poten { if (dependency.Commit == node.Commit && dependency.RepoUri == node.Repository && - potentialContributingBuild.Assets.Any(a => AssetComparer.Equals(a, dependency))) + potentialContributingBuild.Assets.Any(a => Equals(a, dependency))) { return true; } @@ -788,7 +788,7 @@ private static async Task GetRepoPathAsync( new FileSystem(), logger); - string parent = await gitClient.GetRootDirAsync(); + var parent = await gitClient.GetRootDirAsync(); folder = Directory.GetParent(parent).FullName; } @@ -838,17 +838,17 @@ private static async Task> GetDependenciesAsync( { IRemote remoteClient = await remoteFactory.GetRemoteAsync(repoUri, logger); dependencies = await remoteClient.GetDependenciesAsync( - repoUri, + repoUri, commit); } else { - string repoPath = await GetRepoPathAsync(repoUri, commit, remotesMap, reposFolder, logger, gitExecutable); + var repoPath = await GetRepoPathAsync(repoUri, commit, remotesMap, reposFolder, logger, gitExecutable); if (!string.IsNullOrEmpty(repoPath)) { var local = new Local(new RemoteTokenProvider(), logger); - string fileContents = await GitShowAsync( + var fileContents = await GitShowAsync( gitExecutable, repoPath, commit, @@ -890,11 +890,11 @@ private static Dictionary CreateRemotesMapping(IEnumerable(); - foreach (string remotes in remotesMap) + foreach (var remotes in remotesMap) { var keyValuePairs = remotes.Split(';'); - foreach (string keyValue in keyValuePairs) + foreach (var keyValue in keyValuePairs) { var kv = keyValue.Split(','); remotesMapping.Add(kv[0], kv[1]); @@ -926,7 +926,7 @@ private static async Task GetRepoPathFromFolderAsync(string gitLocation, { var processManager = new ProcessManager(logger, gitLocation); - foreach (string directory in Directory.GetDirectories(sourceFolder)) + foreach (var directory in Directory.GetDirectories(sourceFolder)) { var result = await processManager.Execute(gitLocation, new[] { "branch", "--contains", commit }, workingDir: directory); if (!string.IsNullOrEmpty(result.StandardOutput)) diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNode.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNode.cs index cd08e5add9..c2b9fe3630 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNode.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNode.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyGraphNode { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNodeComparer.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNodeComparer.cs index a7f38d2b23..29e0c7f164 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNodeComparer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyGraphNodeComparer.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class DependencyGraphNodeComparer : IEqualityComparer { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyType.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyType.cs index 064a616889..fb96c5d2c5 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyType.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyType.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public enum DependencyType { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyUpdate.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyUpdate.cs index bf37e29ca0..1338802176 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyUpdate.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/DependencyUpdate.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; /// /// Represents a dependency update, from an existing diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/SourceBuildInfo.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/SourceBuildInfo.cs index 983ce93a62..9dfe47b5a9 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/SourceBuildInfo.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Darc/SourceBuildInfo.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.Darc; public class SourceBuildInfo { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitDiff.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitDiff.cs index 056d8828ca..769bd41fe6 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitDiff.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitDiff.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public class GitDiff { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubComment.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubComment.cs index 9ac2ac7abd..d38fb6cdae 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubComment.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubComment.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubComment { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubCommit.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubCommit.cs index fe154dbceb..b0aafcbe17 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubCommit.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubCommit.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubCommit { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContent.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContent.cs index 1e452e92b7..6d8fe36f39 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContent.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContent.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubContent { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContentType.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContentType.cs index 9ef12584c8..3cce2807d3 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContentType.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubContentType.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubContentType { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubMergeMethod.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubMergeMethod.cs index 5d3096e6e4..190ab9fab5 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubMergeMethod.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubMergeMethod.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubMergeMethod { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubPullRequest.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubPullRequest.cs index 57ca669c22..15abd697c3 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubPullRequest.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubPullRequest.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubPullRequest { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubRef.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubRef.cs index 6a6ebca719..5a20aaed32 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubRef.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubRef.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubRef { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTree.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTree.cs index 6bad15247a..06f6fdaf9a 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTree.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTree.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubTree { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTreeItem.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTreeItem.cs index a685b0a791..2d98d265bf 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTreeItem.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/GitHub/GitHubTreeItem.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models.GitHub; public class GitHubTreeItem { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/PrStatus.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/PrStatus.cs index 72c977b435..a1dde5008d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/PrStatus.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/PrStatus.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public enum PrStatus { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/Review.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/Review.cs index 174441799f..109320b36a 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/Review.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/Review.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public class Review { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/ReviewState.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/ReviewState.cs index 75ea15221f..2e851bf33d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/ReviewState.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/ReviewState.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.DarcLib; +namespace Microsoft.DotNet.DarcLib.Models; public enum ReviewState { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VersionDetails.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VersionDetails.cs index 6c18cd0b4c..094bdf6644 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VersionDetails.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VersionDetails.cs @@ -3,6 +3,7 @@ #nullable enable using System.Collections.Generic; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Microsoft.DotNet.DarcLib.Models; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/AllVersionsPropsFile.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/AllVersionsPropsFile.cs index 86cd60da23..00b20a6d6f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/AllVersionsPropsFile.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/AllVersionsPropsFile.cs @@ -4,10 +4,9 @@ using System; using System.Collections.Generic; using System.Xml; -using Microsoft.DotNet.DarcLib.Models; #nullable enable -namespace Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; public interface IAllVersionsPropsFile : IMsBuildPropsFile { @@ -40,7 +39,7 @@ public AllVersionsPropsFile(IReadOnlyCollection repos : base(orderPropertiesAscending: true) { Versions = []; - foreach(var repo in repositoryRecords) + foreach (var repo in repositoryRecords) { UpdateVersion(repo.Path, repo.CommitSha, repo.PackageVersion); } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/GitInfoFile.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/GitInfoFile.cs index f3bbac4d16..0ae9575fe0 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/GitInfoFile.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/GitInfoFile.cs @@ -4,9 +4,8 @@ using System; using System.Collections.Generic; using System.Xml; -using Microsoft.DotNet.DarcLib.Models; -namespace Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; /// /// Model for the git-info files that are part of the VMR. diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/ManifestRecord.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/ManifestRecord.cs index 25e3137302..8113e3347e 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/ManifestRecord.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/ManifestRecord.cs @@ -5,7 +5,7 @@ using Microsoft.DotNet.DarcLib.Helpers; #nullable enable -namespace Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; public interface ISourceComponent { @@ -88,7 +88,7 @@ public int CompareTo(ISourceComponent? other) public class RepositoryRecord : ManifestRecord, IVersionedSourceComponent { - public RepositoryRecord(string path, string remoteUri, string commitSha, string? packageVersion) + public RepositoryRecord(string path, string remoteUri, string commitSha, string? packageVersion) : base(path, remoteUri, commitSha) { PackageVersion = packageVersion; @@ -99,7 +99,7 @@ public RepositoryRecord(string path, string remoteUri, string commitSha, string? public class SubmoduleRecord : ManifestRecord { - public SubmoduleRecord(string path, string remoteUri, string commitSha) + public SubmoduleRecord(string path, string remoteUri, string commitSha) : base(path, remoteUri, commitSha) { } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceManifest.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceManifest.cs index eaa6cdf0e5..bc41b6db6f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceManifest.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceManifest.cs @@ -10,7 +10,7 @@ using Microsoft.DotNet.DarcLib.VirtualMonoRepo; #nullable enable -namespace Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; public interface ISourceManifest { @@ -43,8 +43,8 @@ public class SourceManifest : ISourceManifest public SourceManifest(IEnumerable repositories, IEnumerable submodules) { - _repositories = new SortedSet(repositories); - _submodules = new SortedSet(submodules); + _repositories = [.. repositories]; + _submodules = [.. submodules]; } public void UpdateVersion(string repository, string uri, string sha, string? packageVersion) diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMapping.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMapping.cs index 3692a083cc..7181f2e21f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMapping.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMapping.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; #nullable enable -namespace Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +namespace Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; /// /// Model for the configuration JSON file with list of individual repositories. @@ -15,4 +15,5 @@ public record SourceMapping( string DefaultRef, IReadOnlyCollection Include, IReadOnlyCollection Exclude, + bool DisableSynchronization, string? Version = null); diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMappingFile.cs b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMappingFile.cs index 7b047ba092..4fa75984d8 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMappingFile.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Models/VirtualMonoRepo/SourceMappingFile.cs @@ -58,6 +58,7 @@ public class SourceMappingSetting public string[]? Include { get; set; } public string[]? Exclude { get; set; } public bool IgnoreDefaults { get; set; } + public bool DisableSynchronization { get; set; } } public class AdditionalMappingSetting diff --git a/src/Microsoft.DotNet.Darc/DarcLib/PullRequestNotMergeableException.cs b/src/Microsoft.DotNet.Darc/DarcLib/PullRequestNotMergeableException.cs new file mode 100644 index 0000000000..e3b3830032 --- /dev/null +++ b/src/Microsoft.DotNet.Darc/DarcLib/PullRequestNotMergeableException.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.DotNet.DarcLib; + +[Serializable] +public class PullRequestNotMergeableException : DarcException +{ + public PullRequestNotMergeableException() : base() { } + + public PullRequestNotMergeableException(string message) : base(message) { } +} diff --git a/src/Microsoft.DotNet.Darc/DarcLib/Actions/Remote.cs b/src/Microsoft.DotNet.Darc/DarcLib/Remote.cs similarity index 98% rename from src/Microsoft.DotNet.Darc/DarcLib/Actions/Remote.cs rename to src/Microsoft.DotNet.Darc/DarcLib/Remote.cs index 491c35f8ba..c76ab12542 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/Actions/Remote.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/Remote.cs @@ -10,6 +10,7 @@ using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using NuGet.Versioning; @@ -55,7 +56,7 @@ public async Task DeleteBranchAsync(string repoUri, string branch) public Task BranchExistsAsync(string repoUri, string branch) { _logger.LogInformation("Checking if branch '{branch}' exists in '{repoUri}'", branch, repoUri); - return _remoteGitClient.DoesBranchExistAsync(repoUri, branch); + return _remoteGitClient.DoesBranchExistAsync(repoUri, branch); } /// @@ -184,9 +185,9 @@ public async Task> CommitUpdatesAsync( // If we are updating the arcade sdk we need to update the eng/common files // and the sdk versions in global.json DependencyDetail arcadeItem = itemsToUpdate.GetArcadeUpdate(); - + SemanticVersion targetDotNetVersion = null; - bool mayNeedArcadeUpdate = (arcadeItem != null && repoUri != arcadeItem.RepoUri); + var mayNeedArcadeUpdate = arcadeItem != null && repoUri != arcadeItem.RepoUri; if (mayNeedArcadeUpdate) { @@ -213,7 +214,7 @@ public async Task> CommitUpdatesAsync( filesToCommit.AddRange(engCommonFiles); // Files in the target repo - string latestCommit = await _remoteGitClient.GetLastCommitShaAsync(repoUri, branch); + var latestCommit = await _remoteGitClient.GetLastCommitShaAsync(repoUri, branch); List targetEngCommonFiles = await GetCommonScriptFilesAsync(repoUri, latestCommit); var deletedFiles = new List(); diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CodeownersGenerator.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CodeownersGenerator.cs index 8e3ffc465c..f9fddffee3 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CodeownersGenerator.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CodeownersGenerator.cs @@ -8,8 +8,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/ComponentListGenerator.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/ComponentListGenerator.cs index 7715ee2a18..d5178dbe90 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/ComponentListGenerator.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/ComponentListGenerator.cs @@ -6,8 +6,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CredScanSuppressionsGenerator.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CredScanSuppressionsGenerator.cs index b33069424e..d95e1b6376 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CredScanSuppressionsGenerator.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/CredScanSuppressionsGenerator.cs @@ -9,8 +9,8 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable @@ -104,9 +104,6 @@ public async Task UpdateCredScanSuppressions(CancellationToken cancellationToken private async Task AddCredScanSuppressionsContent(CredScanSuppressionFile vmrCredScanSuppressionsFile, string repoPath, CancellationToken cancellationToken) { - // CredScanSuppressions.json files are very restricted in size so we can safely work with them in-memory - var content = new List(); - foreach (var location in s_credScanSuppressionsLocations) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/Exceptions.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/Exceptions.cs new file mode 100644 index 0000000000..06bfb74d45 --- /dev/null +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/Exceptions.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using Microsoft.DotNet.DarcLib.Helpers; + +#nullable enable +namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; + +public class PatchApplicationFailedException( + VmrIngestionPatch patch, + ProcessExecutionResult result, + bool reverseApply) + : Exception(GetExceptionMessage(patch, result, reverseApply)) +{ + public VmrIngestionPatch Patch { get; } = patch; + public ProcessExecutionResult Result { get; } = result; + + private static string GetExceptionMessage(VmrIngestionPatch patch, ProcessExecutionResult result, bool reverseApply) + => $"Failed to {(reverseApply ? "reverse-apply" : "apply")} the patch {Path.GetFileName(patch.Path)} to {patch.ApplicationPath ?? "/"}." + + Environment.NewLine + + Environment.NewLine + + result; +} + +public class ConflictInPrBranchException(VmrIngestionPatch patch, string targetBranch) + : Exception($"Failed to flow changes due to conflicts in the target branch ({targetBranch})") +{ + public VmrIngestionPatch Patch { get; } = patch; +} diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/IVmrPatchHandler.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/IVmrPatchHandler.cs index d4836bdb53..c065029290 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/IVmrPatchHandler.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/IVmrPatchHandler.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PatchApplicationFailedException.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PatchApplicationFailedException.cs deleted file mode 100644 index c932601986..0000000000 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PatchApplicationFailedException.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using Microsoft.DotNet.DarcLib.Helpers; - -#nullable enable -namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; - -internal class PatchApplicationFailedException : Exception -{ - public PatchApplicationFailedException(VmrIngestionPatch patch, ProcessExecutionResult result, bool reverseApply) - : base($"Failed to {(reverseApply ? "reverse-apply" : "apply")} the patch {Path.GetFileName(patch.Path)} to {patch.ApplicationPath ?? "/"}." - + Environment.NewLine - + Environment.NewLine - + result) - { - } -} diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrBackFlower.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrBackFlower.cs index e40b7ac4a4..4318cc7e8b 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrBackFlower.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrBackFlower.cs @@ -5,8 +5,8 @@ using System.Threading; using System.Threading.Tasks; using LibGit2Sharp; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; @@ -23,18 +23,16 @@ public interface IPcsVmrBackFlower : IVmrBackFlower /// Flows backward the code from the VMR to the target branch of a product repo. /// This overload is used in the context of the PCS. /// - /// Mapping to flow + /// Subscription to flow /// Build to flow - /// If target branch does not exist, it is created off of this branch /// Target branch to make the changes on /// /// Boolean whether there were any changes to be flown /// and a path to the local repo where the new branch is created /// Task<(bool HadUpdates, NativePath RepoPath)> FlowBackAsync( - string mappingName, + Subscription subscription, Build build, - string baseBranch, string targetBranch, CancellationToken cancellationToken = default); } @@ -73,16 +71,15 @@ public PcsVmrBackFlower( } public async Task<(bool HadUpdates, NativePath RepoPath)> FlowBackAsync( - string mappingName, + Subscription subscription, Build build, - string baseBranch, string targetBranch, CancellationToken cancellationToken = default) { - (SourceMapping mapping, ILocalGitRepo targetRepo) = await PrepareVmrAndRepo( - mappingName, + (bool targetBranchExisted, SourceMapping mapping, ILocalGitRepo targetRepo) = await PrepareVmrAndRepo( + subscription.SourceDirectory, build, - baseBranch, + subscription.TargetBranch, targetBranch, cancellationToken); @@ -94,15 +91,17 @@ public PcsVmrBackFlower( lastFlow, build.Commit, build, - baseBranch, + subscription.ExcludedAssets, + subscription.TargetBranch, targetBranch, - true, + discardPatches: true, + rebaseConflicts: !targetBranchExisted, cancellationToken); return (hadUpdates, targetRepo.Path); } - private async Task<(SourceMapping, ILocalGitRepo)> PrepareVmrAndRepo( + private async Task<(bool, SourceMapping, ILocalGitRepo)> PrepareVmrAndRepo( string mappingName, Build build, string baseBranch, @@ -124,6 +123,7 @@ await _vmrCloneManager.PrepareVmrAsync( .ToList(); ILocalGitRepo targetRepo; + bool targetBranchExisted; // Now try to see if the target branch exists already try @@ -134,6 +134,7 @@ await _vmrCloneManager.PrepareVmrAsync( [baseBranch, targetBranch], targetBranch, cancellationToken); + targetBranchExisted = true; } catch (NotFoundException) { @@ -144,8 +145,9 @@ await _vmrCloneManager.PrepareVmrAsync( baseBranch, cancellationToken); await targetRepo.CreateBranchAsync(targetBranch); + targetBranchExisted = false; } - return (mapping, targetRepo); + return (targetBranchExisted, mapping, targetRepo); } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrForwardFlower.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrForwardFlower.cs index 321744cc59..1c90c3ee4f 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrForwardFlower.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/PcsVmrForwardFlower.cs @@ -5,8 +5,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; @@ -22,15 +22,14 @@ public interface IPcsVmrForwardFlower /// Flows forward the code from the source repo to the target branch of the VMR. /// This overload is used in the context of the PCS. /// - /// Mapping to flow + /// Subscription to flow /// Build to flow /// If target branch does not exist, it is created off of this branch /// Target branch to make the changes on /// True when there were changes to be flown Task FlowForwardAsync( - string mappingName, + Subscription subscription, Build build, - string baseBranch, string targetBranch, CancellationToken cancellationToken = default); } @@ -55,7 +54,6 @@ public PcsVmrForwardFlower( ILocalGitRepoFactory localGitRepoFactory, IVersionDetailsParser versionDetailsParser, IProcessManager processManager, - IWorkBranchFactory workBranchFactory, ICoherencyUpdateResolver coherencyUpdateResolver, IAssetLocationResolver assetLocationResolver, IFileSystem fileSystem, @@ -68,16 +66,16 @@ public PcsVmrForwardFlower( } public async Task FlowForwardAsync( - string mappingName, + Subscription subscription, Build build, - string baseBranch, string targetBranch, CancellationToken cancellationToken = default) { - await PrepareVmr(baseBranch, targetBranch, cancellationToken); + var baseBranch = subscription.TargetBranch; + bool targetBranchExisted = await PrepareVmr(baseBranch, targetBranch, cancellationToken); // Prepare repo - SourceMapping mapping = _dependencyTracker.GetMapping(mappingName); + SourceMapping mapping = _dependencyTracker.GetMapping(subscription.TargetDirectory); ISourceComponent repoVersion = _sourceManifest.GetRepoVersion(mapping.Name); List remotes = (new[] { mapping.DefaultRemote, repoVersion.RemoteUri }) .Distinct() @@ -98,9 +96,11 @@ public async Task FlowForwardAsync( sourceRepo, mapping, build, + subscription.ExcludedAssets, baseBranch, targetBranch, discardPatches: true, + rebaseConflicts: !targetBranchExisted, cancellationToken); } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/RepositoryCloneManager.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/RepositoryCloneManager.cs index 0cd20bb093..fe6069a800 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/RepositoryCloneManager.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/RepositoryCloneManager.cs @@ -5,8 +5,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/SourceMappingParser.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/SourceMappingParser.cs index 62a2aa7112..09714be4e4 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/SourceMappingParser.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/SourceMappingParser.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable @@ -117,7 +116,8 @@ private static SourceMapping CreateMapping(SourceMappingSetting defaults, Source DefaultRemote: setting.DefaultRemote, DefaultRef: setting.DefaultRef ?? defaults.DefaultRef ?? "main", Include: include.ToImmutableArray(), - Exclude: exclude.ToImmutableArray()); + Exclude: exclude.ToImmutableArray(), + DisableSynchronization: setting.DisableSynchronization); } private static string? NormalizePath(string? relativePath) diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrBackflower.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrBackflower.cs index 7f6378d222..e226fb6aab 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrBackflower.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrBackflower.cs @@ -7,8 +7,8 @@ using System.Threading; using System.Threading.Tasks; using LibGit2Sharp; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; @@ -25,6 +25,7 @@ public interface IVmrBackFlower /// Local checkout of the repository /// SHA to flow /// Build to flow + /// Assets to exclude from the dependency flow /// If target branch does not exist, it is created off of this branch /// Target branch to make the changes on /// Keep patch files? @@ -33,6 +34,7 @@ Task FlowBackAsync( NativePath targetRepo, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, @@ -46,6 +48,7 @@ Task FlowBackAsync( /// Local checkout of the repository /// SHA to flow /// Build to flow + /// Assets to exclude from the dependency flow /// If target branch does not exist, it is created off of this branch /// Target branch to make the changes on /// Keep patch files? @@ -54,6 +57,7 @@ Task FlowBackAsync( ILocalGitRepo targetRepo, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, @@ -114,6 +118,7 @@ public Task FlowBackAsync( NativePath targetRepoPath, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, @@ -123,6 +128,7 @@ public Task FlowBackAsync( _localGitRepoFactory.Create(targetRepoPath), shaToFlow, buildToFlow, + excludedAssets, baseBranch, targetBranch, discardPatches, @@ -133,6 +139,7 @@ public async Task FlowBackAsync( ILocalGitRepo targetRepo, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, @@ -147,7 +154,7 @@ public async Task FlowBackAsync( // SHA comes either directly or from the build or if none supplied, from tip of the VMR shaToFlow ??= build?.Commit; - (SourceMapping mapping, shaToFlow) = await PrepareVmrAndRepo( + (bool targetBranchExisted, SourceMapping mapping, shaToFlow) = await PrepareVmrAndRepo( mappingName, targetRepo, shaToFlow, @@ -164,9 +171,11 @@ public async Task FlowBackAsync( lastFlow, shaToFlow, build, + excludedAssets, baseBranch, targetBranch, discardPatches, + rebaseConflicts: !targetBranchExisted, cancellationToken); } @@ -176,9 +185,11 @@ protected async Task FlowBackAsync( Codeflow lastFlow, string shaToFlow, Build? build, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches, + bool rebaseConflicts, CancellationToken cancellationToken) { var hasChanges = await FlowCodeAsync( @@ -187,15 +198,18 @@ protected async Task FlowBackAsync( targetRepo, mapping, build, + excludedAssets, baseBranch, targetBranch, discardPatches, + rebaseConflicts, cancellationToken); hasChanges |= await UpdateDependenciesAndToolset( _vmrInfo.VmrPath, targetRepo, build, + excludedAssets, sourceElementSha: shaToFlow, cancellationToken); @@ -208,9 +222,11 @@ protected override async Task SameDirectionFlowAsync( Codeflow currentFlow, ILocalGitRepo targetRepo, Build? build, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches, + bool rebaseConflicts, CancellationToken cancellationToken) { // Exclude all submodules that belong to the mapping @@ -254,7 +270,6 @@ protected override async Task SameDirectionFlowAsync( _logger.LogInformation("Created {count} patch(es)", patches.Count); - await targetRepo.CheckoutAsync(lastFlow.TargetSha); var workBranch = await _workBranchFactory.CreateWorkBranchAsync(targetRepo, newBranchName, targetBranch); // TODO https://github.com/dotnet/arcade-services/issues/3302: Remove VMR patches before we create the patches @@ -270,9 +285,15 @@ protected override async Task SameDirectionFlowAsync( { _logger.LogInformation(e.Message); - // TODO https://github.com/dotnet/arcade-services/issues/2995: This can happen when we also update a PR branch but there are conflicting changes inside. In this case, we should just stop. We need a flag for that. + // When we are updating an already existing PR branch, there can be conflicting changes in the PR from devs. + // In that case we want to throw as that is a conflict we don't want to try to resolve. + if (!rebaseConflicts) + { + _logger.LogInformation("Failed to update a PR branch because of a conflict. Stopping the flow.."); + throw new ConflictInPrBranchException(e.Patch, targetBranch); + } - // This happens when a conflicting change was made in the last backflow PR (before merging) + // Otherwise, we have a conflicting change in the last backflow PR (before merging) // The scenario is described here: https://github.com/dotnet/arcade/blob/main/Documentation/UnifiedBuild/VMR-Full-Code-Flow.md#conflicts _logger.LogInformation("Failed to create PR branch because of a conflict. Re-creating the previous flow.."); @@ -292,10 +313,12 @@ await FlowCodeAsync( new Backflow(lastLastFlow.SourceSha, lastFlow.SourceSha), targetRepo, mapping, - /* TODO: Find a previous build? */ null, + /* TODO (https://github.com/dotnet/arcade-services/issues/4166): Find a previous build? */ null, + excludedAssets, targetBranch, targetBranch, discardPatches, + rebaseConflicts, cancellationToken); // The recursive call right above would returned checked out at targetBranch @@ -374,7 +397,17 @@ .. mapping.Exclude.Select(VmrPatchHandler.GetExclusionRule), .. submoduleExclusions, ]; - ProcessExecutionResult result = await targetRepo.ExecuteGitCommand(["rm", "-r", "-q", "--", .. removalFilters], cancellationToken); + string[] args = ["rm", "-r", "-q"]; + if (removalFilters.Count > 0) + { + args = [.. args, "--", .. removalFilters]; + } + else + { + args = [.. args, "."]; + } + + ProcessExecutionResult result = await targetRepo.ExecuteGitCommand(args, cancellationToken); result.ThrowIfFailed($"Failed to remove files from {targetRepo}"); // Now we insert the VMR files @@ -408,7 +441,7 @@ .. mapping.Exclude.Select(VmrPatchHandler.GetExclusionRule), return true; } - private async Task<(SourceMapping, string)> PrepareVmrAndRepo( + private async Task<(bool, SourceMapping, string)> PrepareVmrAndRepo( string mappingName, ILocalGitRepo targetRepo, string? shaToFlow, @@ -436,6 +469,8 @@ .. mapping.Exclude.Select(VmrPatchHandler.GetExclusionRule), // Refresh the repo await targetRepo.FetchAllAsync(remotes, cancellationToken); + bool targetBranchExisted; + try { // Try to see if both base and target branch are available @@ -445,14 +480,16 @@ await _repositoryCloneManager.PrepareCloneAsync( [baseBranch, targetBranch], targetBranch, cancellationToken); + targetBranchExisted = true; } catch (NotFoundException) { // If target branch does not exist, we create it off of the base branch await targetRepo.CheckoutAsync(baseBranch); await targetRepo.CreateBranchAsync(targetBranch); + targetBranchExisted = false; }; - return (mapping, shaToFlow); + return (targetBranchExisted, mapping, shaToFlow); } } diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloakedFileScanner.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloakedFileScanner.cs index dc96f8f055..af79b9b066 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloakedFileScanner.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloakedFileScanner.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloneManager.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloneManager.cs index c5e1cf00d8..12a8cf672b 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloneManager.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCloneManager.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCodeflower.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCodeflower.cs index 2e613d8194..c0c219f97d 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCodeflower.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrCodeflower.cs @@ -7,9 +7,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; using NuGet.Versioning; @@ -78,9 +79,11 @@ protected async Task FlowCodeAsync( ILocalGitRepo repo, SourceMapping mapping, Build? build, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches, + bool rebaseConflicts, CancellationToken cancellationToken = default) { if (lastFlow.SourceSha == currentFlow.TargetSha) @@ -104,9 +107,11 @@ protected async Task FlowCodeAsync( currentFlow, repo, build, + excludedAssets, baseBranch, targetBranch, discardPatches, + rebaseConflicts, cancellationToken); } else @@ -137,6 +142,16 @@ protected async Task FlowCodeAsync( /// Handles flowing changes that succeed a flow that was in the same direction (outgoing from the source repo). /// The changes that are flown are taken from a simple patch of changes that occurred since the last flow. /// + /// Mapping to flow + /// Last flow that happened for the given mapping + /// Current flow that is being flown + /// Local git repo clone of the source repo + /// Build with assets (dependencies) that is being flown + /// Assets to exclude from the dependency flow + /// If target branch does not exist, it is created off of this branch + /// Target branch to make the changes on + /// If true, patches are deleted after applying them + /// When a conflict is found, should we retry the flow from an earlier checkpoint? /// True if there were changes to flow protected abstract Task SameDirectionFlowAsync( SourceMapping mapping, @@ -144,15 +159,25 @@ protected abstract Task SameDirectionFlowAsync( Codeflow currentFlow, ILocalGitRepo repo, Build? build, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches, + bool rebaseConflicts, CancellationToken cancellationToken); /// /// Handles flowing changes that succeed a flow that was in the opposite direction (incoming in the source repo). /// The changes that are flown are taken from a diff of repo contents and the last sync point from the last flow. /// + /// Mapping to flow + /// Last flow that happened for the given mapping + /// Current flow that is being flown + /// Local git repo clone of the source repo + /// Build with assets (dependencies) that is being flown + /// If target branch does not exist, it is created off of this branch + /// Target branch to make the changes on + /// If true, patches are deleted after applying them /// True if there were changes to flow protected abstract Task OppositeDirectionFlowAsync( SourceMapping mapping, @@ -292,11 +317,13 @@ private async Task GetLastForwardFlow(string mappingName) /// Source repository (needed when eng/common is flown too) /// Target repository directory /// Build with assets (dependencies) that is being flows + /// Assets to exclude from the dependency flow /// For backflows, VMR SHA that is being flown so it can be stored in Version.Details.xml protected async Task UpdateDependenciesAndToolset( NativePath sourceRepo, ILocalGitRepo targetRepo, Build? build, + IReadOnlyCollection? excludedAssets, string? sourceElementSha, CancellationToken cancellationToken) { @@ -324,8 +351,9 @@ protected async Task UpdateDependenciesAndToolset( // Generate the element and get updates if (build is not null) { - IEnumerable assetData = build.Assets.Select( - a => new AssetData(a.NonShipping) + IEnumerable assetData = build.Assets + .Where(a => excludedAssets is null || !excludedAssets.Contains(a.Name)) + .Select(a => new AssetData(a.NonShipping) { Name = a.Name, Version = a.Version diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyTracker.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyTracker.cs index 8c3533e90e..eb8e806672 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyTracker.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyTracker.cs @@ -6,8 +6,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyUpdate.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyUpdate.cs index a6f3d8be0e..d376672c9a 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyUpdate.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrDependencyUpdate.cs @@ -1,7 +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 Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrForwardFlower.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrForwardFlower.cs index 4322e801f7..9c5f57f955 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrForwardFlower.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrForwardFlower.cs @@ -7,8 +7,8 @@ using System.Threading; using System.Threading.Tasks; using LibGit2Sharp; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; @@ -29,6 +29,7 @@ public interface IVmrForwardFlower /// Local checkout of the repository /// SHA to flow /// Build to flow + /// Assets to exclude from the dependency flow /// If target branch does not exist, it is created off of this branch /// Target branch to make the changes on /// Keep patch files? @@ -38,6 +39,7 @@ Task FlowForwardAsync( NativePath sourceRepo, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, @@ -91,12 +93,13 @@ public async Task FlowForwardAsync( NativePath repoPath, string? shaToFlow, int? buildToFlow, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches = false, CancellationToken cancellationToken = default) { - await PrepareVmr(baseBranch, targetBranch, cancellationToken); + bool targetBranchExisted = await PrepareVmr(baseBranch, targetBranch, cancellationToken); Build? build = null; if (buildToFlow.HasValue) @@ -131,24 +134,28 @@ public async Task FlowForwardAsync( sourceRepo, mapping, build, + excludedAssets, baseBranch, targetBranch, discardPatches, + rebaseConflicts: !targetBranchExisted, cancellationToken); hasChanges |= await UpdateDependenciesAndToolset( sourceRepo.Path, LocalVmr, build, + excludedAssets, sourceElementSha: null, cancellationToken); return hasChanges; } - protected async Task PrepareVmr(string baseBranch, string targetBranch, CancellationToken cancellationToken) + protected async Task PrepareVmr(string baseBranch, string targetBranch, CancellationToken cancellationToken) { - // Prepare the VMR + bool branchExisted; + try { await _vmrCloneManager.PrepareVmrAsync( @@ -156,6 +163,7 @@ await _vmrCloneManager.PrepareVmrAsync( [baseBranch, targetBranch], targetBranch, cancellationToken); + branchExisted = true; } catch (NotFoundException) { @@ -163,10 +171,12 @@ await _vmrCloneManager.PrepareVmrAsync( // We will create it off of the base branch await LocalVmr.CheckoutAsync(baseBranch); await LocalVmr.CreateBranchAsync(targetBranch); + branchExisted = false; } await _dependencyTracker.InitializeSourceMappings(); _sourceManifest.Refresh(_vmrInfo.SourceManifestPath); + return branchExisted; } protected override async Task SameDirectionFlowAsync( @@ -175,9 +185,11 @@ protected override async Task SameDirectionFlowAsync( Codeflow currentFlow, ILocalGitRepo sourceRepo, Build? build, + IReadOnlyCollection? excludedAssets, string baseBranch, string targetBranch, bool discardPatches, + bool rebaseConflicts, CancellationToken cancellationToken) { string branchName = currentFlow.GetBranchName(); @@ -217,10 +229,14 @@ protected override async Task SameDirectionFlowAsync( discardPatches, cancellationToken); } - catch (Exception e) when (e.Message.Contains("Failed to apply the patch")) + catch (PatchApplicationFailedException e) { - // TODO https://github.com/dotnet/arcade-services/issues/2995: This can happen when we also update a PR branch but there are conflicting changes inside. - // In this case, we should just stop. We need a flag for that. + // When we are updating an already existing PR branch, there can be conflicting changes in the PR from devs. + if (!rebaseConflicts) + { + _logger.LogInformation("Failed to update a PR branch because of a conflict. Stopping the flow.."); + throw new ConflictInPrBranchException(e.Patch, targetBranch); + } // This happens when a conflicting change was made in the last backflow PR (before merging) // The scenario is described here: https://github.com/dotnet/arcade/blob/main/Documentation/UnifiedBuild/VMR-Full-Code-Flow.md#conflicts @@ -241,10 +257,12 @@ await FlowCodeAsync( new ForwardFlow(lastLastFlow.SourceSha, lastFlow.SourceSha), sourceRepo, mapping, - build, - targetBranch, // TODO: This is an interesting one - should we try to find a build for that previous SHA? + build, // TODO (https://github.com/dotnet/arcade-services/issues/4166): This is an interesting one - should we try to find a build for that previous SHA? + excludedAssets, + baseBranch, targetBranch, discardPatches, + rebaseConflicts, cancellationToken); // We apply the current changes on top again - they should apply now diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInfo.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInfo.cs index 1ac0391797..2f7c540de6 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInfo.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInfo.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrIngestionPatch.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrIngestionPatch.cs index bd7ede52d7..b072a8e781 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrIngestionPatch.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrIngestionPatch.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInitializer.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInitializer.cs index 5e678c9902..4fd61a09bf 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInitializer.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrInitializer.cs @@ -6,8 +6,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrManagerBase.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrManagerBase.cs index b2add4b74d..d504529778 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrManagerBase.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrManagerBase.cs @@ -8,9 +8,10 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPatchHandler.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPatchHandler.cs index e33a955e02..0a65afa538 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPatchHandler.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPatchHandler.cs @@ -9,8 +9,8 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable @@ -418,7 +418,7 @@ public async Task> CreatePatches( sha2, fileName, // Ignore all files except the one we're currently processing - [.. filters?.Except([GetInclusionRule("**/*")]) ], + [.. filters?.Except([GetInclusionRule("**/*")]) ?? []], true, workingDir, applicationPath, @@ -574,7 +574,7 @@ ImmutableArray GetSubmoduleFilters(IReadOnlyCollection filters) static string SanitizeName(string mappingName) { - mappingName = mappingName.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries)[^1]; + mappingName = mappingName.Split(['\\', '/'], StringSplitOptions.RemoveEmptyEntries)[^1]; if (mappingName.EndsWith(".git")) { @@ -589,7 +589,8 @@ static string SanitizeName(string mappingName) change.Url, change.Before, GetSubmoduleFilters(mapping.Include), - GetSubmoduleFilters(mapping.Exclude)); + GetSubmoduleFilters(mapping.Exclude), + DisableSynchronization: false); var submodulePath = change.Path; if (!string.IsNullOrEmpty(relativePath)) diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPusher.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPusher.cs index 91eef7e243..872a0a0cc4 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPusher.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrPusher.cs @@ -9,8 +9,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRegistrations.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRegistrations.cs index 53669ac7db..9ead506826 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRegistrations.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRegistrations.cs @@ -7,8 +7,8 @@ using System.Security.Cryptography.X509Certificates; using Maestro.Common; using Maestro.Common.AzureDevOpsTokens; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRepoVersionResolver.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRepoVersionResolver.cs index f91ed304dd..23ccd03efc 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRepoVersionResolver.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrRepoVersionResolver.cs @@ -3,7 +3,7 @@ using System; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; #nullable enable namespace Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrScanner.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrScanner.cs index da76e3a986..0e86114494 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrScanner.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrScanner.cs @@ -6,8 +6,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable @@ -104,7 +104,7 @@ bool IsApplicableRule(string line) var text = await _fileSystem.ReadAllTextAsync(baselineFilePath); return text - .Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries) .Where(IsApplicableRule) .Select(line => { diff --git a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrUpdater.cs b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrUpdater.cs index cdd19a4731..aa3c886c72 100644 --- a/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrUpdater.cs +++ b/src/Microsoft.DotNet.Darc/DarcLib/VirtualMonoRepo/VmrUpdater.cs @@ -9,8 +9,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.Extensions.Logging; #nullable enable @@ -173,6 +173,12 @@ private async Task> UpdateRepositoryInter bool discardPatches, CancellationToken cancellationToken) { + if (update.Mapping.DisableSynchronization) + { + _logger.LogInformation("Synchronization for {repo} is disabled, skipping...", update.Mapping.Name); + return []; + } + VmrDependencyVersion currentVersion = _dependencyTracker.GetDependencyVersion(update.Mapping) ?? throw new Exception($"Failed to find current version for {update.Mapping.Name}"); @@ -187,7 +193,7 @@ await UpdateTargetVersionOnly( update.Mapping, currentVersion, cancellationToken); - return Array.Empty(); + return []; } throw new EmptySyncException($"Repository {update.Mapping.Name} is already at {update.TargetRevision}"); @@ -279,7 +285,7 @@ private async Task UpdateRepositoryRecursively( var updates = (await GetAllDependenciesAsync(rootUpdate, additionalRemotes, cancellationToken)).ToList(); var extraneousMappings = _dependencyTracker.Mappings - .Where(mapping => !updates.Any(update => update.Mapping == mapping)) + .Where(mapping => !updates.Any(update => update.Mapping == mapping) && !mapping.DisableSynchronization) .Select(mapping => mapping.Name); if (extraneousMappings.Any()) @@ -304,6 +310,11 @@ private async Task UpdateRepositoryRecursively( foreach (VmrDependencyUpdate update in updates) { + if (update.Mapping.DisableSynchronization) + { + continue; + } + cancellationToken.ThrowIfCancellationRequested(); string currentSha; diff --git a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2018_07_16/Controllers/ChannelsController.cs b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2018_07_16/Controllers/ChannelsController.cs index 341c7d8a13..4af32355e9 100644 --- a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2018_07_16/Controllers/ChannelsController.cs +++ b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2018_07_16/Controllers/ChannelsController.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.ApiVersioning.Swashbuckle; using Microsoft.AspNetCore.Mvc; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.EntityFrameworkCore; using Build = Maestro.Data.Models.Build; diff --git a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/BuildsController.cs b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/BuildsController.cs index 9343dca97c..dce4730215 100644 --- a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/BuildsController.cs +++ b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/BuildsController.cs @@ -12,7 +12,6 @@ using Microsoft.DotNet.DarcLib; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Internal; -using ProductConstructionService.Api.VirtualMonoRepo; using ProductConstructionService.DependencyFlow.WorkItems; using ProductConstructionService.WorkItems; diff --git a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/SubscriptionsController.cs b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/SubscriptionsController.cs index c8efa2c0ac..a85664ce30 100644 --- a/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/SubscriptionsController.cs +++ b/src/ProductConstructionService/ProductConstructionService.Api/Api/v2020_02_20/Controllers/SubscriptionsController.cs @@ -405,17 +405,17 @@ public async Task Create([FromBody, Required] SubscriptionData su if (subscription.SourceEnabled.HasValue) { - if (subscription.SourceEnabled.Value && subscription.SourceDirectory == null && subscription.TargetDirectory == null) + if (subscription.SourceEnabled.Value && string.IsNullOrEmpty(subscription.SourceDirectory) && string.IsNullOrEmpty(subscription.TargetDirectory)) { return BadRequest(new ApiError("The request is invalid. Source-enabled subscriptions require the source or target directory to be set")); } - if (!subscription.SourceEnabled.Value && (subscription.SourceDirectory ?? subscription.TargetDirectory) != null) + if (!subscription.SourceEnabled.Value && (!string.IsNullOrEmpty(subscription.SourceDirectory) || !string.IsNullOrEmpty(subscription.TargetDirectory))) { return BadRequest(new ApiError("The request is invalid. Source or target directory can be set only for source-enabled subscriptions")); } - if (subscription.SourceDirectory != null && subscription.TargetDirectory != null) + if (!string.IsNullOrEmpty(subscription.SourceDirectory) && !string.IsNullOrEmpty(subscription.TargetDirectory)) { return BadRequest(new ApiError("The request is invalid. Only one of source or target directory can be set")); } diff --git a/src/ProductConstructionService/ProductConstructionService.Api/appsettings.Staging.json b/src/ProductConstructionService/ProductConstructionService.Api/appsettings.Staging.json index 4667202414..3e0d5f8c30 100644 --- a/src/ProductConstructionService/ProductConstructionService.Api/appsettings.Staging.json +++ b/src/ProductConstructionService/ProductConstructionService.Api/appsettings.Staging.json @@ -5,7 +5,7 @@ "redis": "product-construction-service-redis-int.redis.cache.windows.net:6380,ssl=true" }, "ManagedIdentityClientId": "1d43ba8a-c2a6-4fad-b064-6d8c16fc0745", - "VmrUri": "https://github.com/maestro-auth-test/dnceng-vmr", + "VmrUri": "https://github.com/maestro-auth-test/maestro-test-vmr", "BuildAssetRegistrySqlConnectionString": "Data Source=tcp:maestro-int-server.database.windows.net,1433; Initial Catalog=BuildAssetRegistry; Authentication=Active Directory Managed Identity; Persist Security Info=False; MultipleActiveResultSets=True; Connect Timeout=30; Encrypt=True; TrustServerCertificate=False; User Id=USER_ID_PLACEHOLDER", "Kusto": { "Database": "engineeringdata", diff --git a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/BuildGraphData.cs b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/BuildGraphData.cs index dfa6fc5dbc..b1b0ad4fad 100644 --- a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/BuildGraphData.cs +++ b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/BuildGraphData.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; -using System.Text; -using Microsoft.FluentUI.AspNetCore.Components; using ProductConstructionService.Client.Models; namespace ProductConstructionService.BarViz.Code.Helpers; @@ -13,7 +11,7 @@ public class BuildGraphData { private readonly BuildGraph _buildGraph; private readonly Build _rootBuild; - private int _channelId; + private readonly int _channelId; private readonly Dictionary> _parents; private readonly Dictionary> _children; @@ -32,8 +30,8 @@ public BuildGraphData(BuildGraph buildGraph, int rootBuildId, int channelId) _channelId = channelId; // fill parents and children dictionaries - _parents = new Dictionary>(); - _children = new Dictionary>(); + _parents = []; + _children = []; foreach (var build in _buildGraph.Builds.Values) { foreach (var dep in build.Dependencies) @@ -41,18 +39,16 @@ public BuildGraphData(BuildGraph buildGraph, int rootBuildId, int channelId) int child = dep.BuildId; int parent = build.Id; - HashSet? childParents; - if (!_parents.TryGetValue(child, out childParents)) + if (!_parents.TryGetValue(child, out HashSet? childParents)) { - childParents = new HashSet(); + childParents = []; _parents.Add(child, childParents); } childParents.Add(parent); - HashSet? parentChildren; - if (!_children.TryGetValue(parent, out parentChildren)) + if (!_children.TryGetValue(parent, out HashSet? parentChildren)) { - parentChildren = new HashSet(); + parentChildren = []; _children.Add(parent, parentChildren); } parentChildren.Add(child); @@ -145,7 +141,7 @@ BuildTreeViewItem BuildTree(Build build, int level) }; } - List items = new List(); + List items = []; foreach (var dependency in build.Dependencies) { if (dependency.IsProduct || includeToolset) diff --git a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/RepoUrlConverter.cs b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/RepoUrlConverter.cs index e1176a8257..83ae4ef076 100644 --- a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/RepoUrlConverter.cs +++ b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Helpers/RepoUrlConverter.cs @@ -31,8 +31,8 @@ public static class RepoUrlConverter return null; } - private static Regex _repoUrlGitHubRegex = new Regex(@"^https:\/\/github\.com\/(?[^\/]+)\/(?.*)$"); - private static Regex _repoUrlAzureDevOpsRegex = new Regex(@"^https:\/\/dev\.azure\.com\/(?[^\/]+)\/(?[^\/]+)\/_git\/(?.*)$"); + private static readonly Regex _repoUrlGitHubRegex = new(@"^https:\/\/github\.com\/(?[^\/]+)\/(?.*)$"); + private static readonly Regex _repoUrlAzureDevOpsRegex = new(@"^https:\/\/dev\.azure\.com\/(?[^\/]+)\/(?[^\/]+)\/_git\/(?.*)$"); public static string? RepoUrlToSlug(string? repoUrl) { diff --git a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Services/UrlRedirectManager.cs b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Services/UrlRedirectManager.cs index 3a46a77bb4..c661ef17ef 100644 --- a/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Services/UrlRedirectManager.cs +++ b/src/ProductConstructionService/ProductConstructionService.BarViz/Code/Services/UrlRedirectManager.cs @@ -10,9 +10,9 @@ namespace ProductConstructionService.BarViz.Code.Services; public class UrlRedirectManager { - private static Regex _repoUrlGitHubRegex = new Regex(@"^\/(?[^\/]+)\/(?[^\/]+)\/(?[^\/]+)\/graph$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + private static readonly Regex _repoUrlGitHubRegex = new(@"^\/(?[^\/]+)\/(?[^\/]+)\/(?[^\/]+)\/graph$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); - public string? ApplyLocatinoRedirects(string location) + public static string? ApplyLocatinoRedirects(string location) { Uri uri = new Uri(location); diff --git a/src/ProductConstructionService/ProductConstructionService.BarViz/Components/DependencyGrid.razor.cs b/src/ProductConstructionService/ProductConstructionService.BarViz/Components/DependencyGrid.razor.cs index 2a659fd4d8..35cd8b19b1 100644 --- a/src/ProductConstructionService/ProductConstructionService.BarViz/Components/DependencyGrid.razor.cs +++ b/src/ProductConstructionService/ProductConstructionService.BarViz/Components/DependencyGrid.razor.cs @@ -7,7 +7,6 @@ namespace ProductConstructionService.BarViz.Components; - public partial class DependencyGrid { [Parameter] @@ -26,9 +25,9 @@ public partial class DependencyGrid protected override void OnParametersSet() { - _dependenciesGridData = BuildGraphData != null ? - BuildGraphData.BuildDependenciesGridData(IncludeReleasedBuilds, ShowSubDependencies, IncludeToolset).AsQueryable() : - null; + _dependenciesGridData = BuildGraphData? + .BuildDependenciesGridData(IncludeReleasedBuilds, ShowSubDependencies, IncludeToolset) + .AsQueryable(); } private void OnCellFocus(FluentDataGridCell cell) diff --git a/src/ProductConstructionService/ProductConstructionService.Cli/Operations/DeploymentOperation.cs b/src/ProductConstructionService/ProductConstructionService.Cli/Operations/DeploymentOperation.cs index 96be626e87..870c36d03f 100644 --- a/src/ProductConstructionService/ProductConstructionService.Cli/Operations/DeploymentOperation.cs +++ b/src/ProductConstructionService/ProductConstructionService.Cli/Operations/DeploymentOperation.cs @@ -44,7 +44,7 @@ public DeploymentOperation( "--name", _options.ContainerAppName, "--resource-group", _options.ResourceGroupName, ]; - private readonly RevisionRunningState RunningAtMaxScaleState = new RevisionRunningState("RunningAtMaxScale"); + private readonly RevisionRunningState _runningAtMaxScaleState = new("RunningAtMaxScale"); public async Task RunAsync() { @@ -76,8 +76,8 @@ public async Task RunAsync() // Cleanup all revisions except the currently active one await CleanupRevisionsAsync(trafficWeights.Where(weight => weight != activeRevisionTrafficWeight)); - // Tell the active revision to finish current work items and stop processing new ones - await StopProcessingNewJobs(activeRevisionTrafficWeight.RevisionName); + // Finish current work items and stop processing new ones + await StopProcessingNewJobs(); } var newRevisionName = $"{_options.ContainerAppName}--{_options.NewImageTag}"; @@ -195,10 +195,10 @@ private async Task WaitForRevisionToBecomeActive(string revisionName) status = revision.Data.RunningState ?? RevisionRunningState.Unknown; } while (await Utility.SleepIfTrue( - () => status != RunningAtMaxScaleState && status != RevisionRunningState.Failed, + () => status != _runningAtMaxScaleState && status != RevisionRunningState.Failed, SleepTimeSeconds)); - return status == RunningAtMaxScaleState; + return status == _runningAtMaxScaleState; } private async Task AssignLabelAndTransferTraffic(string revisionName, string label) @@ -238,10 +238,10 @@ private async Task DeactivateFailedRevisionAndGetLogs(string revisionName) { await DeactivateRevision(revisionName); - _logger.LogInformation("Check revision logs too see failure reason: {logsUri}", GetLogsUri(revisionName)); + _logger.LogInformation("Check logs too see failure reason: {logsUri}", GetLogsUri()); } - private string GetLogsUri(string revisionName) + private string GetLogsUri() { var query = """ ContainerAppConsoleLogs_CL ` @@ -266,7 +266,7 @@ private async Task InvokeAzCLI(string[] command, string[ workingDir: Path.GetDirectoryName(_options.AzCliPath)); } - private async Task StopProcessingNewJobs(string activeRevisionName) + private async Task StopProcessingNewJobs() { _logger.LogInformation("Stopping the service from processing new jobs"); diff --git a/src/ProductConstructionService/ProductConstructionService.Client/Generated/AzDo.cs b/src/ProductConstructionService/ProductConstructionService.Client/Generated/AzDo.cs index 6b91872ec6..2aef62c493 100644 --- a/src/ProductConstructionService/ProductConstructionService.Client/Generated/AzDo.cs +++ b/src/ProductConstructionService/ProductConstructionService.Client/Generated/AzDo.cs @@ -80,7 +80,7 @@ public AzDo(ProductConstructionServiceApi client) "/api/azdo/build/status/{account}/{project}/{definitionId}/{branch}".Replace("{account}", Uri.EscapeDataString(Client.Serialize(account))).Replace("{project}", Uri.EscapeDataString(Client.Serialize(project))).Replace("{definitionId}", Uri.EscapeDataString(Client.Serialize(definitionId))).Replace("{branch}", Uri.EscapeDataString(Client.Serialize(branch))), false); - if (count != default(int)) + if (count != default) { _url.AppendQuery("count", Client.Serialize(count)); } diff --git a/src/ProductConstructionService/ProductConstructionService.Client/Generated/ProductConstructionServiceApi.cs b/src/ProductConstructionService/ProductConstructionService.Client/Generated/ProductConstructionServiceApi.cs index 45903e8be8..f85954d6dc 100644 --- a/src/ProductConstructionService/ProductConstructionService.Client/Generated/ProductConstructionServiceApi.cs +++ b/src/ProductConstructionService/ProductConstructionService.Client/Generated/ProductConstructionServiceApi.cs @@ -179,7 +179,6 @@ internal void OnFailedRequest(RestApiException ex) partial void HandleFailedRequest(RestApiException ex); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public string Serialize(string value) { diff --git a/src/ProductConstructionService/ProductConstructionService.Client/GlobalSuppressions.cs b/src/ProductConstructionService/ProductConstructionService.Client/GlobalSuppressions.cs new file mode 100644 index 0000000000..12ad617984 --- /dev/null +++ b/src/ProductConstructionService/ProductConstructionService.Client/GlobalSuppressions.cs @@ -0,0 +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.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Style", "IDE0130:Namespace does not match folder structure", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:ProductConstructionService.Client")] +[assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Auto-generate code", Scope = "namespaceanddescendants", Target = "~N:ProductConstructionService.Client")] diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestBuilder.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestBuilder.cs index 4e33e91e0c..a6c18beb2c 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestBuilder.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestBuilder.cs @@ -6,6 +6,8 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using ProductConstructionService.DependencyFlow.WorkItems; diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestPolicyFailureNotifier.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestPolicyFailureNotifier.cs index c932cecf5a..b8055bf539 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestPolicyFailureNotifier.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestPolicyFailureNotifier.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.Extensions.Logging; diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs index 79b644caad..00eab5209a 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdater.cs @@ -1,13 +1,14 @@ // 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; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging; using ProductConstructionService.Common; @@ -319,9 +320,14 @@ private async Task CheckMergePolicyAsync(InProgressPullR { await remote.MergeDependencyPullRequestAsync(pr.Url, new MergePullRequestParameters()); } - catch + catch (PullRequestNotMergeableException notMergeableException) + { + _logger.LogInformation("NOT Merged: PR '{url}' is not mergeable - {message}", pr.Url, notMergeableException.Message); + return MergePolicyCheckResult.FailedToMerge; + } + catch (Exception ex) { - _logger.LogInformation("NOT Merged: PR '{url}' has merge conflicts", pr.Url); + _logger.LogError(ex, "NOT Merged: Failed to merge PR '{url}' - {message}", pr.Url, ex.Message); return MergePolicyCheckResult.FailedToMerge; } @@ -988,18 +994,16 @@ private async Task UpdateAssetsAndSources(SubscriptionUpdateWorkItem updat { targetRepo = _vmrInfo.VmrPath; hadUpdates = await _vmrForwardFlower.FlowForwardAsync( - subscription.TargetDirectory!, + subscription, build, - subscription.TargetBranch, pullRequest.HeadBranch, cancellationToken: default); } else { (hadUpdates, targetRepo) = await _vmrBackFlower.FlowBackAsync( - subscription.SourceDirectory!, + subscription, build, - subscription.TargetBranch, pullRequest.HeadBranch, cancellationToken: default); } @@ -1105,18 +1109,16 @@ private async Task UpdateAssetsAndSources(SubscriptionUpdateWorkItem updat { targetRepo = _vmrInfo.VmrPath; hadUpdates = await _vmrForwardFlower.FlowForwardAsync( - subscription.TargetDirectory!, + subscription, build, - subscription.TargetBranch, newBranchName, cancellationToken: default); } else { (hadUpdates, targetRepo) = await _vmrBackFlower.FlowBackAsync( - subscription.SourceDirectory!, + subscription, build, - subscription.TargetBranch, newBranchName, cancellationToken: default); } diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdaterId.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdaterId.cs index 2ec90312ef..b465d5b877 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdaterId.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/PullRequestUpdaterId.cs @@ -63,7 +63,7 @@ public static PullRequestUpdaterId Parse(string id) return new NonBatchedPullRequestUpdaterId(guid); } - var colonIndex = id.IndexOf(":", StringComparison.Ordinal); + var colonIndex = id.IndexOf(':'); if (colonIndex == -1) { throw new ArgumentException("Updater ID not in correct format", nameof(id)); diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/SubscriptionTriggerer.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/SubscriptionTriggerer.cs index 878ad6b25b..a0ecde3705 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/SubscriptionTriggerer.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/SubscriptionTriggerer.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Threading; using Maestro.Contracts; using Maestro.Data; using Maestro.Data.Models; diff --git a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/WorkItemProcessors/BuildCoherencyInfoProcessor.cs b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/WorkItemProcessors/BuildCoherencyInfoProcessor.cs index 04cbc2fbf8..19a4040492 100644 --- a/src/ProductConstructionService/ProductConstructionService.DependencyFlow/WorkItemProcessors/BuildCoherencyInfoProcessor.cs +++ b/src/ProductConstructionService/ProductConstructionService.DependencyFlow/WorkItemProcessors/BuildCoherencyInfoProcessor.cs @@ -3,6 +3,7 @@ using Maestro.Data; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; using ProductConstructionService.DependencyFlow.WorkItems; using ProductConstructionService.WorkItems; diff --git a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleaner.cs b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleaner.cs index ae6c91faeb..67ce53f043 100644 --- a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleaner.cs +++ b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleaner.cs @@ -6,6 +6,7 @@ using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; diff --git a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleanerJob.cs b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleanerJob.cs index 8f4e8581fd..aedc162f3c 100644 --- a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleanerJob.cs +++ b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/FeedCleanerJob.cs @@ -5,6 +5,7 @@ using Kusto.Cloud.Platform.Utils; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/appsettings.json b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/appsettings.json index 52d5401147..0faab75ec4 100644 --- a/src/ProductConstructionService/ProductConstructionService.FeedCleaner/appsettings.json +++ b/src/ProductConstructionService/ProductConstructionService.FeedCleaner/appsettings.json @@ -1,4 +1,11 @@ { + "Logging": { + "LogLevel": { + "Default": "Information", + "Azure.Core": "Warning", + "Azure.Identity": "Warning" + } + }, "FeedCleaner": { "Enabled": false, "ReleasePackageFeeds": [ diff --git a/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/LongestBuildPathUpdater.cs b/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/LongestBuildPathUpdater.cs index f55c1a5c52..0c7e3db765 100644 --- a/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/LongestBuildPathUpdater.cs +++ b/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/LongestBuildPathUpdater.cs @@ -4,6 +4,7 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging; namespace ProductConstructionService.LongestBuildPathUpdater; @@ -46,7 +47,7 @@ public async Task UpdateLongestBuildPathAsync() .Where(n => n.OnLongestBuildPath) .OrderByDescending(n => n.BestCasePathTime)]; - if (longestBuildPathNodes.Any()) + if (longestBuildPathNodes.Count != 0) { var lbp = new LongestBuildPath() { diff --git a/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/appsettings.json b/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/appsettings.json index 0967ef424b..9f366f78e9 100644 --- a/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/appsettings.json +++ b/src/ProductConstructionService/ProductConstructionService.LongestBuildPathUpdater/appsettings.json @@ -1 +1,9 @@ -{} +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Azure.Core": "Warning", + "Azure.Identity": "Warning" + } + } +} diff --git a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/Program.cs b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/Program.cs index 8701288878..3eb6c4d24f 100644 --- a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/Program.cs +++ b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/Program.cs @@ -9,7 +9,7 @@ using ProductConstructionService.SubscriptionTriggerer; using ProductConstructionService.WorkItems; -if (args.Count() < 1) +if (args.Length < 1) { Console.WriteLine("Usage: SubscriptionTriggerer "); return 1; diff --git a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggerer.cs b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggerer.cs index ce81a891d6..85482e9aed 100644 --- a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggerer.cs +++ b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggerer.cs @@ -4,7 +4,6 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ProductConstructionService.DependencyFlow.WorkItems; using ProductConstructionService.WorkItems; @@ -44,7 +43,7 @@ await _workItemProducerFactory.CreateProducer(updat private async Task> GetSubscriptionsToTrigger(UpdateFrequency targetUpdateFrequency) { - List<(bool, SubscriptionTriggerWorkItem)> subscriptionsToTrigger = new(); + List<(bool, SubscriptionTriggerWorkItem)> subscriptionsToTrigger = []; var enabledSubscriptionsWithTargetFrequency = (await _context.Subscriptions .Where(s => s.Enabled) diff --git a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggererConfiguration.cs b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggererConfiguration.cs index 675c594832..d5d754512f 100644 --- a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggererConfiguration.cs +++ b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/SubscriptionTriggererConfiguration.cs @@ -4,7 +4,6 @@ using Maestro.DataProviders; using Microsoft.ApplicationInsights.Channel; using Microsoft.DotNet.DarcLib.Helpers; -using Microsoft.DotNet.DarcLib; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ProductConstructionService.Common; diff --git a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/appsettings.json b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/appsettings.json index fd21f047dc..ac7a4d2311 100644 --- a/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/appsettings.json +++ b/src/ProductConstructionService/ProductConstructionService.SubscriptionTriggerer/appsettings.json @@ -1,4 +1,11 @@ { + "Logging": { + "LogLevel": { + "Default": "Information", + "Azure.Core": "Warning", + "Azure.Identity": "Warning" + } + }, "DefaultWorkItemQueueName": "pcs-workitems", "CodeflowWorkItemQueueName": "pcs-codeflow-workitems" } diff --git a/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManager.cs b/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManager.cs index 1a925a8594..5449e62fea 100644 --- a/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManager.cs +++ b/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManager.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Azure; -using Microsoft.Extensions.DependencyInjection; using ProductConstructionService.Common; namespace ProductConstructionService.WorkItems; diff --git a/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManagerFactory.cs b/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManagerFactory.cs index f80b325de3..b139f04838 100644 --- a/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManagerFactory.cs +++ b/src/ProductConstructionService/ProductConstructionService.WorkItems/ReminderManagerFactory.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Extensions.DependencyInjection; using ProductConstructionService.Common; namespace ProductConstructionService.WorkItems; diff --git a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorRegistrations.cs b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorRegistrations.cs index b77885b569..f6f8d690b0 100644 --- a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorRegistrations.cs +++ b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorRegistrations.cs @@ -5,7 +5,7 @@ namespace ProductConstructionService.WorkItems; internal class WorkItemProcessorRegistrations { - private readonly Dictionary _processors = new(); + private readonly Dictionary _processors = []; public void RegisterProcessor() where TWorkItem : WorkItem diff --git a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorStateCache.cs b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorStateCache.cs index a013fb2619..3dd493c4fd 100644 --- a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorStateCache.cs +++ b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemProcessorStateCache.cs @@ -13,7 +13,7 @@ public class WorkItemProcessorStateCache private readonly ILogger _logger; // After 60 days the replica will be inactive for sure, so we can clean the state - private static TimeSpan StateExpirationTime = TimeSpan.FromDays(60); + private static readonly TimeSpan StateExpirationTime = TimeSpan.FromDays(60); public WorkItemProcessorStateCache(IRedisCacheFactory redisCacheFactory, string replicaName, ILogger logger) { diff --git a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemScope.cs b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemScope.cs index e35642aadd..bfb56add63 100644 --- a/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemScope.cs +++ b/src/ProductConstructionService/ProductConstructionService.WorkItems/WorkItemScope.cs @@ -32,11 +32,6 @@ internal WorkItemScope( _telemetryRecorder = telemetryRecorder; } - public void Dispose() - { - DisposeAsync().GetAwaiter().GetResult(); - } - public async ValueTask DisposeAsync() { await _finalizer(); diff --git a/test/DependencyUpdater.Tests/UpdateLongestBuildPathTests.cs b/test/DependencyUpdater.Tests/UpdateLongestBuildPathTests.cs index 0e9671c9d2..3f93211dca 100644 --- a/test/DependencyUpdater.Tests/UpdateLongestBuildPathTests.cs +++ b/test/DependencyUpdater.Tests/UpdateLongestBuildPathTests.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using FluentAssertions; using Maestro.Data.Models; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; diff --git a/test/FeedCleaner.Tests/FeedCleanerServiceTests.cs b/test/FeedCleaner.Tests/FeedCleanerServiceTests.cs index 13d92defd7..af3b8a4f18 100644 --- a/test/FeedCleaner.Tests/FeedCleanerServiceTests.cs +++ b/test/FeedCleaner.Tests/FeedCleanerServiceTests.cs @@ -10,6 +10,7 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/test/Maestro.ScenarioTests/EndToEndFlowLogic.cs b/test/Maestro.ScenarioTests/EndToEndFlowLogic.cs index 0e04feed84..ee53d83f99 100644 --- a/test/Maestro.ScenarioTests/EndToEndFlowLogic.cs +++ b/test/Maestro.ScenarioTests/EndToEndFlowLogic.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; diff --git a/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs b/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs index ff19de102f..9548b494fc 100644 --- a/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs +++ b/test/Maestro.ScenarioTests/MaestroScenarioTestBase.cs @@ -15,6 +15,9 @@ using Maestro.MergePolicyEvaluation; using Maestro.ScenarioTests.ObjectHelpers; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Internal.Testing.Utility; using Microsoft.DotNet.Maestro.Client; using Microsoft.DotNet.Maestro.Client.Models; diff --git a/test/Maestro.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs b/test/Maestro.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs index c07e2cd374..4d20745901 100644 --- a/test/Maestro.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs +++ b/test/Maestro.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Text; -using Microsoft.DotNet.Darc; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.Darc.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace Maestro.ScenarioTests.ObjectHelpers; @@ -14,7 +14,7 @@ internal static string GetString(List expectedDependencies) { StringBuilder stringBuilder = new StringBuilder(); - foreach(DependencyDetail dependency in expectedDependencies) + foreach (DependencyDetail dependency in expectedDependencies) { stringBuilder.AppendLine(UxHelpers.DependencyToString(dependency)); } diff --git a/test/Maestro.ScenarioTests/ScenarioTests_AzDoFlow.cs b/test/Maestro.ScenarioTests/ScenarioTests_AzDoFlow.cs index fe5d4bec35..809a5a6b04 100644 --- a/test/Maestro.ScenarioTests/ScenarioTests_AzDoFlow.cs +++ b/test/Maestro.ScenarioTests/ScenarioTests_AzDoFlow.cs @@ -1,12 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; diff --git a/test/Maestro.ScenarioTests/ScenarioTests_DefaultChannels.cs b/test/Maestro.ScenarioTests/ScenarioTests_DefaultChannels.cs index 79af4960e1..ac8ad5c05f 100644 --- a/test/Maestro.ScenarioTests/ScenarioTests_DefaultChannels.cs +++ b/test/Maestro.ScenarioTests/ScenarioTests_DefaultChannels.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Threading.Tasks; using FluentAssertions; using NUnit.Framework; diff --git a/test/Maestro.ScenarioTests/ScenarioTests_GitHubFlow.cs b/test/Maestro.ScenarioTests/ScenarioTests_GitHubFlow.cs index ab11e1594d..681daf4925 100644 --- a/test/Maestro.ScenarioTests/ScenarioTests_GitHubFlow.cs +++ b/test/Maestro.ScenarioTests/ScenarioTests_GitHubFlow.cs @@ -1,12 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; using NUnit.Framework.Internal; diff --git a/test/Maestro.ScenarioTests/ScenarioTests_SdkUpdate.cs b/test/Maestro.ScenarioTests/ScenarioTests_SdkUpdate.cs index 66dca15b9b..8184028eb5 100644 --- a/test/Maestro.ScenarioTests/ScenarioTests_SdkUpdate.cs +++ b/test/Maestro.ScenarioTests/ScenarioTests_SdkUpdate.cs @@ -7,7 +7,8 @@ using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; diff --git a/test/Maestro.ScenarioTests/ScenarioTests_Subscriptions.cs b/test/Maestro.ScenarioTests/ScenarioTests_Subscriptions.cs index 5619ec2abf..ce381fd03f 100644 --- a/test/Maestro.ScenarioTests/ScenarioTests_Subscriptions.cs +++ b/test/Maestro.ScenarioTests/ScenarioTests_Subscriptions.cs @@ -1,12 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Threading.Tasks; using FluentAssertions; using Maestro.MergePolicyEvaluation; using Maestro.ScenarioTests.ObjectHelpers; -using Microsoft.DotNet.Darc; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; using NUnit.Framework.Internal; diff --git a/test/Maestro.Web.Tests/SubscriptionsController20200220Tests.cs b/test/Maestro.Web.Tests/SubscriptionsController20200220Tests.cs index f93fe3bcdd..e2aff09f0e 100644 --- a/test/Maestro.Web.Tests/SubscriptionsController20200220Tests.cs +++ b/test/Maestro.Web.Tests/SubscriptionsController20200220Tests.cs @@ -12,6 +12,7 @@ using Maestro.Web.Api.v2020_02_20.Controllers; using Microsoft.AspNetCore.Mvc; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.DotNet.Internal.Testing.DependencyInjection.Abstractions; using Microsoft.DotNet.Internal.Testing.Utility; diff --git a/test/Microsoft.DotNet.Darc.Tests/DependencyAddUpdateTests.cs b/test/Microsoft.DotNet.Darc.Tests/DependencyAddUpdateTests.cs index 9cb5b17dc9..4db45d1245 100644 --- a/test/Microsoft.DotNet.Darc.Tests/DependencyAddUpdateTests.cs +++ b/test/Microsoft.DotNet.Darc.Tests/DependencyAddUpdateTests.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; namespace Microsoft.DotNet.Darc.Tests; diff --git a/test/Microsoft.DotNet.Darc.Tests/DependencyCoherencyTests.cs b/test/Microsoft.DotNet.Darc.Tests/DependencyCoherencyTests.cs index 2a59356bd5..5e865d4271 100644 --- a/test/Microsoft.DotNet.Darc.Tests/DependencyCoherencyTests.cs +++ b/test/Microsoft.DotNet.Darc.Tests/DependencyCoherencyTests.cs @@ -8,6 +8,8 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -885,10 +887,10 @@ public async Task StrictCoherencyUpdateTests8() AddDependency(repoADeps, depB.Name, "v42", depB.RepoUri, "commit5", pinned: false); RepoHasDependencies(remoteMock, "repoA", "commit1", repoADeps); - BuildProducesAssets(barClientMock, "repoB", "commit5", new List<(string name, string version, string[])> - { + BuildProducesAssets(barClientMock, "repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json" } ) - }); + ]); List coherencyUpdates = await resolver.GetRequiredCoherencyUpdatesAsync(existingDetails, remoteFactoryMock.Object); @@ -935,13 +937,13 @@ public async Task StrictCoherencyUpdateTests9() AddDependency(repoADeps, depB.Name, "v42", depB.RepoUri, "commit5", pinned: false); RepoHasDependencies(remoteMock, "repoA", "commit1", repoADeps); - BuildProducesAssets(barClientMock, "repoB", "commit5", new List<(string name, string version, string[])> - { + BuildProducesAssets(barClientMock, "repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }); + ]); List coherencyUpdates = await resolver.GetRequiredCoherencyUpdatesAsync(existingDetails, remoteFactoryMock.Object); @@ -996,18 +998,18 @@ public async Task StrictCoherencyUpdateTests10() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }, 13), + ], 13), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", null ) - }, 1) + ], 1) }); // Repo has no feeds @@ -1016,21 +1018,16 @@ public async Task StrictCoherencyUpdateTests10() List coherencyUpdates = await resolver.GetRequiredCoherencyUpdatesAsync(existingDetails, remoteFactoryMock.Object); - coherencyUpdates.Should().SatisfyRespectively( u => + coherencyUpdates.Should().SatisfyRespectively(u => { u.From.Should().Be(depB); u.To.Version.Should().Be("v42"); u.To.Commit.Should().Be("commit5"); u.To.RepoUri.Should().Be(depB.RepoUri); u.To.Name.Should().Be(depB.Name); - u.To.Locations.Should().SatisfyRespectively( u => - { - u.Should().Be("https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json"); - }, u => - { - u.Should().Be("https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json"); - } - ); + u.To.Locations.Should().SatisfyRespectively( + u => u.Should().Be("https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json"), + u => u.Should().Be("https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json")); }); } @@ -1068,17 +1065,17 @@ public async Task StrictCoherencyUpdateTests11() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", null ) - }), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + ]), + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }) + ]) }); List coherencyUpdates = @@ -1134,20 +1131,20 @@ public async Task StrictCoherencyUpdateTests12() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core2/index.json" } ) - }, 11), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + ], 11), + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }, 10) + ], 10) }); RepositoryHasFeeds(gitRepoMock, "repoA", "commit1", @@ -1207,20 +1204,20 @@ public async Task StrictCoherencyUpdateTests13() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet566/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core2/index.json" } ) - }, 10), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + ], 10), + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }, 11) + ], 11) }); RepositoryHasFeeds(gitRepoMock, "repoA", "commit1", @@ -1280,20 +1277,20 @@ public async Task StrictCoherencyUpdateTests14() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet566/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core2/index.json" } ) - }, 10), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + ], 10), + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet566/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }, 11) + ], 11) }); RepositoryHasFeeds(gitRepoMock, "repoA", "commit1", @@ -1347,7 +1344,7 @@ public async Task StrictCoherencyUpdateTests15() AddDependency(repoADeps, depB.Name, "v42", depB.RepoUri, "commit5", pinned: false); RepoHasDependencies(remoteMock, "repoA", "commit1", repoADeps); - BuildProducesAssets(barClientMock, "repoB", "commit5", new List<(string name, string version, string[])> {}); + BuildProducesAssets(barClientMock, "repoB", "commit5", []); List coherencyUpdates = await resolver.GetRequiredCoherencyUpdatesAsync(existingDetails, remoteFactoryMock.Object); @@ -1393,18 +1390,18 @@ public async Task StrictCoherencyUpdateTests16() RepoHadBuilds(barClientMock, "repoB", "commit5", new List { - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v42", new string[] { "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json", "https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" } ) - }, 13), + ], 13), - CreateBuild("repoB", "commit5", new List<(string name, string version, string[])> - { + CreateBuild("repoB", "commit5", + [ ("depB", "v43", null ) - }, 1) + ], 1) }); // Repo has no feeds diff --git a/test/Microsoft.DotNet.Darc.Tests/DependencyFileManagerTests.cs b/test/Microsoft.DotNet.Darc.Tests/DependencyFileManagerTests.cs index b1ec1eb5ea..ae1a2e5cc5 100644 --- a/test/Microsoft.DotNet.Darc.Tests/DependencyFileManagerTests.cs +++ b/test/Microsoft.DotNet.Darc.Tests/DependencyFileManagerTests.cs @@ -8,6 +8,7 @@ using System.Xml; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.Extensions.Logging.Abstractions; using NUnit.Framework; diff --git a/test/Microsoft.DotNet.Darc.Tests/DependencyFlowTestDriver.cs b/test/Microsoft.DotNet.Darc.Tests/DependencyFlowTestDriver.cs index a85ac07adb..c42ee8a9d6 100644 --- a/test/Microsoft.DotNet.Darc.Tests/DependencyFlowTestDriver.cs +++ b/test/Microsoft.DotNet.Darc.Tests/DependencyFlowTestDriver.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using FluentAssertions; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Newtonsoft.Json; namespace Microsoft.DotNet.Darc.Tests; diff --git a/test/Microsoft.DotNet.Darc.Tests/DependencyTestDriver.cs b/test/Microsoft.DotNet.Darc.Tests/DependencyTestDriver.cs index 334413c30b..c02769a35b 100644 --- a/test/Microsoft.DotNet.Darc.Tests/DependencyTestDriver.cs +++ b/test/Microsoft.DotNet.Darc.Tests/DependencyTestDriver.cs @@ -10,6 +10,7 @@ using FluentAssertions; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.Extensions.Logging.Abstractions; using NuGet.Versioning; diff --git a/test/Microsoft.DotNet.Darc.Tests/Operations/GetBuildOperationTests.cs b/test/Microsoft.DotNet.Darc.Tests/Operations/GetBuildOperationTests.cs index dd62e9fbb7..d1721b4254 100644 --- a/test/Microsoft.DotNet.Darc.Tests/Operations/GetBuildOperationTests.cs +++ b/test/Microsoft.DotNet.Darc.Tests/Operations/GetBuildOperationTests.cs @@ -4,6 +4,7 @@ #nullable enable using FluentAssertions; +using Microsoft.DotNet.Darc.Helpers; using Microsoft.DotNet.Darc.Operations; using Microsoft.DotNet.Darc.Options; using Microsoft.DotNet.Darc.Tests.Helpers; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/Constants.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/Constants.cs index beecbe5385..5adf355848 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/Constants.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/Constants.cs @@ -57,6 +57,7 @@ public class Constants public const string ProductRepoName = "product-repo1"; public const string DependencyRepoName = "dependency"; public const string SecondRepoName = "product-repo2"; + public const string SyncDisabledRepoName = "sync-disabled-repo"; public const string InstallerRepoName = "installer"; public const string VmrName = "vmr"; public const string TmpFolderName = "tmp"; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/LoadSourceMappingsFromInstallerTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/LoadSourceMappingsFromInstallerTest.cs index c2a34b88c2..2352d37642 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/LoadSourceMappingsFromInstallerTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/LoadSourceMappingsFromInstallerTest.cs @@ -5,7 +5,6 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrBackflowTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrBackflowTest.cs index 568a83bdc3..41b97a9c8e 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrBackflowTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrBackflowTest.cs @@ -6,8 +6,8 @@ using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Newtonsoft.Json.Linq; using NUnit.Framework; @@ -42,6 +42,7 @@ public async Task OnlyBackflowsTest() CheckFileContents(_productRepoFilePath, "New content from the VMR again"); // Make an additional change in the PR branch before merging + await GitOperations.Checkout(ProductRepoPath, branchName); await File.WriteAllTextAsync(_productRepoFilePath, "Change that happened in the PR"); await GitOperations.CommitAll(ProductRepoPath, "Extra commit in the PR"); await GitOperations.MergePrBranch(ProductRepoPath, branchName); @@ -59,6 +60,7 @@ await GitOperations.VerifyMergeConflict(ProductRepoPath, branchName, hadUpdates.ShouldHaveUpdates(); await GitOperations.MergePrBranch(VmrPath, branchName); CheckFileContents(_productRepoVmrFilePath, "A completely different change"); + } [Test] @@ -121,26 +123,22 @@ await File.WriteAllTextAsync(ProductRepoPath / VersionFiles.VersionProps, - <{VersionFiles.GetVersionPropsPackageVersionElementName(DependencyFileManager.ArcadeSdkPackageName)}>1.0.0 - 1.0.0 1.0.0 - 1.0.0 - 1.0.0 @@ -175,7 +173,12 @@ await File.WriteAllTextAsync(ProductRepoPath / VersionFiles.VersionProps, ]); // Flow changes back from the VMR - hadUpdates = await CallDarcBackflow(Constants.ProductRepoName, ProductRepoPath, branchName + "-backflow", buildToFlow: build1.Id); + hadUpdates = await CallDarcBackflow( + Constants.ProductRepoName, + ProductRepoPath, + branchName + "-backflow", + buildToFlow: build1.Id, + excludedAssets: ["Package.C2"]); hadUpdates.ShouldHaveUpdates(); await GitOperations.MergePrBranch(ProductRepoPath, branchName + "-backflow"); @@ -188,7 +191,19 @@ .. GetExpectedVersionFiles(ProductRepoPath), CheckDirectoryContents(ProductRepoPath, expectedFiles); // Verify the version files have both of the changes - List expectedDependencies = GetDependencies(build1); + List expectedDependencies = + [ + ..GetDependencies(build1).Where(a => a.Name != "Package.C2"), // C2 is excluded + new DependencyDetail + { + Name = "Package.C2", + Version = "1.0.0", + RepoUri = "https://github.com/dotnet/repo2", + Commit = "c03", + Type = DependencyType.Product, + Pinned = false, + }, + ]; var productRepo = GetLocal(ProductRepoPath); @@ -293,7 +308,7 @@ .. GetExpectedVersionFiles(ProductRepoPath), await GitOperations.MergePrBranch(VmrPath, branchName + "-ff"); // Now we will change something in the VMR and flow it back to the repo - // Then we will change something in the VMR again but before we flow it back, we will update the repo package versions by running update-dependencies + // Then we will change something in the VMR again but before we flow it back, we will make a conflicting change in the VMR await File.WriteAllTextAsync(_productRepoVmrFilePath, "New content again in the VMR #1"); await GitOperations.CommitAll(VmrPath, "Changing a VMR file again #1"); @@ -305,8 +320,6 @@ .. GetExpectedVersionFiles(ProductRepoPath), ("Package.D3", "1.0.5"), ]); - // Now we will change something in the VMR and flow it back to the repo - // Then we will change something in the VMR again but before we flow it back, we will change the PR branch so that there's a conflict await File.WriteAllTextAsync(_productRepoVmrFilePath, "New content again in the VMR #2"); await GitOperations.CommitAll(VmrPath, "Changing a VMR file again #2"); @@ -341,13 +354,18 @@ .. GetExpectedVersionFiles(ProductRepoPath), dependencies.Should().BeEquivalentTo(expectedDependencies); // We make a conflicting change in the PR branch - // TODO + await File.WriteAllTextAsync(_productRepoFilePath, "New content again but this time in the PR directly"); + await GitOperations.CommitAll(ProductRepoPath, "Changing a repo file in the PR"); - // Flow the second build - hadUpdates = await CallDarcBackflow(Constants.ProductRepoName, ProductRepoPath, branchName + "-pr2", buildToFlow: build5.Id); - hadUpdates.ShouldHaveUpdates(); + // Flow the second build - this should throw as there's a conflict in the PR branch + await this.Awaiting(_ => CallDarcBackflow(Constants.ProductRepoName, ProductRepoPath, branchName + "-pr2", buildToFlow: build5.Id)) + .Should().ThrowAsync(); + + // The state of the branch should be the same as before + productRepo.Checkout(branchName + "-pr2"); dependencies = await productRepo.GetDependenciesAsync(); - dependencies.Should().BeEquivalentTo(GetDependencies(build5)); + dependencies.Should().BeEquivalentTo(expectedDependencies); + CheckFileContents(_productRepoFilePath, "New content again but this time in the PR directly"); } } diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrCodeFlowTests.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrCodeFlowTests.cs index 6ea2f9f2f4..aac7c38d65 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrCodeFlowTests.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrCodeFlowTests.cs @@ -10,6 +10,7 @@ using FluentAssertions; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.DotNet.Maestro.Client.Models; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrForwardFlowTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrForwardFlowTest.cs index 6a0cea5eb3..802834886c 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrForwardFlowTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrForwardFlowTest.cs @@ -5,8 +5,9 @@ using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using NUnit.Framework; @@ -82,25 +83,59 @@ await GetLocal(VmrPath).AddDependencyAsync(new DependencyDetail await File.WriteAllTextAsync(_productRepoFilePath, "New content in the repository"); await GitOperations.CommitAll(ProductRepoPath, "Changing a repo file"); - var build = await CreateNewRepoBuild( + var build1 = await CreateNewRepoBuild( [ ("Package.A1", "1.0.1"), ]); - var hadUpdates = await CallDarcForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: build.Id); + var hadUpdates = await CallDarcForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: build1.Id); hadUpdates.ShouldHaveUpdates(); await GitOperations.MergePrBranch(VmrPath, branchName); // Verify that VMR's version files have the new versions - var vmrVersionDetails = new VersionDetailsParser() - .ParseVersionDetailsFile(VmrPath / VersionFiles.VersionDetailsXml); - - vmrVersionDetails.Dependencies.Where(d => d.Name != DependencyFileManager.ArcadeSdkPackageName) - .Should().BeEquivalentTo(GetDependencies(build)); + var vmr = GetLocal(VmrPath); + var dependencies = await vmr.GetDependenciesAsync(); + dependencies.Where(d => d.Name != DependencyFileManager.ArcadeSdkPackageName) + .Should().BeEquivalentTo(GetDependencies(build1)); var propName = VersionFiles.GetVersionPropsPackageVersionElementName("Package.A1"); var vmrVersionProps = AllVersionsPropsFile.DeserializeFromXml(VmrPath / VersionFiles.VersionProps); vmrVersionProps.Versions[propName].Should().Be("1.0.1"); + + // Now we will change something in the repo and flow it to the VMR + // Then we will change something in the repo again but before we flow it, we will make a conflicting change in the PR branch + await File.WriteAllTextAsync(_productRepoFilePath, "New content again in the repo #1"); + await GitOperations.CommitAll(ProductRepoPath, "Changing a repo file again #1"); + + var build2 = await CreateNewRepoBuild( + [ + ("Package.A1", "1.0.5"), + ]); + + await File.WriteAllTextAsync(_productRepoFilePath, "New content again in the repo #2"); + await GitOperations.CommitAll(ProductRepoPath, "Changing a repo file again #2"); + + var build3 = await CreateNewRepoBuild( + [ + ("Package.A1", "1.0.6"), + ]); + + // Flow the first build + hadUpdates = await CallDarcForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: build2.Id); + hadUpdates.ShouldHaveUpdates(); + + // We make a conflicting change in the PR branch + await GitOperations.Checkout(VmrPath, branchName); + await File.WriteAllTextAsync(_productRepoVmrFilePath, "New content again but this time in the PR directly"); + await GitOperations.CommitAll(VmrPath, "Changing a file in the PR"); + + // Flow the second build - this should throw as there's a conflict in the PR branch + await this.Awaiting(_ => CallDarcForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: build3.Id)) + .Should().ThrowAsync(); + + // The state of the branch should be the same as before + vmr.Checkout(branchName); + CheckFileContents(_productRepoVmrFilePath, "New content again but this time in the PR directly"); } } diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrMultipleRemotesTests.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrMultipleRemotesTests.cs index 92de1b184f..8985b926b2 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrMultipleRemotesTests.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrMultipleRemotesTests.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRecursiveSyncTests.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRecursiveSyncTests.cs index 251bb7d6a2..a2b954a2b6 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRecursiveSyncTests.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRecursiveSyncTests.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; @@ -23,6 +22,7 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() var firstRepoFilePath = vmrSourcesDir / Constants.ProductRepoName / Constants.GetRepoFileName(Constants.ProductRepoName); var secondRepoFilePath = vmrSourcesDir / Constants.SecondRepoName / Constants.GetRepoFileName(Constants.SecondRepoName); var dependencyFilePath = vmrSourcesDir / Constants.DependencyRepoName / Constants.GetRepoFileName(Constants.DependencyRepoName); + var syncDisabledRepoFilePath = vmrSourcesDir / Constants.SyncDisabledRepoName / Constants.GetRepoFileName(Constants.SyncDisabledRepoName); /* * The dependency tree looks like: @@ -44,6 +44,7 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() firstRepoFilePath, secondRepoFilePath, dependencyFilePath, + syncDisabledRepoFilePath }; var expectedFiles = GetExpectedFilesInVmr( @@ -52,7 +53,8 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() Constants.InstallerRepoName, Constants.ProductRepoName, Constants.SecondRepoName, - Constants.DependencyRepoName + Constants.DependencyRepoName, + Constants.SyncDisabledRepoName ], expectedFilesFromRepos); @@ -79,10 +81,18 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() "New version of product-repo2 file"); await GitOperations.CommitAll(SecondRepoPath, "update version details"); + // Update the SyncDisabled repo with a new version, save the old content to compare first + var syncDisabledRepoFileContent = File.ReadAllText(SyncDisabledRepoPath / Constants.GetRepoFileName(Constants.SyncDisabledRepoName)); + File.WriteAllText( + SyncDisabledRepoPath / Constants.GetRepoFileName(Constants.SyncDisabledRepoName), + "New version that shouldn't get synced into the vmr"); + await GitOperations.CommitAll(SyncDisabledRepoPath, "change the file in syncDisabled repo"); + // Update installers Version.Details var newSecondRepoSha = await GitOperations.GetRepoLastCommit(SecondRepoPath); var productRepoSha = await GitOperations.GetRepoLastCommit(ProductRepoPath); + var syncDisabledRepoSha = await GitOperations.GetRepoLastCommit(SyncDisabledRepoPath); var productRepoDependency = string.Format( Constants.DependencyTemplate, Constants.ProductRepoName, ProductRepoPath, productRepoSha); @@ -91,9 +101,13 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() Constants.DependencyTemplate, Constants.SecondRepoName, SecondRepoPath, newSecondRepoSha); + var syncDisabledRepoDependency = string.Format( + Constants.DependencyTemplate, + Constants.SyncDisabledRepoName, SyncDisabledRepoPath, syncDisabledRepoSha); + versionDetails = string.Format( Constants.VersionDetailsTemplate, - productRepoDependency + Environment.NewLine + secondRepoDependency); + productRepoDependency + Environment.NewLine + secondRepoDependency + Environment.NewLine + syncDisabledRepoDependency); File.WriteAllText(InstallerRepoPath / VersionFiles.VersionDetailsXml, versionDetails); File.WriteAllText( @@ -120,6 +134,9 @@ public async Task RecursiveUpdatePreservesDependencyVersionTest() // The new version of dependency shouldn't be pulled in the VMR CheckFileContents(dependencyFilePath, "File in dependency"); + + // The new version of the syncDisabled repo shouldn't be pulled in the VMR + CheckFileContents(syncDisabledRepoFilePath, syncDisabledRepoFileContent); } protected override async Task CopyReposForCurrentTest() @@ -130,11 +147,13 @@ protected override async Task CopyReposForCurrentTest() Constants.InstallerRepoName, [ Constants.ProductRepoName, - Constants.SecondRepoName + Constants.SecondRepoName, + Constants.SyncDisabledRepoName ] }, { Constants.ProductRepoName, [Constants.DependencyRepoName] }, { Constants.SecondRepoName, [Constants.DependencyRepoName] }, + { Constants.SyncDisabledRepoName, [] } }; await CopyRepoAndCreateVersionFiles(Constants.InstallerRepoName, dependenciesMap); @@ -167,6 +186,12 @@ protected override async Task CopyVmrForCurrentTest() { Name = Constants.DependencyRepoName, DefaultRemote = DependencyRepoPath + }, + new SourceMappingSetting + { + Name = Constants.SyncDisabledRepoName, + DefaultRemote = SyncDisabledRepoPath, + DisableSynchronization = true } ], PatchesPath = "src/installer/patches/" diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRepoDeletionTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRepoDeletionTest.cs index b2577b4649..ef27c0a37b 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRepoDeletionTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrRepoDeletionTest.cs @@ -7,7 +7,6 @@ using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrSyncRepoChangesTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrSyncRepoChangesTest.cs index 8fd2107ff6..84604b125b 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrSyncRepoChangesTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrSyncRepoChangesTest.cs @@ -5,8 +5,6 @@ using System.IO; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; -using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsBase.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsBase.cs index a89ce62678..f506086136 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsBase.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsBase.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; @@ -30,6 +29,7 @@ internal abstract class VmrTestsBase protected NativePath TmpPath { get; private set; } = null!; protected NativePath SecondRepoPath { get; private set; } = null!; protected NativePath DependencyRepoPath { get; private set; } = null!; + protected NativePath SyncDisabledRepoPath { get; private set; } = null!; protected NativePath InstallerRepoPath { get; private set; } = null!; protected GitOperationsHelper GitOperations { get; } = new(); protected IServiceProvider ServiceProvider { get; private set; } = null!; @@ -49,6 +49,7 @@ public async Task Setup() SecondRepoPath = CurrentTestDirectory / Constants.SecondRepoName; DependencyRepoPath = CurrentTestDirectory / Constants.DependencyRepoName; InstallerRepoPath = CurrentTestDirectory / Constants.InstallerRepoName; + SyncDisabledRepoPath = CurrentTestDirectory / Constants.SyncDisabledRepoName; Directory.CreateDirectory(TmpPath); @@ -184,18 +185,46 @@ protected async Task CallDarcUpdate(string repository, string commit, Additional await vmrUpdater.UpdateRepository(repository, commit, null, true, additionalRemotes, null, null, generateCodeowners, generateCredScanSuppressions, true, _cancellationToken.Token); } - protected async Task CallDarcBackflow(string mappingName, NativePath repoPath, string branch, string? shaToFlow = null, int? buildToFlow = null) + protected async Task CallDarcBackflow( + string mappingName, + NativePath repoPath, + string branch, + string? shaToFlow = null, + int? buildToFlow = null, + IReadOnlyCollection? excludedAssets = null) { using var scope = ServiceProvider.CreateScope(); var codeflower = scope.ServiceProvider.GetRequiredService(); - return await codeflower.FlowBackAsync(mappingName, repoPath, shaToFlow, buildToFlow, "main", branch, cancellationToken: _cancellationToken.Token); + return await codeflower.FlowBackAsync( + mappingName, + repoPath, + shaToFlow, + buildToFlow, + excludedAssets, + "main", + branch, + cancellationToken: _cancellationToken.Token); } - protected async Task CallDarcForwardflow(string mappingName, NativePath repoPath, string branch, string? shaToFlow = null, int? buildToFlow = null) + protected async Task CallDarcForwardflow( + string mappingName, + NativePath repoPath, + string branch, + string? shaToFlow = null, + int? buildToFlow = null, + IReadOnlyCollection? excludedAssets = null) { using var scope = ServiceProvider.CreateScope(); var codeflower = scope.ServiceProvider.GetRequiredService(); - return await codeflower.FlowForwardAsync(mappingName, repoPath, shaToFlow, buildToFlow, "main", branch, cancellationToken: _cancellationToken.Token); + return await codeflower.FlowForwardAsync( + mappingName, + repoPath, + shaToFlow, + buildToFlow, + excludedAssets, + "main", + branch, + cancellationToken: _cancellationToken.Token); } protected async Task> CallDarcCloakedFileScan(string baselinesFilePath) diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsOneTimeSetUp.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsOneTimeSetUp.cs index 2f7db96cc0..8deabaccc7 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsOneTimeSetUp.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTestsOneTimeSetUp.cs @@ -20,6 +20,7 @@ public class VmrTestsOneTimeSetUp public static readonly NativePath CommonDependencyPath; public static readonly NativePath CommonInstallerPath; public static readonly NativePath CommonExternalRepoPath; + public static readonly NativePath CommonSyncDisabledRepoPath; public static readonly NativePath ResourcesPath; private readonly GitOperationsHelper _gitOperations = new(); @@ -34,6 +35,7 @@ static VmrTestsOneTimeSetUp() CommonExternalRepoPath = TestsDirectory / Constants.SecondRepoName; CommonDependencyPath = TestsDirectory / Constants.DependencyRepoName; CommonInstallerPath = TestsDirectory / Constants.InstallerRepoName; + CommonSyncDisabledRepoPath = TestsDirectory / Constants.SyncDisabledRepoName; } [OneTimeSetUp] @@ -49,6 +51,7 @@ public async Task OneTimeSetUp() await CreateRepository(CommonDependencyPath, Constants.DependencyRepoName); await CreateRepository(CommonExternalRepoPath, Constants.SecondRepoName); await CreateRepository(CommonInstallerPath, Constants.InstallerRepoName); + await CreateRepository(CommonSyncDisabledRepoPath, Constants.SyncDisabledRepoName); Directory.CreateDirectory(CommonInstallerPath / Constants.PatchesFolderName / Constants.ProductRepoName); } diff --git a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTwoWayCodeflowTest.cs b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTwoWayCodeflowTest.cs index 32e3a52f01..16ab961a38 100644 --- a/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTwoWayCodeflowTest.cs +++ b/test/Microsoft.DotNet.Darc.VirtualMonoRepo.E2E.Tests/VmrTwoWayCodeflowTest.cs @@ -7,6 +7,7 @@ using FluentAssertions; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.DependencyInjection; using Moq; diff --git a/test/Microsoft.DotNet.DarcLib.Tests/GitHubClientTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/GitHubClientTests.cs index dfdfd646fc..fdf52787ad 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/GitHubClientTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/GitHubClientTests.cs @@ -4,6 +4,7 @@ using FluentAssertions; using Maestro.Common; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.Internal.Testing.Utility; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; diff --git a/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionDetailsParserTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionDetailsParserTests.cs index dc4bc7a9d4..bd6e2c3e33 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionDetailsParserTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionDetailsParserTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; namespace Microsoft.DotNet.DarcLib.Tests.Helpers; diff --git a/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionFileTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionFileTests.cs index 8722c6a926..3115d689ac 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionFileTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/Helpers/VersionFileTests.cs @@ -3,6 +3,7 @@ using System; using FluentAssertions; +using Microsoft.DotNet.DarcLib.Helpers; using NUnit.Framework; namespace Microsoft.DotNet.DarcLib.Tests.Helpers; diff --git a/test/Microsoft.DotNet.DarcLib.Tests/Models/Darc/DependencyFlowNodeTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/Models/Darc/DependencyFlowNodeTests.cs index 8710ca4396..390f1a4029 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/Models/Darc/DependencyFlowNodeTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/Models/Darc/DependencyFlowNodeTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using NUnit.Framework; using System; diff --git a/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/GitInfoFileTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/GitInfoFileTests.cs index e4ffc93196..b26169b210 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/GitInfoFileTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/GitInfoFileTests.cs @@ -4,7 +4,7 @@ using System; using System.IO; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using NUnit.Framework; #nullable enable diff --git a/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/ManifestRecordTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/ManifestRecordTests.cs index 1bd91ba841..9fe6b66366 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/ManifestRecordTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/Models/VirtualMonoRepo/ManifestRecordTests.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using NUnit.Framework; #nullable enable diff --git a/test/Microsoft.DotNet.DarcLib.Tests/RemoteTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/RemoteTests.cs index f1d72cbdbc..6e060ae2bc 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/RemoteTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/RemoteTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; +using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.Internal.Testing.Utility; using Moq; using NUnit.Framework; @@ -71,12 +72,12 @@ See [Dependency Description Format](https://github.com/dotnet/arcade/blob/main/D var secondCommit = new Commit(Constants.DarcBotName, "Sha", "TestCommit2"); var thirdCommit = new Commit("User", "Sha", "Updated text"); - IList commits = new List - { + IList commits = + [ firstCommit, secondCommit, thirdCommit - }; + ]; client.Setup(x => x.GetPullRequestAsync(It.IsAny())) .ReturnsAsync(pr); diff --git a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/RepositoryCloneManagerTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/RepositoryCloneManagerTests.cs index d9c60b6db9..b58291ce5a 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/RepositoryCloneManagerTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/RepositoryCloneManagerTests.cs @@ -7,8 +7,8 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging.Abstractions; using Moq; @@ -117,8 +117,9 @@ public async Task MultipleRemotesAreConfiguredTest() "test-repo", RepoUri, "main", - Array.Empty(), - Array.Empty()); + [], + [], + false); var newRemote = "https://dev.azure.com/dnceng/test-repo"; @@ -213,8 +214,9 @@ public async Task CommitsAreFetchedGradually() "test-repo", RepoUri, "main", - Array.Empty(), - Array.Empty()); + [], + [], + false); var clonePath = _tmpDir / mapping.Name; var configuration = new Dictionary() @@ -256,8 +258,9 @@ public async Task CommitIsNotFound() "test-repo", RepoUri, "main", - Array.Empty(), - Array.Empty()); + [], + [], + false); var clonePath = _tmpDir / mapping.Name; var configuration = new Dictionary() diff --git a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPatchHandlerTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPatchHandlerTests.cs index 96bd17d884..0bd6a09675 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPatchHandlerTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPatchHandlerTests.cs @@ -7,8 +7,8 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.Extensions.Logging.Abstractions; using Moq; @@ -65,7 +65,8 @@ public class VmrPatchHandlerTests "*.exe", "src/**/tests/**/*.*", "submodules/external-1/LICENSE.md", - }); + }, + DisableSynchronization: false); public VmrPatchHandlerTests() { @@ -989,12 +990,6 @@ public async Task CreatePatchesWithAFileTooLargeTest() private void VerifyGitCall(IEnumerable expectedArguments, Times? times = null) => VerifyGitCall(expectedArguments, _vmrPath.Path, times); - private void VerifyGitCall(string[] expectedArguments, string repoDir, Times? times = null) - { - _processManager - .Verify(x => x.ExecuteGit(repoDir, expectedArguments, It.IsAny?>(), It.IsAny()), times ?? Times.Once()); - } - private void VerifyGitCall(IEnumerable expectedArguments, string repoDir, Times? times = null) { _processManager diff --git a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPusherTests.cs b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPusherTests.cs index 61be58f108..fd8906a25a 100644 --- a/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPusherTests.cs +++ b/test/Microsoft.DotNet.DarcLib.Tests/VirtualMonoRepo/VmrPusherTests.cs @@ -8,8 +8,8 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; -using Microsoft.DotNet.Darc.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.VirtualMonoRepo; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.DotNet.Internal.Testing.Utility; using Microsoft.Extensions.Logging.Abstractions; diff --git a/test/Microsoft.DotNet.Maestro.Tasks.Tests/MergeSigningInfoTests.cs b/test/Microsoft.DotNet.Maestro.Tasks.Tests/MergeSigningInfoTests.cs index 36457ffc0c..2a0101eb06 100644 --- a/test/Microsoft.DotNet.Maestro.Tasks.Tests/MergeSigningInfoTests.cs +++ b/test/Microsoft.DotNet.Maestro.Tasks.Tests/MergeSigningInfoTests.cs @@ -12,8 +12,6 @@ namespace Microsoft.DotNet.Maestro.Tasks.Tests; [TestFixture] public class MergeSigningInfoTests { - private PushMetadataToBuildAssetRegistry _pushMetadata; - public const string Commit = "e7a79ce64f0703c231e6da88b5279dd0bf681b3d"; public const string AzureDevOpsAccount1 = "dnceng"; public const int AzureDevOpsBuildDefinitionId1 = 6; @@ -256,12 +254,6 @@ public class MergeSigningInfoTests ItemsToSign = [] }; - [SetUp] - public void SetupMergeSigningInfo() - { - _pushMetadata = new PushMetadataToBuildAssetRegistry(); - } - [Test] public void GivenCompatibleSigningInfo() { diff --git a/test/Microsoft.DotNet.Maestro.Tasks.Tests/ParseBuildManifestMetadataTests.cs b/test/Microsoft.DotNet.Maestro.Tasks.Tests/ParseBuildManifestMetadataTests.cs index 251d943821..ec830b743d 100644 --- a/test/Microsoft.DotNet.Maestro.Tasks.Tests/ParseBuildManifestMetadataTests.cs +++ b/test/Microsoft.DotNet.Maestro.Tasks.Tests/ParseBuildManifestMetadataTests.cs @@ -348,24 +348,6 @@ public class ParseBuildManifestMetadataTests SigningInformation = signingInfo1 }; - private static readonly Manifest manifest2 = new() - { - AzureDevOpsAccount = AzureDevOpsAccount1, - AzureDevOpsBranch = AzureDevOpsBranch1, - AzureDevOpsBuildDefinitionId = AzureDevOpsBuildDefinitionId1, - AzureDevOpsBuildId = AzureDevOpsBuildId1, - AzureDevOpsBuildNumber = AzureDevOpsBuildNumber1, - AzureDevOpsProject = AzureDevOpsProject1, - AzureDevOpsRepository = AzureDevOpsRepository1, - InitialAssetsLocation = LocationString, - PublishingVersion = 3, - Commit = Commit, - Name = GitHubRepositoryName, - Branch = GitHubBranch, - Packages = [package2], - Blobs = [blob2], - SigningInformation = signingInfo2 - }; private readonly BuildModel _buildModel = new( new BuildIdentity { diff --git a/test/ProductConstructionService.Api.Tests/BuildController20200914Tests.cs b/test/ProductConstructionService.Api.Tests/BuildController20200914Tests.cs index 5e5e279adf..5cc14651c2 100644 --- a/test/ProductConstructionService.Api.Tests/BuildController20200914Tests.cs +++ b/test/ProductConstructionService.Api.Tests/BuildController20200914Tests.cs @@ -18,7 +18,6 @@ using Moq; using ProductConstructionService.Api.Api.v2020_02_20.Controllers; -using ProductConstructionService.Api.VirtualMonoRepo; using ProductConstructionService.DependencyFlow.WorkItems; using ProductConstructionService.WorkItems; using Commit = Maestro.Api.Model.v2020_02_20.Commit; diff --git a/test/ProductConstructionService.Api.Tests/ChannelsController20200220Tests.cs b/test/ProductConstructionService.Api.Tests/ChannelsController20200220Tests.cs index 7fa62bf22e..bfb45fde8d 100644 --- a/test/ProductConstructionService.Api.Tests/ChannelsController20200220Tests.cs +++ b/test/ProductConstructionService.Api.Tests/ChannelsController20200220Tests.cs @@ -18,7 +18,6 @@ using Moq; using ProductConstructionService.Api.Api.v2020_02_20.Controllers; using ProductConstructionService.WorkItems; -using ProductConstructionService.Api.VirtualMonoRepo; using ProductConstructionService.DependencyFlow.WorkItems; namespace ProductConstructionService.Api.Tests; diff --git a/test/ProductConstructionService.Api.Tests/LoggingConfigurationTests.cs b/test/ProductConstructionService.Api.Tests/LoggingConfigurationTests.cs index d23b7cac54..3189386012 100644 --- a/test/ProductConstructionService.Api.Tests/LoggingConfigurationTests.cs +++ b/test/ProductConstructionService.Api.Tests/LoggingConfigurationTests.cs @@ -6,17 +6,13 @@ using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DataContracts; -using Microsoft.AspNetCore.Builder; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.Internal.Logging; using Microsoft.DotNet.ServiceFabric.ServiceHost; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Services.Common; using Moq; -using ProductConstructionService.Api.Telemetry; namespace ProductConstructionService.Api.Tests; diff --git a/test/ProductConstructionService.Api.Tests/RepositoryUrlAttributeTests.cs b/test/ProductConstructionService.Api.Tests/RepositoryUrlAttributeTests.cs index 67a4910367..70d31244db 100644 --- a/test/ProductConstructionService.Api.Tests/RepositoryUrlAttributeTests.cs +++ b/test/ProductConstructionService.Api.Tests/RepositoryUrlAttributeTests.cs @@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations; using FluentAssertions; using Maestro.Api.Model; -using NUnit.Framework; namespace ProductConstructionService.Api.Tests; diff --git a/test/ProductConstructionService.Api.Tests/SubscriptionsController20200220Tests.cs b/test/ProductConstructionService.Api.Tests/SubscriptionsController20200220Tests.cs index 96bd971db4..d68ed4c1a2 100644 --- a/test/ProductConstructionService.Api.Tests/SubscriptionsController20200220Tests.cs +++ b/test/ProductConstructionService.Api.Tests/SubscriptionsController20200220Tests.cs @@ -20,6 +20,7 @@ using ProductConstructionService.Api.Api.v2020_02_20.Controllers; using ProductConstructionService.WorkItems; using ProductConstructionService.DependencyFlow.WorkItems; +using Microsoft.DotNet.DarcLib.Helpers; namespace ProductConstructionService.Api.Tests; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/MockRedisCache.cs b/test/ProductConstructionService.DependencyFlow.Tests/MockRedisCache.cs index 58df783614..c05fd25add 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/MockRedisCache.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/MockRedisCache.cs @@ -1,7 +1,6 @@ // 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 ProductConstructionService.Common; namespace ProductConstructionService.DependencyFlow.Tests; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/PendingUpdatePullRequestUpdaterTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/PendingUpdatePullRequestUpdaterTests.cs index dac6ae125f..3cb9b4db3f 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/PendingUpdatePullRequestUpdaterTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/PendingUpdatePullRequestUpdaterTests.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Maestro.Data.Models; -using Microsoft.DotNet.DarcLib; -using Moq; using ProductConstructionService.DependencyFlow.WorkItems; namespace ProductConstructionService.DependencyFlow.Tests; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestBuilderTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestBuilderTests.cs index 64fa5c2c69..57c915eaec 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestBuilderTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestBuilderTests.cs @@ -5,6 +5,7 @@ using System.Text; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestPolicyFailureNotifierTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestPolicyFailureNotifierTests.cs index d9f0b4b789..57aea2649a 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestPolicyFailureNotifierTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestPolicyFailureNotifierTests.cs @@ -4,6 +4,8 @@ using System.Collections.Immutable; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestUpdaterTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestUpdaterTests.cs index 148c91b68b..707e9a2fbc 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/PullRequestUpdaterTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/PullRequestUpdaterTests.cs @@ -9,6 +9,8 @@ using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.DarcLib.VirtualMonoRepo; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.Extensions.DependencyInjection; @@ -191,9 +193,8 @@ protected void ThenCodeShouldHaveBeenBackflown(Build build) { _backFlower .Verify(b => b.FlowBackAsync( - Subscription.SourceDirectory, + It.Is(s => s.Id == Subscription.Id), It.Is(b => b.Id == build.Id && b.Commit == build.Commit), - TargetBranch, It.IsAny(), It.IsAny()), Times.Once); @@ -207,9 +208,8 @@ protected void ThenCodeShouldHaveBeenFlownForward(Build build) { _forwardFlower .Verify(b => b.FlowForwardAsync( - Subscription.TargetDirectory, + It.Is(s => s.Id == Subscription.Id), It.Is(b => b.Id == build.Id && b.Commit == build.Commit), - TargetBranch, It.IsAny(), It.IsAny()), Times.Once); diff --git a/test/ProductConstructionService.DependencyFlow.Tests/SubscriptionUpdaterTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/SubscriptionUpdaterTests.cs index 66d95bee05..b653c5dbd0 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/SubscriptionUpdaterTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/SubscriptionUpdaterTests.cs @@ -47,7 +47,7 @@ internal async Task WhenUpdateAsyncIsCalled(Subscription forSubscription, Build await Execute( async provider => { - ISubscriptionTriggerer updater = ActivatorUtilities.CreateInstance(provider, forSubscription.Id); + var updater = ActivatorUtilities.CreateInstance(provider, forSubscription.Id); await updater.UpdateSubscriptionAsync(andForBuild.Id); }); } diff --git a/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsForCodeFlowTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsForCodeFlowTests.cs index 451d6ac1c5..4058b4b378 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsForCodeFlowTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsForCodeFlowTests.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Maestro.Data.Models; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; using NUnit.Framework; namespace ProductConstructionService.DependencyFlow.Tests; diff --git a/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsTests.cs b/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsTests.cs index 87fd89754c..b3be93106c 100644 --- a/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsTests.cs +++ b/test/ProductConstructionService.DependencyFlow.Tests/UpdateAssetsTests.cs @@ -101,7 +101,7 @@ public async Task UpdateWithNoAssets(bool batchable) Batchable = batchable, UpdateFrequency = UpdateFrequency.EveryBuild }); - Build b = GivenANewBuild(true, Array.Empty<(string, string, bool)>()); + Build b = GivenANewBuild(true, []); WithRequireNonCoherencyUpdates(); WithNoRequiredCoherencyUpdates(); diff --git a/test/ProductConstructionService.FeedCleaner.Tests/FeedCleanerTests.cs b/test/ProductConstructionService.FeedCleaner.Tests/FeedCleanerTests.cs index a8ac37d8d1..aef0bcd909 100644 --- a/test/ProductConstructionService.FeedCleaner.Tests/FeedCleanerTests.cs +++ b/test/ProductConstructionService.FeedCleaner.Tests/FeedCleanerTests.cs @@ -6,6 +6,7 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/test/ProductConstructionService.LongestBuildPathUpdater.Tests/LongestBuildPathUpdaterTests.cs b/test/ProductConstructionService.LongestBuildPathUpdater.Tests/LongestBuildPathUpdaterTests.cs index 5d8abde722..73e95f1bb2 100644 --- a/test/ProductConstructionService.LongestBuildPathUpdater.Tests/LongestBuildPathUpdaterTests.cs +++ b/test/ProductConstructionService.LongestBuildPathUpdater.Tests/LongestBuildPathUpdaterTests.cs @@ -4,6 +4,7 @@ using Maestro.Data; using Maestro.Data.Models; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Kusto; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/test/ProductConstructionService.ScenarioTests.Tests/ProductConstructionService.ScenarioTests.Tests.csproj b/test/ProductConstructionService.ScenarioTests.Tests/ProductConstructionService.ScenarioTests.Tests.csproj new file mode 100644 index 0000000000..49a140cf39 --- /dev/null +++ b/test/ProductConstructionService.ScenarioTests.Tests/ProductConstructionService.ScenarioTests.Tests.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + diff --git a/test/ProductConstructionService.ScenarioTests/TestHelpersTest.cs b/test/ProductConstructionService.ScenarioTests.Tests/TestHelpersTest.cs similarity index 93% rename from test/ProductConstructionService.ScenarioTests/TestHelpersTest.cs rename to test/ProductConstructionService.ScenarioTests.Tests/TestHelpersTest.cs index 85ac2e8551..f47c0c94d5 100644 --- a/test/ProductConstructionService.ScenarioTests/TestHelpersTest.cs +++ b/test/ProductConstructionService.ScenarioTests.Tests/TestHelpersTest.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; -using NUnit.Framework; -namespace ProductConstructionService.ScenarioTests; +namespace ProductConstructionService.ScenarioTests.Tests; public class TestHelpersTests { diff --git a/test/ProductConstructionService.ScenarioTests/CodeFlowScenarioTestBase.cs b/test/ProductConstructionService.ScenarioTests/CodeFlowScenarioTestBase.cs new file mode 100644 index 0000000000..7871c738e2 --- /dev/null +++ b/test/ProductConstructionService.ScenarioTests/CodeFlowScenarioTestBase.cs @@ -0,0 +1,145 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using FluentAssertions; + +#nullable enable +namespace ProductConstructionService.ScenarioTests; + +internal class CodeFlowScenarioTestBase : ScenarioTestBase +{ + protected async Task CheckForwardFlowGitHubPullRequest( + string sourceRepoName, + string targetRepoName, + string targetBranch, + string[] testFiles, + Dictionary testFilePatches) + { + var expectedPRTitle = GetCodeFlowPRName(targetBranch, sourceRepoName); + + Octokit.PullRequest pullRequest = await WaitForPullRequestAsync(targetRepoName, targetBranch); + IReadOnlyList files = await GitHubApi.PullRequest.Files(TestParameters.GitHubTestOrg, targetRepoName, pullRequest.Number); + + files.Count.Should().Be(testFiles.Length + 3); + + // Verify source-manifest has changes + var sourceManifestFile = files.FirstOrDefault(file => file.FileName == "src/source-manifest.json"); + sourceManifestFile.Should().NotBeNull(); + + // Verify git-info + var allRepoVersionsFile = files.FirstOrDefault(file => file.FileName == "prereqs/git-info/AllRepoVersions.props"); + allRepoVersionsFile.Should().NotBeNull(); + + var repoPropsFile = files.FirstOrDefault(file => file.FileName == $"prereqs/git-info/{sourceRepoName}.props"); + repoPropsFile.Should().NotBeNull(); + + // Verify new files are in the PR + foreach (var testFile in testFiles) + { + var newFile = files.FirstOrDefault(file => file.FileName == $"src/{sourceRepoName}/{testFile}"); + newFile.Should().NotBeNull(); + newFile!.Patch.Should().Be(testFilePatches[testFile]); + } + } + + protected async Task CheckBackwardFlowGitHubPullRequest( + string sourceRepoName, + string targetRepoName, + string targetBranch, + string[] testFiles, + Dictionary testFilePatches, + string commitSha) + { + var expectedPRTitle = GetCodeFlowPRName(targetBranch, sourceRepoName); + + Octokit.PullRequest pullRequest = await WaitForPullRequestAsync(targetRepoName, targetBranch); + IReadOnlyList files = await GitHubApi.PullRequest.Files(TestParameters.GitHubTestOrg, targetRepoName, pullRequest.Number); + + var versionDetailsFile = files.FirstOrDefault(file => file.FileName == "eng/Version.Details.xml"); + versionDetailsFile.Should().NotBeNull(); + versionDetailsFile!.Patch.Should().Contain(GetExpectedCodeFlowDependencyVersionEntry(sourceRepoName, commitSha)); + + // Verify new files are in the PR + foreach (var testFile in testFiles) + { + var newFile = files.FirstOrDefault(file => file.FileName == $"{testFile}"); + newFile.Should().NotBeNull(); + newFile!.Patch.Should().Be(testFilePatches[testFile]); + } + } + + protected static async Task> CreateForwardFlowSubscriptionAsync( + string sourceChannelName, + string sourceRepo, + string targetRepo, + string targetBranch, + string updateFrequency, + string sourceOrg, + string targetDirectory) + => await CreateSourceEnabledSubscriptionAsync( + sourceChannelName, + sourceRepo, + targetRepo, + targetBranch, + updateFrequency, + sourceOrg, + targetDirectory: targetDirectory); + + protected static async Task> CreateBackwardFlowSubscriptionAsync( + string sourceChannelName, + string sourceRepo, + string targetRepo, + string targetBranch, + string updateFrequency, + string sourceOrg, + string sourceDirectory) + => await CreateSourceEnabledSubscriptionAsync( + sourceChannelName, + sourceRepo, + targetRepo, + targetBranch, + updateFrequency, + sourceOrg, + sourceDirectory: sourceDirectory); + + private static async Task> CreateSourceEnabledSubscriptionAsync( + string sourceChannelName, + string sourceRepo, + string targetRepo, + string targetBranch, + string updateFrequency, + string sourceOrg = "dotnet", + bool sourceIsAzDo = false, + bool targetIsAzDo = false, + bool trigger = false, + string? sourceDirectory = null, + string? targetDirectory = null) + { + string directoryType; + string directoryName; + if (!string.IsNullOrEmpty(sourceDirectory)) + { + directoryType = "--source-directory"; + directoryName = sourceDirectory; + } + else + { + directoryType = "--target-directory"; + directoryName = targetDirectory!; + } + + return await CreateSubscriptionAsync( + sourceChannelName, + sourceRepo, + targetRepo, + targetBranch, + updateFrequency, + sourceOrg, + [ + "--source-enabled", "true", + directoryType, directoryName + ], + sourceIsAzDo, + targetIsAzDo, + trigger); + } +} diff --git a/test/ProductConstructionService.ScenarioTests/EndToEndFlowLogic.cs b/test/ProductConstructionService.ScenarioTests/EndToEndFlowLogic.cs index 1570c09426..1f969a8337 100644 --- a/test/ProductConstructionService.ScenarioTests/EndToEndFlowLogic.cs +++ b/test/ProductConstructionService.ScenarioTests/EndToEndFlowLogic.cs @@ -2,23 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; using ProductConstructionService.Client.Models; namespace ProductConstructionService.ScenarioTests; -internal class EndToEndFlowLogic : ScenarioTestBase +internal abstract class TestLogic : ScenarioTestBase { private const string SourceBuildNumber = "654321"; private const string Source2BuildNumber = "987654"; - private readonly TestParameters _parameters; - - public EndToEndFlowLogic(TestParameters parameters) - { - _parameters = parameters; - SetTestParameters(_parameters); - } public async Task DarcBatchedFlowTestBase( string targetBranch, @@ -341,7 +334,7 @@ public async Task NonBatchedUpdatingGitHubFlowTestBase(string targetBranch, stri } } - public async Task NonBatchedUpdatingAzDoFlowTestBase(string targetBranch, string channelName, IImmutableList sourceAssets, IImmutableList updatedSourceAssets, + public static async Task NonBatchedUpdatingAzDoFlowTestBase(string targetBranch, string channelName, IImmutableList sourceAssets, IImmutableList updatedSourceAssets, List expectedDependencies, List expectedUpdatedDependencies) { var targetRepoName = TestRepository.TestRepo2Name; @@ -406,7 +399,7 @@ public async Task NonBatchedUpdatingAzDoFlowTestBase(string targetBranch, string } } - public async Task NonBatchedAzDoFlowTestBase(string targetBranch, string channelName, IImmutableList sourceAssets, + public static async Task NonBatchedAzDoFlowTestBase(string targetBranch, string channelName, IImmutableList sourceAssets, List expectedDependencies, bool allChecks = false, bool isFeedTest = false, string[] expectedFeeds = null, string[] notExpectedFeeds = null) { var targetRepoName = TestRepository.TestRepo2Name; @@ -462,7 +455,7 @@ public async Task NonBatchedAzDoFlowTestBase(string targetBranch, string channel } } - private async Task> CreateSubscriptionForEndToEndTests(string testChannelName, string sourceRepoName, + private static async Task> CreateSubscriptionForEndToEndTests(string testChannelName, string sourceRepoName, string targetRepoName, string targetBranch, bool allChecks, bool isAzDoTest) { if (allChecks) diff --git a/test/ProductConstructionService.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs b/test/ProductConstructionService.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs index 7837dbc4cc..9319e71279 100644 --- a/test/ProductConstructionService.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs +++ b/test/ProductConstructionService.ScenarioTests/ObjectHelpers/DependencyCollectionStringBuilder.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; -using Microsoft.DotNet.Darc; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.Darc.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; namespace ProductConstructionService.ScenarioTests.ObjectHelpers; diff --git a/test/ProductConstructionService.ScenarioTests/ObjectHelpers/SubscriptionBuilder.cs b/test/ProductConstructionService.ScenarioTests/ObjectHelpers/SubscriptionBuilder.cs index d4ca89695b..e00bbd6c5d 100644 --- a/test/ProductConstructionService.ScenarioTests/ObjectHelpers/SubscriptionBuilder.cs +++ b/test/ProductConstructionService.ScenarioTests/ObjectHelpers/SubscriptionBuilder.cs @@ -57,7 +57,7 @@ public static Subscription BuildSubscription( }); } - if (mergePolicyNames.Contains(MergePolicyConstants.AllCheckSuccessfulMergePolicyName) && ignoreChecks.Any()) + if (mergePolicyNames.Contains(MergePolicyConstants.AllCheckSuccessfulMergePolicyName) && ignoreChecks.Count != 0) { mergePolicies.Add( new MergePolicy diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs index 8a7ea1293a..f74a9f5c6d 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTestBase.cs @@ -8,6 +8,9 @@ using FluentAssertions; using Maestro.MergePolicyEvaluation; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models; +using Microsoft.DotNet.DarcLib.Models.AzureDevOps; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Internal.Testing.Utility; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; @@ -22,20 +25,18 @@ #nullable enable namespace ProductConstructionService.ScenarioTests; -internal abstract class ScenarioTestBase +internal abstract partial class ScenarioTestBase { private string _packageNameSalt = null!; - private TestParameters _parameters = null!; - private List _baseDarcRunArgs = []; // We need this for tests where we have multiple updates private readonly Dictionary _lastUpdatedPrTimes = []; - protected IProductConstructionServiceApi PcsApi => _parameters.PcsApi; + protected static IProductConstructionServiceApi PcsApi => TestParameters.PcsApi; - protected Octokit.GitHubClient GitHubApi => _parameters.GitHubApi; + protected static Octokit.GitHubClient GitHubApi => TestParameters.GitHubApi; - protected AzureDevOpsClient AzDoClient => _parameters.AzDoClient; + protected static AzureDevOpsClient AzDoClient => TestParameters.AzDoClient; [SetUp] public void BaseSetup() @@ -43,25 +44,14 @@ public void BaseSetup() _packageNameSalt = Guid.NewGuid().ToString().Substring(0, 8); } - public void SetTestParameters(TestParameters parameters) + public static void ConfigureDarcArgs() { - _parameters = parameters; - _baseDarcRunArgs = [ - "--bar-uri", _parameters.MaestroBaseUri, - "--github-pat", _parameters.GitHubToken, - "--azdev-pat", _parameters.AzDoToken, - _parameters.IsCI ? "--ci" : "" - ]; - - if (!string.IsNullOrEmpty(_parameters.MaestroToken)) - { - _baseDarcRunArgs.AddRange(["--p", _parameters.MaestroToken]); - } + } protected async Task WaitForPullRequestAsync(string targetRepo, string targetBranch) { - Octokit.Repository repo = await GitHubApi.Repository.Get(_parameters.GitHubTestOrg, targetRepo); + Octokit.Repository repo = await GitHubApi.Repository.Get(TestParameters.GitHubTestOrg, targetRepo); var attempts = 40; while (attempts-- > 0) @@ -95,7 +85,7 @@ public void SetTestParameters(TestParameters parameters) private async Task WaitForUpdatedPullRequestAsync(string targetRepo, string targetBranch, int attempts = 40) { - Octokit.Repository repo = await GitHubApi.Repository.Get(_parameters.GitHubTestOrg, targetRepo); + Octokit.Repository repo = await GitHubApi.Repository.Get(TestParameters.GitHubTestOrg, targetRepo); Octokit.PullRequest pr = await WaitForPullRequestAsync(targetRepo, targetBranch); while (attempts-- > 0) @@ -116,7 +106,7 @@ public void SetTestParameters(TestParameters parameters) private async Task WaitForMergedPullRequestAsync(string targetRepo, string targetBranch, int attempts = 40) { - Octokit.Repository repo = await GitHubApi.Repository.Get(_parameters.GitHubTestOrg, targetRepo); + Octokit.Repository repo = await GitHubApi.Repository.Get(TestParameters.GitHubTestOrg, targetRepo); Octokit.PullRequest pr = await WaitForPullRequestAsync(targetRepo, targetBranch); while (attempts-- > 0) @@ -135,7 +125,7 @@ private async Task WaitForMergedPullRequestAsync(string targetRepo, string throw new ScenarioTestException($"The created pull request for {targetRepo} targeting {targetBranch} was not merged within {attempts} minutes"); } - private async Task GetAzDoPullRequestIdAsync(string targetRepoName, string targetBranch) + private static async Task GetAzDoPullRequestIdAsync(string targetRepoName, string targetBranch) { var searchBaseUrl = GetAzDoRepoUrl(targetRepoName); IEnumerable prs = new List(); @@ -170,7 +160,7 @@ private async Task GetAzDoPullRequestIdAsync(string targetRepoName, string throw new ScenarioTestException($"No pull request was created in {searchBaseUrl} targeting {targetBranch}"); } - private async Task> SearchPullRequestsAsync(string repoUri, string targetPullRequestBranch) + private static async Task> SearchPullRequestsAsync(string repoUri, string targetPullRequestBranch) { (var accountName, var projectName, var repoName) = AzureDevOpsClient.ParseRepoUri(repoUri); var query = new StringBuilder(); @@ -179,7 +169,7 @@ private async Task> SearchPullRequestsAsync(string repoUri, str query.Append($"searchCriteria.status={prStatus.ToString().ToLower()}"); query.Append($"&searchCriteria.targetRefName=refs/heads/{targetPullRequestBranch}"); - JObject content = await _parameters.AzDoClient.ExecuteAzureDevOpsAPIRequestAsync( + JObject content = await TestParameters.AzDoClient.ExecuteAzureDevOpsAPIRequestAsync( HttpMethod.Get, accountName, projectName, @@ -192,7 +182,7 @@ private async Task> SearchPullRequestsAsync(string repoUri, str return prs; } - private async Task> GetAzDoPullRequestAsync(int pullRequestId, string targetRepoName, string targetBranch, bool isUpdated, string? expectedPRTitle = null) + private static async Task> GetAzDoPullRequestAsync(int pullRequestId, string targetRepoName, string targetBranch, bool isUpdated, string? expectedPRTitle = null) { var repoUri = GetAzDoRepoUrl(targetRepoName); (var accountName, var projectName, var repoName) = AzureDevOpsClient.ParseRepoUri(repoUri); @@ -216,7 +206,7 @@ private async Task> GetAzDoPullRequestAsync(in try { - JObject content = await _parameters.AzDoClient.ExecuteAzureDevOpsAPIRequestAsync( + JObject content = await TestParameters.AzDoClient.ExecuteAzureDevOpsAPIRequestAsync( HttpMethod.Patch, accountName, projectName, @@ -242,7 +232,7 @@ protected async Task CheckBatchedGitHubPullRequest(string targetBranch, string[] string targetRepoName, List expectedDependencies, string repoDirectory) { var repoNames = sourceRepoNames - .Select(name => $"{_parameters.GitHubTestOrg}/{name}") + .Select(name => $"{TestParameters.GitHubTestOrg}/{name}") .OrderBy(s => s); var expectedPRTitle = $"[{targetBranch}] Update dependencies from {string.Join(", ", repoNames)}"; @@ -252,10 +242,14 @@ protected async Task CheckBatchedGitHubPullRequest(string targetBranch, string[] protected async Task CheckNonBatchedGitHubPullRequest(string sourceRepoName, string targetRepoName, string targetBranch, List expectedDependencies, string repoDirectory, bool isCompleted = false, bool isUpdated = false) { - var expectedPRTitle = $"[{targetBranch}] Update dependencies from {_parameters.GitHubTestOrg}/{sourceRepoName}"; + var expectedPRTitle = $"[{targetBranch}] Update dependencies from {TestParameters.GitHubTestOrg}/{sourceRepoName}"; await CheckGitHubPullRequest(expectedPRTitle, targetRepoName, targetBranch, expectedDependencies, repoDirectory, isCompleted, isUpdated); } + protected static string GetCodeFlowPRName(string targetBranch, string sourceRepoName) => $"[{targetBranch}] Source code changes from {TestParameters.GitHubTestOrg}/{sourceRepoName}"; + protected static string GetExpectedCodeFlowDependencyVersionEntry(string repo, string sha) => + $"Source Uri=\"{GetGitHubRepoUrl(repo)}\" Sha=\"{sha}\" />"; + protected async Task CheckGitHubPullRequest(string expectedPRTitle, string targetRepoName, string targetBranch, List expectedDependencies, string repoDirectory, bool isCompleted, bool isUpdated) { @@ -279,7 +273,7 @@ protected async Task CheckGitHubPullRequest(string expectedPRTitle, string targe } } - protected async Task CheckBatchedAzDoPullRequest( + protected static async Task CheckBatchedAzDoPullRequest( string[] sourceRepoNames, string targetRepoName, string targetBranch, @@ -288,14 +282,14 @@ protected async Task CheckBatchedAzDoPullRequest( bool complete = false) { var repoNames = sourceRepoNames - .Select(n => $"{_parameters.AzureDevOpsAccount}/{_parameters.AzureDevOpsProject}/{n}") + .Select(n => $"{TestParameters.AzureDevOpsAccount}/{TestParameters.AzureDevOpsProject}/{n}") .OrderBy(s => s); var expectedPRTitle = $"[{targetBranch}] Update dependencies from {string.Join(", ", repoNames)}"; await CheckAzDoPullRequest(expectedPRTitle, targetRepoName, targetBranch, expectedDependencies, repoDirectory, complete, true, null, null); } - protected async Task CheckNonBatchedAzDoPullRequest( + protected static async Task CheckNonBatchedAzDoPullRequest( string sourceRepoName, string targetRepoName, string targetBranch, @@ -306,12 +300,12 @@ protected async Task CheckNonBatchedAzDoPullRequest( string[]? expectedFeeds = null, string[]? notExpectedFeeds = null) { - var expectedPRTitle = $"[{targetBranch}] Update dependencies from {_parameters.AzureDevOpsAccount}/{_parameters.AzureDevOpsProject}/{sourceRepoName}"; + var expectedPRTitle = $"[{targetBranch}] Update dependencies from {TestParameters.AzureDevOpsAccount}/{TestParameters.AzureDevOpsProject}/{sourceRepoName}"; // TODO (https://github.com/dotnet/arcade-services/issues/3149): I noticed we are not passing isCompleted further down - when I put it there the tests started failing - but we should fix this await CheckAzDoPullRequest(expectedPRTitle, targetRepoName, targetBranch, expectedDependencies, repoDirectory, false, isUpdated, expectedFeeds, notExpectedFeeds); } - protected async Task CheckAzDoPullRequest( + protected static async Task CheckAzDoPullRequest( string expectedPRTitle, string targetRepoName, string targetBranch, @@ -354,7 +348,7 @@ protected async Task CheckAzDoPullRequest( return pullRequest.Value.HeadBranch; } - private async Task ValidatePullRequestDependencies(string pullRequestBaseBranch, List expectedDependencies, int tries = 1) + private static async Task ValidatePullRequestDependencies(string pullRequestBaseBranch, List expectedDependencies, int tries = 1) { var triesRemaining = tries; while (triesRemaining-- > 0) @@ -369,12 +363,16 @@ private async Task ValidatePullRequestDependencies(string pullRequestBaseBranch, } } - protected async Task GitCommitAsync(string message) + protected static async Task GitCommitAsync(string message) { await RunGitAsync("commit", "-am", message); } - protected async Task PushGitBranchAsync(string remote, string branch) + protected static async Task GitAddAllAsync() => await RunGitAsync("add", "."); + + protected static async Task GitGetCurrentSha() => await RunGitAsync("rev-parse", "HEAD"); + + protected static async Task PushGitBranchAsync(string remote, string branch) { await RunGitAsync("push", "-u", remote, branch); return AsyncDisposable.Create(async () => @@ -397,19 +395,19 @@ protected static string GetRepoUrl(string org, string repository) return $"https://github.com/{org}/{repository}"; } - protected string GetGitHubRepoUrl(string repository) + protected static string GetGitHubRepoUrl(string repository) { - return GetRepoUrl(_parameters.GitHubTestOrg, repository); + return GetRepoUrl(TestParameters.GitHubTestOrg, repository); } - protected string GetRepoFetchUrl(string repository) + protected static string GetRepoFetchUrl(string repository) { - return GetRepoFetchUrl(_parameters.GitHubTestOrg, repository); + return GetRepoFetchUrl(TestParameters.GitHubTestOrg, repository); } - protected string GetRepoFetchUrl(string org, string repository) + protected static string GetRepoFetchUrl(string org, string repository) { - return $"https://{_parameters.GitHubUser}:{_parameters.GitHubToken}@github.com/{org}/{repository}"; + return $"https://{TestParameters.GitHubUser}:{TestParameters.GitHubToken}@github.com/{org}/{repository}"; } protected static string GetAzDoRepoUrl(string repoName, string azdoAccount = "dnceng", string azdoProject = "internal") @@ -422,30 +420,30 @@ protected static string GetAzDoApiRepoUrl(string repoName, string azdoAccount = return $"https://dev.azure.com/{azdoAccount}/{azdoProject}/_apis/git/repositories/{repoName}"; } - protected Task RunDarcAsyncWithInput(string input, params string[] args) + protected static Task RunDarcAsyncWithInput(string input, params string[] args) { - return TestHelpers.RunExecutableAsyncWithInput(_parameters.DarcExePath, input, + return TestHelpers.RunExecutableAsyncWithInput(TestParameters.DarcExePath, input, [ .. args, - .. _baseDarcRunArgs, + .. TestParameters.BaseDarcRunArgs, ]); } - protected Task RunDarcAsync(params string[] args) + protected static Task RunDarcAsync(params string[] args) { - return TestHelpers.RunExecutableAsync(_parameters.DarcExePath, + return TestHelpers.RunExecutableAsync(TestParameters.DarcExePath, [ .. args, - .. _baseDarcRunArgs, + .. TestParameters.BaseDarcRunArgs, ]); } - protected Task RunGitAsync(params string[] args) + protected static Task RunGitAsync(params string[] args) { - return TestHelpers.RunExecutableAsync(_parameters.GitExePath, args); + return TestHelpers.RunExecutableAsync(TestParameters.GitExePath, args); } - protected async Task> CreateTestChannelAsync(string testChannelName) + protected static async Task> CreateTestChannelAsync(string testChannelName) { var message = ""; @@ -485,39 +483,39 @@ protected async Task> CreateTestChannelAsync(string } }); } - protected async Task AddDependenciesToLocalRepo(string repoPath, string name, string repoUri, bool isToolset = false) + protected static async Task AddDependenciesToLocalRepo(string repoPath, string name, string repoUri, bool isToolset = false) { using (ChangeDirectory(repoPath)) { await RunDarcAsync(["add-dependency", "--name", name, "--type", isToolset ? "toolset" : "product", "--repo", repoUri, "--version", "0.0.1"]); } } - protected async Task GetTestChannelsAsync() + protected static async Task GetTestChannelsAsync() { return await RunDarcAsync("get-channels"); } - protected async Task DeleteTestChannelAsync(string testChannelName) + protected static async Task DeleteTestChannelAsync(string testChannelName) { await RunDarcAsync("delete-channel", "--name", testChannelName); } - protected async Task AddDefaultTestChannelAsync(string testChannelName, string repoUri, string branchName) + protected static async Task AddDefaultTestChannelAsync(string testChannelName, string repoUri, string branchName) { return await RunDarcAsync("add-default-channel", "--channel", testChannelName, "--repo", repoUri, "--branch", branchName, "-q"); } - protected async Task GetDefaultTestChannelsAsync(string repoUri, string branch) + protected static async Task GetDefaultTestChannelsAsync(string repoUri, string branch) { return await RunDarcAsync("get-default-channels", "--source-repo", repoUri, "--branch", branch); } - protected async Task DeleteDefaultTestChannelAsync(string testChannelName, string repoUri, string branch) + protected static async Task DeleteDefaultTestChannelAsync(string testChannelName, string repoUri, string branch) { await RunDarcAsync("delete-default-channel", "--channel", testChannelName, "--repo", repoUri, "--branch", branch); } - protected async Task> CreateSubscriptionAsync( + protected static async Task> CreateSubscriptionAsync( string sourceChannelName, string sourceRepo, string targetRepo, @@ -567,7 +565,7 @@ .. additionalOptions ?? [] }); } - protected async Task> CreateSubscriptionAsync(string yamlDefinition) + protected static async Task> CreateSubscriptionAsync(string yamlDefinition) { var output = await RunDarcAsyncWithInput(yamlDefinition, "add-subscription", "-q", "--read-stdin", "--no-trigger"); @@ -592,55 +590,55 @@ protected async Task> CreateSubscriptionAsync(strin throw new ScenarioTestException("Unable to create subscription."); } - protected async Task GetSubscriptionInfo(string subscriptionId) + protected static async Task GetSubscriptionInfo(string subscriptionId) { return await RunDarcAsync("get-subscriptions", "--ids", subscriptionId); } - protected async Task GetSubscriptions(string channelName) + protected static async Task GetSubscriptions(string channelName) { return await RunDarcAsync("get-subscriptions", "--channel", channelName); } - protected async Task SetSubscriptionStatusByChannel(bool enableSub, string channelName) + protected static async Task SetSubscriptionStatusByChannel(bool enableSub, string channelName) { await RunDarcAsync("subscription-status", enableSub ? "--enable" : "-d", "--channel", channelName, "--quiet"); } - protected async Task SetSubscriptionStatusById(bool enableSub, string subscriptionId) + protected static async Task SetSubscriptionStatusById(bool enableSub, string subscriptionId) { await RunDarcAsync("subscription-status", "--id", subscriptionId, enableSub ? "--enable" : "-d", "--quiet"); } - protected async Task DeleteSubscriptionsForChannel(string channelName) + protected static async Task DeleteSubscriptionsForChannel(string channelName) { return await RunDarcAsync("delete-subscriptions", "--channel", channelName, "--quiet"); } - protected async Task DeleteSubscriptionById(string subscriptionId) + protected static async Task DeleteSubscriptionById(string subscriptionId) { return await RunDarcAsync("delete-subscriptions", "--id", subscriptionId, "--quiet"); } - protected Task CreateBuildAsync(string repositoryUrl, string branch, string commit, string buildNumber, IImmutableList assets) + protected static Task CreateBuildAsync(string repositoryUrl, string branch, string commit, string buildNumber, IImmutableList assets) { return CreateBuildAsync(repositoryUrl, branch, commit, buildNumber, assets, ImmutableList.Empty); } - protected async Task CreateBuildAsync(string repositoryUrl, string branch, string commit, string buildNumber, IImmutableList assets, IImmutableList dependencies) + protected static async Task CreateBuildAsync(string repositoryUrl, string branch, string commit, string buildNumber, IImmutableList assets, IImmutableList dependencies) { Build build = await PcsApi.Builds.CreateAsync(new BuildData( commit: commit, - azureDevOpsAccount: _parameters.AzureDevOpsAccount, - azureDevOpsProject: _parameters.AzureDevOpsProject, + azureDevOpsAccount: TestParameters.AzureDevOpsAccount, + azureDevOpsProject: TestParameters.AzureDevOpsProject, azureDevOpsBuildNumber: buildNumber, azureDevOpsRepository: repositoryUrl, azureDevOpsBranch: branch, released: false, stable: false) { - AzureDevOpsBuildId = _parameters.AzureDevOpsBuildId, - AzureDevOpsBuildDefinitionId = _parameters.AzureDevOpsBuildDefinitionId, + AzureDevOpsBuildId = TestParameters.AzureDevOpsBuildId, + AzureDevOpsBuildDefinitionId = TestParameters.AzureDevOpsBuildDefinitionId, GitHubRepository = repositoryUrl, GitHubBranch = branch, Assets = assets, @@ -650,19 +648,19 @@ protected async Task CreateBuildAsync(string repositoryUrl, string branch return build; } - protected async Task GetDarcBuildAsync(int buildId) + protected static async Task GetDarcBuildAsync(int buildId) { var buildString = await RunDarcAsync("get-build", "--id", buildId.ToString()); return buildString; } - protected async Task UpdateBuildAsync(int buildId, string updateParams) + protected static async Task UpdateBuildAsync(int buildId, string updateParams) { var buildString = await RunDarcAsync("update-build", "--id", buildId.ToString(), updateParams); return buildString; } - protected async Task AddDependenciesToLocalRepo(string repoPath, List dependencies, string repoUri, string coherentParent = "") + protected static async Task AddDependenciesToLocalRepo(string repoPath, List dependencies, string repoUri, string coherentParent = "") { using (ChangeDirectory(repoPath)) { @@ -685,7 +683,7 @@ protected async Task AddDependenciesToLocalRepo(string repoPath, List } } - protected async Task GatherDrop(int buildId, string outputDir, bool includeReleased, string extraAssetsRegex) + protected static async Task GatherDrop(int buildId, string outputDir, bool includeReleased, string extraAssetsRegex) { string[] args = ["gather-drop", "--id", buildId.ToString(), "--dry-run", "--output-dir", outputDir]; @@ -702,12 +700,12 @@ protected async Task GatherDrop(int buildId, string outputDir, bool incl return await RunDarcAsync(args); } - protected async Task TriggerSubscriptionAsync(string subscriptionId) + protected static async Task TriggerSubscriptionAsync(string subscriptionId) { await PcsApi.Subscriptions.TriggerSubscriptionAsync(0, Guid.Parse(subscriptionId)); } - protected async Task AddBuildToChannelAsync(int buildId, string channelName) + protected static async Task AddBuildToChannelAsync(int buildId, string channelName) { await RunDarcAsync("add-build-to-channel", "--id", buildId.ToString(), "--channel", channelName, "--skip-assets-publishing"); return AsyncDisposable.Create(async () => @@ -717,7 +715,7 @@ protected async Task AddBuildToChannelAsync(int buildId, strin }); } - protected async Task DeleteBuildFromChannelAsync(string buildId, string channelName) + protected static async Task DeleteBuildFromChannelAsync(string buildId, string channelName) { await RunDarcAsync("delete-build-from-channel", "--id", buildId, "--channel", channelName); } @@ -734,12 +732,12 @@ protected static IDisposable ChangeDirectory(string directory) }); } - protected Task CloneRepositoryAsync(string repository) + protected static Task CloneRepositoryAsync(string repository) { - return CloneRepositoryAsync(_parameters.GitHubTestOrg, repository); + return CloneRepositoryAsync(TestParameters.GitHubTestOrg, repository); } - protected async Task CloneRepositoryAsync(string org, string repository) + protected static async Task CloneRepositoryAsync(string org, string repository) { using var shareable = Shareable.Create(TemporaryDirectory.Get()); var directory = shareable.Peek()!.Directory; @@ -749,8 +747,8 @@ protected async Task CloneRepositoryAsync(string org, string using (ChangeDirectory(directory)) { - await RunGitAsync("config", "user.email", $"{_parameters.GitHubUser}@test.com"); - await RunGitAsync("config", "user.name", _parameters.GitHubUser); + await RunGitAsync("config", "user.email", $"{TestParameters.GitHubUser}@test.com"); + await RunGitAsync("config", "user.name", TestParameters.GitHubUser); await RunGitAsync("config", "gc.auto", "0"); await RunGitAsync("config", "advice.detachedHead", "false"); await RunGitAsync("config", "color.ui", "false"); @@ -759,12 +757,12 @@ protected async Task CloneRepositoryAsync(string org, string return shareable.TryTake()!; } - protected string GetAzDoRepoAuthUrl(string repoName) + protected static string GetAzDoRepoAuthUrl(string repoName) { - return $"https://{_parameters.AzDoToken}@dev.azure.com/{_parameters.AzureDevOpsAccount}/{_parameters.AzureDevOpsProject}/_git/{repoName}"; + return $"https://{TestParameters.AzDoToken}@dev.azure.com/{TestParameters.AzureDevOpsAccount}/{TestParameters.AzureDevOpsProject}/_git/{repoName}"; } - protected async Task CloneAzDoRepositoryAsync(string repoName) + protected static async Task CloneAzDoRepositoryAsync(string repoName) { using var shareable = Shareable.Create(TemporaryDirectory.Get()); var directory = shareable.Peek()!.Directory; @@ -775,14 +773,14 @@ protected async Task CloneAzDoRepositoryAsync(string repoNam using (ChangeDirectory(directory)) { // The GitHubUser and AzDoUser have the same user name so this uses the existing parameter - await RunGitAsync("config", "user.email", $"{_parameters.GitHubUser}@test.com"); - await RunGitAsync("config", "user.name", _parameters.GitHubUser); + await RunGitAsync("config", "user.email", $"{TestParameters.GitHubUser}@test.com"); + await RunGitAsync("config", "user.name", TestParameters.GitHubUser); } return shareable.TryTake()!; } - protected async Task CloneRepositoryWithDarc(string repoName, string version, string reposToIgnore, bool includeToolset, int depth) + protected static async Task CloneRepositoryWithDarc(string repoName, string version, string reposToIgnore, bool includeToolset, int depth) { var sourceRepoUri = GetRepoUrl("dotnet", repoName); @@ -798,19 +796,19 @@ protected async Task CloneRepositoryWithDarc(string repoName return shareable.TryTake()!; } - protected async Task CheckoutRemoteRefAsync(string commit) + protected static async Task CheckoutRemoteRefAsync(string commit) { await RunGitAsync("fetch", "origin", commit); await RunGitAsync("checkout", commit); } - protected async Task CheckoutRemoteBranchAsync(string branchName) + protected static async Task CheckoutRemoteBranchAsync(string branchName) { await RunGitAsync("fetch", "origin", branchName); await RunGitAsync("checkout", branchName); } - protected async Task CheckoutBranchAsync(string branchName) + protected static async Task CheckoutBranchAsync(string branchName) { await RunGitAsync("fetch", "origin"); await RunGitAsync("checkout", "-b", branchName); @@ -829,7 +827,7 @@ protected async Task CheckoutBranchAsync(string branchName) }); } - protected async Task DeleteBranchAsync(string branchName) + protected static async Task DeleteBranchAsync(string branchName) { await RunGitAsync("push", "origin", "--delete", branchName); } @@ -895,19 +893,19 @@ protected static IImmutableList GetSingleAssetData(string assetName, return ImmutableList.Create(asset); } - protected async Task SetRepositoryPolicies(string repoUri, string branchName, string[]? policyParams = null) + protected static async Task SetRepositoryPolicies(string repoUri, string branchName, string[]? policyParams = null) { string[] commandParams = ["set-repository-policies", "-q", "--repo", repoUri, "--branch", branchName, .. policyParams ?? []]; await RunDarcAsync(commandParams); } - protected async Task GetRepositoryPolicies(string repoUri, string branchName) + protected static async Task GetRepositoryPolicies(string repoUri, string branchName) { return await RunDarcAsync("get-repository-policies", "--all", "--repo", repoUri, "--branch", branchName); } - protected async Task WaitForMergedPullRequestAsync(string targetRepo, string targetBranch, Octokit.PullRequest pr, Octokit.Repository repo, int attempts = 40) + protected static async Task WaitForMergedPullRequestAsync(string targetRepo, string targetBranch, Octokit.PullRequest pr, Octokit.Repository repo, int attempts = 40) { while (attempts-- > 0) { @@ -929,12 +927,12 @@ protected async Task CheckGithubPullRequestChecks(string targetRepoName, s { TestContext.WriteLine($"Checking opened PR in {targetBranch} {targetRepoName}"); Octokit.PullRequest pullRequest = await WaitForPullRequestAsync(targetRepoName, targetBranch); - Octokit.Repository repo = await GitHubApi.Repository.Get(_parameters.GitHubTestOrg, targetRepoName); + Octokit.Repository repo = await GitHubApi.Repository.Get(TestParameters.GitHubTestOrg, targetRepoName); return await ValidateGithubMaestroCheckRunsSuccessful(targetRepoName, targetBranch, pullRequest, repo); } - protected async Task ValidateGithubMaestroCheckRunsSuccessful(string targetRepoName, string targetBranch, Octokit.PullRequest pullRequest, Octokit.Repository repo) + protected static async Task ValidateGithubMaestroCheckRunsSuccessful(string targetRepoName, string targetBranch, Octokit.PullRequest pullRequest, Octokit.Repository repo) { // Waiting 5 minutes 30 seconds for maestro to add the checks to the PR (it takes 5 minutes for the checks to be added) await Task.Delay(TimeSpan.FromSeconds(5 * 60 + 30)); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_AzDoFlow.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_AzDoFlow.cs index 970d0e5214..14447e06b1 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_AzDoFlow.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_AzDoFlow.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; using ProductConstructionService.Client.Models; @@ -12,7 +12,7 @@ namespace ProductConstructionService.ScenarioTests; [Category("PostDeployment")] [Category("AzDO")] [NonParallelizable] -internal class ScenarioTests_AzDoFlow : ScenarioTestBase +internal class ScenarioTests_AzDoFlow : TestLogic { private IImmutableList _source1Assets = null; private IImmutableList _source2Assets = null; @@ -103,12 +103,9 @@ public async Task Darc_AzDoFlow_Batched() { TestContext.WriteLine("Azure DevOps Dependency Flow, batched"); - TestParameters parameters = await TestParameters.GetAsync(useNonPrimaryEndpoint: true); - SetTestParameters(parameters); - var testLogic = new EndToEndFlowLogic(parameters); var expectedDependencies = _expectedAzDoDependenciesSource1.Concat(_expectedAzDoDependenciesSource2).ToList(); - await testLogic.DarcBatchedFlowTestBase( + await DarcBatchedFlowTestBase( GetTestBranchName(), GetTestChannelName(), _source1Assets, @@ -122,11 +119,7 @@ public async Task Darc_AzDoFlow_NonBatched_AllChecksSuccessful() { TestContext.WriteLine("AzDo Dependency Flow, non-batched, all checks successful"); - TestParameters parameters = await TestParameters.GetAsync(); - SetTestParameters(parameters); - var testLogic = new EndToEndFlowLogic(parameters); - - await testLogic.NonBatchedAzDoFlowTestBase( + await NonBatchedAzDoFlowTestBase( GetTestBranchName(), GetTestChannelName(), _source1Assets, @@ -139,11 +132,7 @@ public async Task Darc_AzDoFlow_NonBatched() { TestContext.WriteLine("AzDo Dependency Flow, non-batched"); - TestParameters parameters = await TestParameters.GetAsync(); - SetTestParameters(parameters); - var testLogic = new EndToEndFlowLogic(parameters); - - await testLogic.NonBatchedUpdatingAzDoFlowTestBase( + await NonBatchedUpdatingAzDoFlowTestBase( GetTestBranchName(), GetTestChannelName(), _source1Assets, @@ -176,10 +165,6 @@ public async Task Darc_AzDoFlow_FeedFlow() ]; TestContext.WriteLine("Azure DevOps Internal feed flow"); - TestParameters parameters = await TestParameters.GetAsync(); - SetTestParameters(parameters); - - var testLogic = new EndToEndFlowLogic(parameters); List expectedAzDoFeedFlowDependencies = [ @@ -228,7 +213,7 @@ public async Task Darc_AzDoFlow_FeedFlow() }, ]; - await testLogic.NonBatchedAzDoFlowTestBase( + await NonBatchedAzDoFlowTestBase( GetTestBranchName(), GetTestChannelName(), feedFlowSourceAssets, diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Builds.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Builds.cs index ef6aca0d0e..bd5641330a 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Builds.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Builds.cs @@ -21,23 +21,13 @@ internal class ScenarioTests_Builds : ScenarioTestBase private const string SourceBranch = "master"; private IImmutableList _sourceAssets; - private TestParameters _parameters; [SetUp] - public async Task InitializeAsync() + public void SetUp() { _sourceAssets = GetAssetData( - GetUniqueAssetName("Foo"), "1.1.0", - GetUniqueAssetName("Bar"), "2.1.0"); - _parameters = await TestParameters.GetAsync(); - SetTestParameters(_parameters); - } - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; + GetUniqueAssetName("Foo"), "1.1.0", + GetUniqueAssetName("Bar"), "2.1.0"); } // Create a new build and check some of the metadata. Then mark as released and check again @@ -45,7 +35,7 @@ public Task DisposeAsync() public async Task ArcadeBuilds_EndToEnd() { TestContext.WriteLine("Darc/Maestro build-handling tests"); - var scenarioDirectory = _parameters._dir.Directory; + using var scenarioDirectory = TemporaryDirectory.Get(); _repoUrl = GetGitHubRepoUrl(_repoName); @@ -59,7 +49,7 @@ public async Task ArcadeBuilds_EndToEnd() updatedBuild.Released.Should().BeTrue("Retrieved build has Released set to false when it should be true"); // Gather a drop with release included - var gatherWithReleasedDir = Path.Combine(scenarioDirectory, "gather-with-released"); + var gatherWithReleasedDir = Path.Combine(scenarioDirectory.Directory, "gather-with-released"); var gatherDropOutput = ""; TestContext.WriteLine("Starting 'Gather with released, where build has been set to released' using folder " + gatherWithReleasedDir); @@ -74,7 +64,7 @@ public async Task ArcadeBuilds_EndToEnd() // Gather with release excluded (default behavior). Gather-drop should throw an error. TestContext.WriteLine("Starting 'Gather with release excluded' - gather-drop should throw an error."); - var gatherWithNoReleasedDir = Path.Combine(scenarioDirectory, "gather-no-released"); + var gatherWithNoReleasedDir = Path.Combine(scenarioDirectory.Directory, "gather-no-released"); Assert.ThrowsAsync(async () => await GatherDrop(build.Id, gatherWithNoReleasedDir, false, string.Empty), "Gather with release excluded"); // Unrelease the build @@ -82,7 +72,7 @@ public async Task ArcadeBuilds_EndToEnd() unreleaseBuild.Released.Should().BeFalse(); // Gather with release excluded again (default behavior) - var gatherWithNoReleased2Dir = Path.Combine(scenarioDirectory, "gather-no-released-2"); + var gatherWithNoReleased2Dir = Path.Combine(scenarioDirectory.Directory, "gather-no-released-2"); TestContext.WriteLine("Starting 'Gather unreleased with release excluded' using folder " + gatherWithNoReleased2Dir); gatherDropOutput = await GatherDrop(build.Id, gatherWithNoReleased2Dir, false, string.Empty); @@ -92,7 +82,7 @@ public async Task ArcadeBuilds_EndToEnd() gatherDropOutput.Should().NotContain("always-download assets in build", "Gather unreleased with release excluded"); // Gather with release excluded again, but specify --always-download-asset-filters - var gatherWithNoReleased3Dir = Path.Combine(scenarioDirectory, "gather-no-released-3"); + var gatherWithNoReleased3Dir = Path.Combine(scenarioDirectory.Directory, "gather-no-released-3"); TestContext.WriteLine("Starting 'Gather unreleased with release excluded' using folder " + gatherWithNoReleased3Dir); gatherDropOutput = await GatherDrop(build.Id, gatherWithNoReleased3Dir, false, GetUniqueAssetName("Bar").Replace(".", "\\.") + "$"); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Channels.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Channels.cs index 951c06d993..4ba9cd51bb 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Channels.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Channels.cs @@ -11,21 +11,9 @@ namespace ProductConstructionService.ScenarioTests; [Parallelizable] internal class ScenarioTests_Channels : ScenarioTestBase { - private TestParameters _parameters; - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - [Test] public async Task ArcadeChannels_EndToEnd() { - _parameters = await TestParameters.GetAsync(); - SetTestParameters(_parameters); - // Create a new channel var testChannelName = GetTestChannelName(); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Clone.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Clone.cs index 33e5283426..da4146b279 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Clone.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Clone.cs @@ -18,9 +18,6 @@ public async Task Darc_CloneRepo() { TestContext.WriteLine("Darc-Clone repo end to end test"); - TestParameters parameters = await TestParameters.GetAsync(useNonPrimaryEndpoint: true); - SetTestParameters(parameters); - var sourceRepoName = "core-sdk"; var sourceRepoVersion = "v3.0.100-preview4-011223"; var sourceRepoUri = GetGitHubRepoUrl(sourceRepoName); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_CodeFlow.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_CodeFlow.cs new file mode 100644 index 0000000000..6976414935 --- /dev/null +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_CodeFlow.cs @@ -0,0 +1,176 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using NUnit.Framework; +using ProductConstructionService.Client.Models; + +#nullable enable + +namespace ProductConstructionService.ScenarioTests.ScenarioTests; + +[TestFixture] +[Category("PostDeployment")] +[Category("CodeFlow")] +internal class ScenarioTests_CodeFlow : CodeFlowScenarioTestBase +{ + private const string TestFileName = "newFile.txt"; + + private static readonly Dictionary TestFilesContent = new() + { + { TestFileName, "test" } + }; + + private static readonly Dictionary TestFilePatches = new() + { + { TestFileName, "@@ -0,0 +1 @@\n+test\n\\ No newline at end of file" } + }; + + [Test] + public async Task Vmr_ForwardFlowTest() + { + var channelName = GetTestChannelName(); + var branchName = GetTestBranchName(); + var productRepo = GetGitHubRepoUrl(TestRepository.TestRepo1Name); + var targetBranchName = GetTestBranchName(); + + await using AsyncDisposableValue testChannel = await CreateTestChannelAsync(channelName); + + await using AsyncDisposableValue subscriptionId = await CreateForwardFlowSubscriptionAsync( + channelName, + TestRepository.TestRepo1Name, + TestRepository.VmrTestRepoName, + targetBranchName, + UpdateFrequency.None.ToString(), + TestParameters.GitHubTestOrg, + targetDirectory: TestRepository.TestRepo1Name); + + TemporaryDirectory vmrDirectory = await CloneRepositoryAsync(TestRepository.VmrTestRepoName); + TemporaryDirectory reposFolder = await CloneRepositoryAsync(TestRepository.TestRepo1Name); + var newFilePath = Path.Combine(reposFolder.Directory, TestFileName); + + await CreateTargetBranchAndExecuteTest(targetBranchName, vmrDirectory, async () => + { + using (ChangeDirectory(reposFolder.Directory)) + { + await using (await CheckoutBranchAsync(branchName)) + { + // Make a change in a product repo + TestContext.WriteLine("Making code changes to the repo"); + await File.WriteAllTextAsync(newFilePath, TestFilesContent[TestFileName]); + + await GitAddAllAsync(); + await GitCommitAsync("Add new file"); + + // Push it to github + await using (await PushGitBranchAsync("origin", branchName)) + { + var repoSha = (await GitGetCurrentSha()).TrimEnd(); + + // Create a new build from the commit and add it to a channel + Build build = await CreateBuildAsync( + GetGitHubRepoUrl(TestRepository.TestRepo1Name), + branchName, + repoSha, + "1", + []); + + TestContext.WriteLine("Adding build to channel"); + await AddBuildToChannelAsync(build.Id, channelName); + + TestContext.WriteLine("Triggering the subscription"); + // Now trigger the subscription + await TriggerSubscriptionAsync(subscriptionId.Value); + + TestContext.WriteLine("Verifying subscription PR"); + await CheckForwardFlowGitHubPullRequest(TestRepository.TestRepo1Name, TestRepository.VmrTestRepoName, targetBranchName, [TestFileName], TestFilePatches); + } + } + } + }); + } + + [Test] + public async Task Vmr_BackwardFlowTest() + { + var channelName = GetTestChannelName(); + var branchName = GetTestBranchName(); + var productRepo = GetGitHubRepoUrl(TestRepository.TestRepo1Name); + var targetBranchName = GetTestBranchName(); + + await using AsyncDisposableValue testChannel = await CreateTestChannelAsync(channelName); + + await using AsyncDisposableValue subscriptionId = await CreateBackwardFlowSubscriptionAsync( + channelName, + TestRepository.VmrTestRepoName, + TestRepository.TestRepo1Name, + targetBranchName, + UpdateFrequency.None.ToString(), + TestParameters.GitHubTestOrg, + sourceDirectory: TestRepository.TestRepo1Name); + + TemporaryDirectory testRepoFolder = await CloneRepositoryAsync(TestRepository.TestRepo1Name); + TemporaryDirectory reposFolder = await CloneRepositoryAsync(TestRepository.VmrTestRepoName); + var newFilePath = Path.Combine(reposFolder.Directory, "src", TestRepository.TestRepo1Name, TestFileName); + + await CreateTargetBranchAndExecuteTest(targetBranchName, testRepoFolder, async () => + { + using (ChangeDirectory(reposFolder.Directory)) + { + await using (await CheckoutBranchAsync(branchName)) + { + // Make a change in the VMR + TestContext.WriteLine("Making code changes in the VMR"); + using FileStream newFileStream = File.Create(newFilePath); + { + using StreamWriter newFileWriter = new(newFileStream); + newFileWriter.Write(TestFilesContent[TestFileName]); + } + + await GitAddAllAsync(); + await GitCommitAsync("Add new file"); + + // Push it to github + await using (await PushGitBranchAsync("origin", branchName)) + { + var repoSha = (await GitGetCurrentSha()).TrimEnd(); + + // Create a new build from the commit and add it to a channel + Build build = await CreateBuildAsync( + GetGitHubRepoUrl(TestRepository.VmrTestRepoName), + branchName, + repoSha, + "1", + // We might want to add some assets here to mimic what happens in the VMR + []); + + TestContext.WriteLine("Adding build to channel"); + await AddBuildToChannelAsync(build.Id, channelName); + + TestContext.WriteLine("Triggering the subscription"); + // Now trigger the subscription + await TriggerSubscriptionAsync(subscriptionId.Value); + + TestContext.WriteLine("Verifying subscription PR"); + await CheckBackwardFlowGitHubPullRequest(TestRepository.VmrTestRepoName, TestRepository.TestRepo1Name, targetBranchName, [TestFileName], TestFilePatches, repoSha); + } + } + } + }); + } + + private async Task CreateTargetBranchAndExecuteTest(string targetBranchName, TemporaryDirectory targetDirectory, Func test) + { + // first create a new target branch in the VMR + using (ChangeDirectory(targetDirectory.Directory)) + { + await using (await CheckoutBranchAsync(targetBranchName)) + { + // and push it to GH + await using (await PushGitBranchAsync("origin", targetBranchName)) + { + await test(); + } + } + } + } +} diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_DefaultChannels.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_DefaultChannels.cs index 8b322591d1..41e6680361 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_DefaultChannels.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_DefaultChannels.cs @@ -14,7 +14,6 @@ internal class ScenarioTests_DefaultChannels : ScenarioTestBase private readonly string _repoName = TestRepository.TestRepo1Name; private readonly string _branchName; private readonly string _branchNameWithRefsHeads; - private TestParameters _parameters; public ScenarioTests_DefaultChannels() { @@ -22,20 +21,6 @@ public ScenarioTests_DefaultChannels() _branchNameWithRefsHeads = $"refs/heads/{_branchName}"; } - [SetUp] - public async Task InitializeAsync() - { - _parameters = await TestParameters.GetAsync(); - SetTestParameters(_parameters); - } - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - [Test] public async Task ArcadeChannels_DefaultChannels() { diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Dependencies.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Dependencies.cs index 2bf93f0537..dc05506db3 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Dependencies.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Dependencies.cs @@ -17,22 +17,9 @@ namespace ProductConstructionService.ScenarioTests; [Parallelizable] internal class ScenarioTests_Dependencies : ScenarioTestBase { - - private TestParameters _parameters; - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - [Test] public async Task ArcadeDependencies_EndToEnd() { - _parameters = await TestParameters.GetAsync(useNonPrimaryEndpoint: true); - SetTestParameters(_parameters); - var source1RepoName = TestRepository.TestRepo1Name; var source2RepoName = TestRepository.TestRepo3Name; var targetRepoName = TestRepository.TestRepo2Name; @@ -63,7 +50,7 @@ public async Task ArcadeDependencies_EndToEnd() Build build2 = await CreateBuildAsync(source2RepoUri, sourceBranch, sourceCommit, sourceBuildNumber, source2Assets); await AddBuildToChannelAsync(build2.Id, testChannelName); - ImmutableList dependencies = ImmutableList.Empty; + ImmutableList dependencies = []; var buildRef1 = new BuildRef(build1.Id, true, 1); dependencies = dependencies.Add(buildRef1); var buildRef2 = new BuildRef(build2.Id, true, 2); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_GitHubFlow.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_GitHubFlow.cs index 53ff27ab9f..60be9d77fb 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_GitHubFlow.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_GitHubFlow.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; using NUnit.Framework.Internal; using ProductConstructionService.Client.Models; @@ -13,7 +13,7 @@ namespace ProductConstructionService.ScenarioTests; [Category("PostDeployment")] [Category("GitHub")] [Parallelizable] -internal class ScenarioTests_GitHubFlow : ScenarioTestBase +internal class ScenarioTests_GitHubFlow : TestLogic { private IImmutableList _source1Assets = null; private IImmutableList _source2Assets = null; @@ -25,9 +25,6 @@ internal class ScenarioTests_GitHubFlow : ScenarioTestBase [SetUp] public void SetUp() { - using TestParameters parameters = TestParameters.GetAsync().Result; - SetTestParameters(parameters); - _source1Assets = GetAssetData(GetUniqueAssetName("Foo"), "1.1.0", GetUniqueAssetName("Bar"), "2.1.0"); _source2Assets = GetAssetData(GetUniqueAssetName("Pizza"), "3.1.0", GetUniqueAssetName("Hamburger"), "4.1.0"); _source1AssetsUpdated = GetAssetData(GetUniqueAssetName("Foo"), "1.17.0", GetUniqueAssetName("Bar"), "2.17.0"); @@ -107,11 +104,9 @@ public async Task Darc_GitHubFlow_Batched() { TestContext.WriteLine("Github Dependency Flow, batched"); - using TestParameters parameters = await TestParameters.GetAsync(); - var testLogic = new EndToEndFlowLogic(parameters); var expectedDependencies = _expectedDependenciesSource1.Concat(_expectedDependenciesSource2).ToList(); - await testLogic.DarcBatchedFlowTestBase( + await DarcBatchedFlowTestBase( GetTestBranchName(), GetTestChannelName(), _source1Assets, @@ -125,10 +120,7 @@ public async Task Darc_GitHubFlow_NonBatched() { TestContext.WriteLine("GitHub Dependency Flow, non-batched"); - using TestParameters parameters = await TestParameters.GetAsync(); - var testLogic = new EndToEndFlowLogic(parameters); - - await testLogic.NonBatchedUpdatingGitHubFlowTestBase( + await NonBatchedUpdatingGitHubFlowTestBase( GetTestBranchName(), GetTestChannelName(), _source1Assets, @@ -142,9 +134,6 @@ public async Task Darc_GitHubFlow_NonBatched_StrictCoherency() { TestContext.WriteLine("GitHub Dependency Flow, non-batched"); - using TestParameters parameters = await TestParameters.GetAsync(); - var testLogic = new EndToEndFlowLogic(parameters); - List expectedCoherencyDependencies = [ new DependencyDetail @@ -169,7 +158,7 @@ public async Task Darc_GitHubFlow_NonBatched_StrictCoherency() IImmutableList sourceAssets = GetAssetData(GetUniqueAssetName("Foo"), "1.1.0", GetUniqueAssetName("Bar"), "2.1.0"); - await testLogic.NonBatchedGitHubFlowTestBase( + await NonBatchedGitHubFlowTestBase( GetTestBranchName(), GetTestChannelName(), sourceAssets, @@ -180,9 +169,6 @@ await testLogic.NonBatchedGitHubFlowTestBase( [Test] public async Task Darc_GitHubFlow_NonBatched_FailingCoherencyUpdate() { - using TestParameters parameters = await TestParameters.GetAsync(); - var testLogic = new EndToEndFlowLogic(parameters); - List expectedCoherencyDependencies = [ new DependencyDetail @@ -226,7 +212,7 @@ public async Task Darc_GitHubFlow_NonBatched_FailingCoherencyUpdate() IImmutableList sourceAssets = GetAssetData(GetUniqueAssetName("Foo"), "1.1.0", GetUniqueAssetName("Bar"), "2.1.0"); IImmutableList childSourceAssets = GetAssetData(GetUniqueAssetName("Fzz"), "1.1.0", GetUniqueAssetName("ASD"), "1.1.1"); - await testLogic.NonBatchedGitHubFlowCoherencyTestBase( + await NonBatchedGitHubFlowCoherencyTestBase( GetTestBranchName(), GetTestChannelName(), sourceAssets, @@ -239,9 +225,6 @@ await testLogic.NonBatchedGitHubFlowCoherencyTestBase( [Test] public async Task Darc_GitHubFlow_NonBatched_FailingCoherentOnlyUpdate() { - using TestParameters parameters = await TestParameters.GetAsync(); - var testLogic = new EndToEndFlowLogic(parameters); - List expectedNonCoherencyDependencies = [ new DependencyDetail @@ -307,7 +290,7 @@ public async Task Darc_GitHubFlow_NonBatched_FailingCoherentOnlyUpdate() IImmutableList sourceAssets = GetAssetData(GetUniqueAssetName("A1"), "1.1.0", GetUniqueAssetName("A2"), "1.1.0"); IImmutableList childSourceAssets = GetAssetData(GetUniqueAssetName("B1"), "2.1.0", GetUniqueAssetName("B2"), "2.1.0"); - await testLogic.NonBatchedGitHubFlowCoherencyOnlyTestBase( + await NonBatchedGitHubFlowCoherencyOnlyTestBase( GetTestBranchName(), GetTestChannelName(), sourceAssets, diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_MergePolicies.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_MergePolicies.cs index 17138fbfe7..59f1d27797 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_MergePolicies.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_MergePolicies.cs @@ -13,25 +13,10 @@ namespace ProductConstructionService.ScenarioTests; [Parallelizable] internal class ScenarioTests_MergePolicies : ScenarioTestBase { - private TestParameters _parameters; private readonly Random _random = new(); private const string SourceRepo = "maestro-test1"; private const string TargetRepo = "maestro-test2"; - [SetUp] - public async Task InitializeAsync() - { - _parameters = await TestParameters.GetAsync(useNonPrimaryEndpoint: true); - SetTestParameters(_parameters); - } - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - private string GetTestChannelName() { return "Test Channel " + _random.Next(int.MaxValue); diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_RepoPolicies.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_RepoPolicies.cs index b500120094..a8b8031225 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_RepoPolicies.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_RepoPolicies.cs @@ -13,14 +13,6 @@ namespace ProductConstructionService.ScenarioTests; internal class ScenarioTests_RepoPolicies : ScenarioTestBase { private readonly string _repoName = TestRepository.TestRepo1Name; - private TestParameters _parameters; - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } [Test] public async Task RepoPolicies_EndToEnd() @@ -28,9 +20,6 @@ public async Task RepoPolicies_EndToEnd() TestContext.WriteLine("Repository merge policy handling"); TestContext.WriteLine("Running tests..."); - _parameters = await TestParameters.GetAsync(); - SetTestParameters(_parameters); - var repoUrl = GetGitHubRepoUrl(_repoName); // The RepoPolicies logic does a partial string match for the branch name in the base, diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_SdkUpdate.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_SdkUpdate.cs index c684561181..b687a938f3 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_SdkUpdate.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_SdkUpdate.cs @@ -3,7 +3,8 @@ using System.Collections.Immutable; using FluentAssertions; -using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models.Darc; using NUnit.Framework; using ProductConstructionService.Client.Models; @@ -14,23 +15,12 @@ namespace ProductConstructionService.ScenarioTests; [NonParallelizable] internal class ScenarioTests_SdkUpdate : ScenarioTestBase { - private TestParameters _parameters; private readonly Random _random = new(); - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - [TestCase(false)] [TestCase(true)] public async Task ArcadeSdkUpdate_E2E(bool targetAzDO) { - _parameters = await TestParameters.GetAsync(); - SetTestParameters(_parameters); - var testChannelName = "Test Channel " + _random.Next(int.MaxValue); const string sourceOrg = "maestro-auth-test"; const string sourceRepo = "arcade"; diff --git a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Subscriptions.cs b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Subscriptions.cs index 6c04dc5610..6cc587cdcd 100644 --- a/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Subscriptions.cs +++ b/test/ProductConstructionService.ScenarioTests/ScenarioTests/ScenarioTests_Subscriptions.cs @@ -3,7 +3,7 @@ using FluentAssertions; using Maestro.MergePolicyEvaluation; -using Microsoft.DotNet.Darc; +using Microsoft.DotNet.Darc.Helpers; using NUnit.Framework; using NUnit.Framework.Internal; using ProductConstructionService.ScenarioTests.ObjectHelpers; @@ -16,15 +16,6 @@ namespace ProductConstructionService.ScenarioTests; [Parallelizable] internal class ScenarioTests_Subscriptions : ScenarioTestBase { - private TestParameters _parameters; - - [TearDown] - public Task DisposeAsync() - { - _parameters.Dispose(); - return Task.CompletedTask; - } - [Test] public async Task Subscriptions_EndToEnd() { @@ -34,9 +25,6 @@ public async Task Subscriptions_EndToEnd() var channel1Name = GetTestChannelName(); var channel2Name = GetTestChannelName(); - _parameters = await TestParameters.GetAsync(useNonPrimaryEndpoint: true); - SetTestParameters(_parameters); - var repo1Uri = GetGitHubRepoUrl(repo1Name); var repo2Uri = GetGitHubRepoUrl(repo2Name); var repo1AzDoUri = GetAzDoRepoUrl(repo1Name); @@ -264,7 +252,7 @@ await CreateSubscriptionAsync(channel1Name, repo1Name, repo2Name, targetBranch, } } - private async Task ValidateSubscriptionInfo(string subscriptionId, string expectedSubscriptionInfo) + private static async Task ValidateSubscriptionInfo(string subscriptionId, string expectedSubscriptionInfo) { var subscriptionInfo = await GetSubscriptionInfo(subscriptionId); subscriptionInfo.Should().BeEquivalentTo(expectedSubscriptionInfo); diff --git a/test/ProductConstructionService.ScenarioTests/TestHelpers.cs b/test/ProductConstructionService.ScenarioTests/TestHelpers.cs index 0fee1e363c..bea7198aaa 100644 --- a/test/ProductConstructionService.ScenarioTests/TestHelpers.cs +++ b/test/ProductConstructionService.ScenarioTests/TestHelpers.cs @@ -124,13 +124,13 @@ public static async Task Which(string command) var cmd = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd"; return (await RunExecutableAsync(cmd, "/c", $"where {command}")).Trim() // get the first line of where's output - .Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? ""; + .Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? ""; } return (await RunExecutableAsync("/bin/sh", "-c", $"which {command}")).Trim(); } - internal static string FormatExecutableCall(string executable, params string[] args) + public static string FormatExecutableCall(string executable, params string[] args) { var output = new StringBuilder(); var secretArgNames = new[] { "-p", "--password", "--github-pat", "--azdev-pat" }; diff --git a/test/ProductConstructionService.ScenarioTests/TestParameters.cs b/test/ProductConstructionService.ScenarioTests/TestParameters.cs index f6e5ff0b36..f4f102b191 100644 --- a/test/ProductConstructionService.ScenarioTests/TestParameters.cs +++ b/test/ProductConstructionService.ScenarioTests/TestParameters.cs @@ -9,25 +9,46 @@ using Microsoft.DotNet.DarcLib.Helpers; using Microsoft.DotNet.Internal.Testing.Utility; using Microsoft.Extensions.Configuration; +using NUnit.Framework; using Octokit.Internal; using ProductConstructionService.Client; #nullable enable namespace ProductConstructionService.ScenarioTests; +[SetUpFixture] public class TestParameters : IDisposable { - internal readonly TemporaryDirectory _dir; - private static readonly string pcsBaseUri; + private static TemporaryDirectory? _dir; private static readonly string? pcsToken; - private static readonly string githubToken; private static readonly string darcPackageSource; - private static readonly string? azdoToken; - private static readonly bool isCI; + private static readonly string? azDoToken; private static readonly string? darcDir; private static readonly string? darcVersion; - - private readonly IAzureDevOpsTokenProvider _azdoTokenProvider; + private static IProductConstructionServiceApi? _pcsApi; + private static AzureDevOpsTokenProvider? _azDoTokenProvider; + private static Octokit.GitHubClient? _gitHubApi; + private static AzureDevOpsClient? _azDoClient; + private static string? _gitHubPath; + private static List? _baseDarcRunArgs; + + public static string DarcExePath { get; private set; } = string.Empty; + public static IProductConstructionServiceApi PcsApi => _pcsApi!; + public static Octokit.GitHubClient GitHubApi => _gitHubApi!; + public static AzureDevOpsClient AzDoClient => _azDoClient!; + public static string PcsBaseUri { get; private set; } + public static string GitHubToken { get; private set; } + public static string AzDoToken => _azDoTokenProvider!.GetTokenForAccount("default"); + public static bool IsCI { get; private set; } + public static string? PcsToken => PcsApi.Options.Credentials?.GetToken(new TokenRequestContext(), default).Token; + public static string GitHubTestOrg => "maestro-auth-test"; + public static string AzureDevOpsAccount => "dnceng"; + public static string AzureDevOpsProject => "internal"; + public static string GitHubUser => "dotnet-maestro-bot"; + public static string GitExePath => _gitHubPath!; + public static int AzureDevOpsBuildId => 144618; + public static int AzureDevOpsBuildDefinitionId => 6; + public static List BaseDarcRunArgs => _baseDarcRunArgs!; static TestParameters() { @@ -35,74 +56,73 @@ static TestParameters() .AddUserSecrets() .Build(); - pcsBaseUri = Environment.GetEnvironmentVariable("PCS_BASEURI") + PcsBaseUri = Environment.GetEnvironmentVariable("PCS_BASEURI") ?? userSecrets["PCS_BASEURI"] ?? "https://product-construction-int.delightfuldune-c0f01ab0.westus2.azurecontainerapps.io/"; pcsToken = Environment.GetEnvironmentVariable("PCS_TOKEN") ?? userSecrets["PCS_TOKEN"]; - isCI = Environment.GetEnvironmentVariable("DARC_IS_CI")?.ToLower() == "true"; - githubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? userSecrets["GITHUB_TOKEN"] + IsCI = Environment.GetEnvironmentVariable("DARC_IS_CI")?.ToLower() == "true"; + GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? userSecrets["GITHUB_TOKEN"] ?? throw new Exception("Please configure the GitHub token"); darcPackageSource = Environment.GetEnvironmentVariable("DARC_PACKAGE_SOURCE") ?? userSecrets["DARC_PACKAGE_SOURCE"] ?? throw new Exception("Please configure the Darc package source"); - azdoToken = Environment.GetEnvironmentVariable("AZDO_TOKEN") + azDoToken = Environment.GetEnvironmentVariable("AZDO_TOKEN") ?? userSecrets["AZDO_TOKEN"]; darcDir = Environment.GetEnvironmentVariable("DARC_DIR"); darcVersion = Environment.GetEnvironmentVariable("DARC_VERSION") ?? userSecrets["DARC_VERSION"]; } - /// If set to true, the test will attempt to use the non primary endpoint, if provided - public static async Task GetAsync(bool useNonPrimaryEndpoint = false) + [OneTimeSetUp] + public async Task Initialize() { - var testDir = TemporaryDirectory.Get(); - var testDirSharedWrapper = Shareable.Create(testDir); + _dir = TemporaryDirectory.Get(); + var testDirSharedWrapper = Shareable.Create(_dir); - IProductConstructionServiceApi pcsApi = pcsBaseUri.Contains("localhost") || pcsBaseUri.Contains("127.0.0.1") - ? PcsApiFactory.GetAnonymous(pcsBaseUri) - : PcsApiFactory.GetAuthenticated(pcsBaseUri, accessToken: pcsToken, managedIdentityId: null, disableInteractiveAuth: isCI); + _pcsApi = PcsBaseUri.Contains("localhost") || PcsBaseUri.Contains("127.0.0.1") + ? PcsApiFactory.GetAnonymous(PcsBaseUri) + : PcsApiFactory.GetAuthenticated(PcsBaseUri, accessToken: pcsToken, managedIdentityId: null, disableInteractiveAuth: IsCI); var darcRootDir = darcDir; if (string.IsNullOrEmpty(darcRootDir)) { - await InstallDarc(pcsApi, testDirSharedWrapper); + await InstallDarc(_pcsApi, testDirSharedWrapper); darcRootDir = testDirSharedWrapper.Peek()!.Directory; } - var darcExe = Path.Join(darcRootDir, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "darc.exe" : "darc"); - var git = await TestHelpers.Which("git"); - var azDoTokenProvider = AzureDevOpsTokenProvider.FromStaticOptions(new() + DarcExePath = Path.Join(darcRootDir, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "darc.exe" : "darc"); + _gitHubPath = await TestHelpers.Which("git"); + _azDoTokenProvider = AzureDevOpsTokenProvider.FromStaticOptions(new() { ["default"] = new() { - Token = azdoToken, - UseLocalCredentials = !isCI, - DisableInteractiveAuth = isCI, + Token = azDoToken, + UseLocalCredentials = !IsCI, + DisableInteractiveAuth = IsCI, } }); + _baseDarcRunArgs = [ + "--bar-uri", TestParameters.PcsBaseUri, + "--github-pat", TestParameters.GitHubToken, + "--azdev-pat", TestParameters.AzDoToken, + TestParameters.IsCI ? "--ci" : "" + ]; + if (!string.IsNullOrEmpty(TestParameters.PcsToken)) + { + _baseDarcRunArgs.AddRange(["--p", TestParameters.PcsToken]); + } + Assembly assembly = typeof(TestParameters).Assembly; - var githubApi = + _gitHubApi = new Octokit.GitHubClient( new Octokit.ProductHeaderValue(assembly.GetName().Name, assembly.GetCustomAttribute()?.InformationalVersion), - new InMemoryCredentialStore(new Octokit.Credentials(githubToken))); - var azDoClient = + new InMemoryCredentialStore(new Octokit.Credentials(GitHubToken))); + _azDoClient = new AzureDevOpsClient( - azDoTokenProvider, - new ProcessManager(new NUnitLogger(), git), + _azDoTokenProvider, + new ProcessManager(new NUnitLogger(), _gitHubPath), new NUnitLogger(), testDirSharedWrapper.TryTake()!.Directory); - - return new TestParameters( - darcExe, - git, - pcsBaseUri, - githubToken, - pcsApi, - githubApi, - azDoClient, - testDir, - azDoTokenProvider, - isCI); } private static async Task InstallDarc(IProductConstructionServiceApi pcsApi, Shareable toolPath) @@ -127,62 +147,6 @@ private static async Task InstallDarc(IProductConstructionServiceApi pcsApi, Sha await TestHelpers.RunExecutableAsync(dotnetExe, [.. toolInstallArgs]); } - private TestParameters( - string darcExePath, - string gitExePath, - string pcsBaseUri, - string gitHubToken, - IProductConstructionServiceApi pcsApi, - Octokit.GitHubClient gitHubApi, - AzureDevOpsClient azdoClient, - TemporaryDirectory dir, - IAzureDevOpsTokenProvider azdoTokenProvider, - bool isCI) - { - _dir = dir; - _azdoTokenProvider = azdoTokenProvider; - DarcExePath = darcExePath; - GitExePath = gitExePath; - MaestroBaseUri = pcsBaseUri; - GitHubToken = gitHubToken; - PcsApi = pcsApi; - GitHubApi = gitHubApi; - AzDoClient = azdoClient; - IsCI = isCI; - } - - public string DarcExePath { get; } - - public string GitExePath { get; } - - public string GitHubUser { get; } = "dotnet-maestro-bot"; - - public string GitHubTestOrg { get; } = "maestro-auth-test"; - - public string MaestroBaseUri { get; } - - public string? MaestroToken => PcsApi.Options.Credentials?.GetToken(new TokenRequestContext(), default).Token; - - public string GitHubToken { get; } - - public IProductConstructionServiceApi PcsApi { get; } - - public Octokit.GitHubClient GitHubApi { get; } - - public AzureDevOpsClient AzDoClient { get; } - - public int AzureDevOpsBuildDefinitionId { get; } = 6; - - public int AzureDevOpsBuildId { get; } = 144618; - - public string AzureDevOpsAccount { get; } = "dnceng"; - - public string AzureDevOpsProject { get; } = "internal"; - - public string AzDoToken => _azdoTokenProvider.GetTokenForAccount("default"); - - public bool IsCI { get; } - public void Dispose() { _dir?.Dispose(); diff --git a/test/ProductConstructionService.ScenarioTests/TestRepository.cs b/test/ProductConstructionService.ScenarioTests/TestRepository.cs index 7b49f4f2d5..f091a5cf01 100644 --- a/test/ProductConstructionService.ScenarioTests/TestRepository.cs +++ b/test/ProductConstructionService.ScenarioTests/TestRepository.cs @@ -8,6 +8,7 @@ internal class TestRepository internal static string TestRepo1Name => "maestro-test1"; internal static string TestRepo2Name => "maestro-test2"; internal static string TestRepo3Name => "maestro-test3"; + internal static string VmrTestRepoName => "maestro-test-vmr"; internal static string SourceBranch => "master"; // This branch and commit data is special for the coherency test diff --git a/test/ProductConstructionService.SubscriptionTriggerer.Tests/SubscriptionTriggererTests.cs b/test/ProductConstructionService.SubscriptionTriggerer.Tests/SubscriptionTriggererTests.cs index ddf9176876..f434f82dc1 100644 --- a/test/ProductConstructionService.SubscriptionTriggerer.Tests/SubscriptionTriggererTests.cs +++ b/test/ProductConstructionService.SubscriptionTriggerer.Tests/SubscriptionTriggererTests.cs @@ -159,19 +159,19 @@ public async Task ShouldNotTriggerUpToDateSubscription() private const string RepoName = "source.repo"; - private Channel GetChannel() => new() + private static Channel GetChannel() => new() { Name = "channel", Classification = "class" }; - private Build GetOldBuild() => new() + private static Build GetOldBuild() => new() { AzureDevOpsRepository = RepoName, DateProduced = DateTimeOffset.UtcNow.AddDays(-2) }; - private Build GetNewBuild() => new() + private static Build GetNewBuild() => new() { AzureDevOpsRepository = RepoName, DateProduced = DateTimeOffset.UtcNow, diff --git a/test/ProductConstructionService.WorkItem.Tests/FakeRedisCache.cs b/test/ProductConstructionService.WorkItem.Tests/FakeRedisCache.cs index a82b69fb9d..766f180b3d 100644 --- a/test/ProductConstructionService.WorkItem.Tests/FakeRedisCache.cs +++ b/test/ProductConstructionService.WorkItem.Tests/FakeRedisCache.cs @@ -6,15 +6,15 @@ namespace ProductConstructionService.WorkItem.Tests; internal class FakeRedisCache : IRedisCache { - private string? value; + private string? _value; - public Task GetAsync() => Task.FromResult(value); + public Task GetAsync() => Task.FromResult(_value); public Task SetAsync(string value, TimeSpan? expiration = null) { - this.value = value; + _value = value; return Task.CompletedTask; } public Task TryDeleteAsync() => throw new NotImplementedException(); - public Task TryGetAsync() => Task.FromResult(value); + public Task TryGetAsync() => Task.FromResult(_value); } diff --git a/test/SubscriptionActorService.Tests/PullRequestActorTests.cs b/test/SubscriptionActorService.Tests/PullRequestActorTests.cs index 0925eb0c27..824c33086c 100644 --- a/test/SubscriptionActorService.Tests/PullRequestActorTests.cs +++ b/test/SubscriptionActorService.Tests/PullRequestActorTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using FluentAssertions; using Maestro.Contracts; @@ -12,6 +11,7 @@ using Maestro.Data.Models; using Maestro.DataProviders; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.DotNet.Kusto; using Microsoft.DotNet.ServiceFabric.ServiceHost; diff --git a/test/SubscriptionActorService.Tests/PullRequestBuilderTests.cs b/test/SubscriptionActorService.Tests/PullRequestBuilderTests.cs index a09f1a2d12..d4c02142de 100644 --- a/test/SubscriptionActorService.Tests/PullRequestBuilderTests.cs +++ b/test/SubscriptionActorService.Tests/PullRequestBuilderTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Models.Darc; using Microsoft.DotNet.Maestro.Client.Models; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/SubscriptionActorService.Tests/PullRequestPolicyFailureNotifierTests.cs b/test/SubscriptionActorService.Tests/PullRequestPolicyFailureNotifierTests.cs index 0b1b135093..59077eef40 100644 --- a/test/SubscriptionActorService.Tests/PullRequestPolicyFailureNotifierTests.cs +++ b/test/SubscriptionActorService.Tests/PullRequestPolicyFailureNotifierTests.cs @@ -8,6 +8,8 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.DotNet.DarcLib; +using Microsoft.DotNet.DarcLib.Helpers; +using Microsoft.DotNet.DarcLib.Models; using Microsoft.DotNet.GitHub.Authentication; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting;