diff --git a/.azure/pipelines/fast-pr-validation.yml b/.azure/pipelines/fast-pr-validation.yml index 66e7364fb489..00af6695ec8c 100644 --- a/.azure/pipelines/fast-pr-validation.yml +++ b/.azure/pipelines/fast-pr-validation.yml @@ -1,7 +1,11 @@ +# Don't run CI for this config +trigger: none -trigger: -- master -- release/* +# Run PR validation on all branches +pr: + branches: + include: + - '*' jobs: - template: jobs/default-build.yml diff --git a/build/dependencies.props b/build/dependencies.props index 17b2d0d75a49..7a2cf789f75d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -6,6 +6,7 @@ 3.0.0-preview1-26907-05 3.0.0-preview1-26907-05 + 3.0.0-preview1-26907-05 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 1.6.0-preview1-26907-04 @@ -21,10 +22,12 @@ 1.7.0-preview1-26907-04 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 4.6.0-preview1-26907-04 4.10.0-preview1-26907-04 @@ -170,8 +173,12 @@ 1.0.0-rc3-003121 1.1.0 3.19.8 + 5.3.0 + 5.3.0 5.3.0 + 5.3.0 5.3.0 + 5.3.0 2.1.1 1.0.12 1.1.9 diff --git a/build/external-dependencies.props b/build/external-dependencies.props index 0283778f3343..e723c6d7a47c 100644 --- a/build/external-dependencies.props +++ b/build/external-dependencies.props @@ -136,8 +136,12 @@ + + + + @@ -154,6 +158,7 @@ + @@ -229,10 +234,12 @@ + + diff --git a/build/tasks/ProcessSharedFrameworkDeps.cs b/build/tasks/GenerateSharedFrameworkMetadataFiles.cs similarity index 79% rename from build/tasks/ProcessSharedFrameworkDeps.cs rename to build/tasks/GenerateSharedFrameworkMetadataFiles.cs index 97afbd47344c..9105cbbb5ac3 100644 --- a/build/tasks/ProcessSharedFrameworkDeps.cs +++ b/build/tasks/GenerateSharedFrameworkMetadataFiles.cs @@ -14,7 +14,7 @@ namespace RepoTasks { - public class ProcessSharedFrameworkDeps : Task + public class GenerateSharedFrameworkMetadataFiles : Task { [Required] public string AssetsFilePath { get; set; } @@ -23,7 +23,7 @@ public class ProcessSharedFrameworkDeps : Task public string DepsFilePath { get; set; } [Required] - public string OutputPath { get; set; } + public string DepsFileOutputPath { get; set; } [Required] public string TargetFramework { get; set; } @@ -37,6 +37,9 @@ public class ProcessSharedFrameworkDeps : Task [Required] public string BaseRuntimeIdentifier { get; set; } + [Required] + public string PlatformManifestOutputPath { get; set; } + public override bool Execute() { ExecuteCore(); @@ -65,27 +68,38 @@ private void ExecuteCore() var runtimeFiles = new List(); var nativeFiles = new List(); var resourceAssemblies = new List(); + var platformManifest = new List(); foreach (var library in context.RuntimeLibraries) { foreach (var file in library.RuntimeAssemblyGroups.SelectMany(g => g.RuntimeFiles)) { - var path = $"runtimes/{context.Target.Runtime}/lib/{TargetFramework}/{Path.GetFileName(file.Path)}"; + var fileName = Path.GetFileName(file.Path); + var path = $"runtimes/{context.Target.Runtime}/lib/{TargetFramework}/{fileName}"; runtimeFiles.Add( new RuntimeFile( path, file.AssemblyVersion, file.FileVersion)); + + platformManifest.Add($"{fileName}|{FrameworkName}|{file.AssemblyVersion}|{file.FileVersion}"); } foreach (var file in library.NativeLibraryGroups.SelectMany(g => g.RuntimeFiles)) { - var path = $"runtimes/{context.Target.Runtime}/native/{Path.GetFileName(file.Path)}"; + var fileName = Path.GetFileName(file.Path); + var path = $"runtimes/{context.Target.Runtime}/native/{fileName}"; nativeFiles.Add( new RuntimeFile( path, file.AssemblyVersion, file.FileVersion)); + + if (!Version.TryParse(file.FileVersion, out var fileVersion)) + { + fileVersion = new Version(0, 0, 0, 0); + } + platformManifest.Add($"{fileName}|{FrameworkName}||{fileVersion}"); } resourceAssemblies.AddRange( @@ -126,7 +140,12 @@ private void ExecuteCore() expandedGraph ); - using (var depsStream = File.Create(OutputPath)) + Directory.CreateDirectory(Path.GetDirectoryName(PlatformManifestOutputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(DepsFileOutputPath)); + + File.WriteAllLines(PlatformManifestOutputPath, platformManifest.OrderBy(n => n)); + + using (var depsStream = File.Create(DepsFileOutputPath)) { new DependencyContextWriter().Write(context, depsStream); } diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks index 8bb46081f56b..dfc02c545149 100644 --- a/build/tasks/RepoTasks.tasks +++ b/build/tasks/RepoTasks.tasks @@ -10,7 +10,7 @@ - + diff --git a/modules/HttpClientFactory b/modules/HttpClientFactory index 7c4f9479b475..4dfcf7485e62 160000 --- a/modules/HttpClientFactory +++ b/modules/HttpClientFactory @@ -1 +1 @@ -Subproject commit 7c4f9479b4753a37c8b0669a883002e5e448cc94 +Subproject commit 4dfcf7485e62819d0d73c00d7e7eb53d75abdbd3 diff --git a/modules/MusicStore b/modules/MusicStore index aca4b432e157..2b0ea782be84 160000 --- a/modules/MusicStore +++ b/modules/MusicStore @@ -1 +1 @@ -Subproject commit aca4b432e157c5e9063f551af8bff3de7641b744 +Subproject commit 2b0ea782be84655f9d6320b591efcb6dc1a38177 diff --git a/modules/Templating b/modules/Templating index 514fcdcba533..0af2acd6fff0 160000 --- a/modules/Templating +++ b/modules/Templating @@ -1 +1 @@ -Subproject commit 514fcdcba533eb70a670b9ccc2073d67f6c6f9ca +Subproject commit 0af2acd6fff0f51ec42183f5a5b01f8f0712af5f diff --git a/src/Framework/Microsoft.AspNetCore.App.props b/src/Framework/Microsoft.AspNetCore.App.props index c9ad8cf00829..208ded45fc7b 100644 --- a/src/Framework/Microsoft.AspNetCore.App.props +++ b/src/Framework/Microsoft.AspNetCore.App.props @@ -3,8 +3,16 @@ --> + + + + + + + - + @@ -40,10 +48,10 @@ + - @@ -51,13 +59,15 @@ + - + + @@ -81,6 +91,11 @@ + + + + @@ -96,6 +111,7 @@ + @@ -124,8 +140,24 @@ + + + + + + + + + + + + + + + + diff --git a/src/Framework/pkg/Metapackage.targets b/src/Framework/pkg/Metapackage.targets index 1c4e011b4ca0..365eacc8fa6e 100644 --- a/src/Framework/pkg/Metapackage.targets +++ b/src/Framework/pkg/Metapackage.targets @@ -21,7 +21,7 @@ - + $(MicrosoftNETCoreAppPackageVersion) @@ -40,12 +40,22 @@ - + + + + + <_SupportedRids Include="$(SupportedRuntimeIdentifiers)" /> + { "runtimes": { @@ -55,7 +65,42 @@ - + + + + + + + <_AspNetAppPackageConflictOverrides Include="@(Dependency->'%(Identity)|%(Version)')" Condition=" '%(Dependency.Version)' != '' " /> + + + + + + + + + + + + + + @(_AspNetAppPackageConflictOverrides, '%3B%0A )%3B + + + + +]]> + + + + @@ -63,6 +108,12 @@ ref/$(TargetFramework)/%(ReferencePath.FileName)%(ReferencePath.Extension) + + build/$(TargetFramework)/Microsoft.AspNetCore.App.PlatformManifest.txt + + + build/$(TargetFramework)/Microsoft.AspNetCore.App.props + diff --git a/src/Framework/pkg/Microsoft.AspNetCore.App.pkgproj b/src/Framework/pkg/Microsoft.AspNetCore.App.pkgproj index a7f0ed52ccca..79a90fbed802 100644 --- a/src/Framework/pkg/Microsoft.AspNetCore.App.pkgproj +++ b/src/Framework/pkg/Microsoft.AspNetCore.App.pkgproj @@ -23,6 +23,14 @@ This package requires the ASP.NET Core runtime. This runtime is installed by the + + + false + true + _ResolvedFxProjects + + + diff --git a/src/Framework/src/SharedFx.targets b/src/Framework/src/SharedFx.targets index 1c3063ebaf70..7efa45bc777d 100644 --- a/src/Framework/src/SharedFx.targets +++ b/src/Framework/src/SharedFx.targets @@ -18,7 +18,7 @@ This targets file should only be imported by .shfxproj files. PrepareForPublish; ComputeAndCopyFilesToPublishDirectory; GeneratePublishDependencyFile; - GenerateSharedFxDependencyFile; + GenerateSharedFxMetadataFiles; GeneratePublishRuntimeConfigurationFile; CopySharedFxToOutput; CollectSharedFxOutput; @@ -78,6 +78,7 @@ This targets file should only be imported by .shfxproj files. false + $(OutputPath)manifest\ $(OutputPath)files\ $(OutputPath)symbols\ $(OutputPath)native\ @@ -99,6 +100,7 @@ This targets file should only be imported by .shfxproj files. $(PublishRuntimeConfigFilePath) $(MetadataOutputPath)$(SharedFxName).deps.json $(MetadataOutputPath).version + $(ManifestOutputDir)$(SharedFxName).PlatformManifest.txt @@ -115,6 +117,8 @@ This targets file should only be imported by .shfxproj files. $(MetadataOutputPath) $(RuntimeAssetsOutputPath) $(NativeAssetsOutputPath) + + $(ManifestOutputDir) $(SharedFxName) $(PackageId) @@ -170,17 +174,18 @@ This targets file should only be imported by .shfxproj files. Overwrite="true" /> - - + - diff --git a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj index 4ea4f83952bb..7642891eae9c 100644 --- a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj +++ b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj @@ -6,6 +6,8 @@ false + + <_Parameter1>PackageVersion @@ -38,10 +40,20 @@ - - <_Parameter1>SharedFxMetadataOutput:%(_ResolvedFrameworkReference.SharedFxName) + + + + <_Parameter1>SharedFxDependencies + <_Parameter2>@(ExpectedAssemblyNames) + + + <_Parameter1>MetadataOutputPath <_Parameter2>%(_ResolvedFrameworkReference.MetadataOutputPath) + + <_Parameter1>ManifestOutputDir + <_Parameter2>%(_ResolvedFrameworkReference.ManifestOutputDir) + diff --git a/src/Framework/test/SharedFxTests.cs b/src/Framework/test/SharedFxTests.cs index b465b16705af..21341a40fdeb 100644 --- a/src/Framework/test/SharedFxTests.cs +++ b/src/Framework/test/SharedFxTests.cs @@ -1,29 +1,94 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json.Linq; using Xunit; +using Xunit.Abstractions; namespace Microsoft.AspNetCore { public class SharedFxTests { private readonly string _expectedTfm; + private readonly string _expectedRid; + private readonly ITestOutputHelper _output; - public SharedFxTests() + public SharedFxTests(ITestOutputHelper output) { + _output = output; _expectedTfm = "netcoreapp" + TestData.GetPackageVersion().Substring(0, 3); + _expectedRid = TestData.GetSharedFxRuntimeIdentifier(); + } + + [Fact] + public void PlatformManifestListsAllFiles() + { + var platformManifestPath = Path.Combine(TestData.GetManifestOutputDir(), "Microsoft.AspNetCore.App.PlatformManifest.txt"); + var expectedAssemblies = TestData.GetSharedFxDependencies() + .Split(';', StringSplitOptions.RemoveEmptyEntries) + .ToHashSet(); + + _output.WriteLine("==== file contents ===="); + _output.WriteLine(File.ReadAllText(platformManifestPath)); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', expectedAssemblies)); + + AssertEx.FileExists(platformManifestPath); + + var manifestFileLines = File.ReadAllLines(platformManifestPath); + + var actualAssemblies = manifestFileLines + .Where(s => !string.IsNullOrEmpty(s)) + .Select(i => + { + var fileName = i.Split('|')[0]; + return fileName.EndsWith(".dll", StringComparison.Ordinal) + ? fileName.Substring(0, fileName.Length - 4) + : fileName; + }) + .ToHashSet(); + + var missing = expectedAssemblies.Except(actualAssemblies); + var unexpected = actualAssemblies.Except(expectedAssemblies) + .Where(s => !string.Equals(s, "aspnetcorev2_inprocess", StringComparison.Ordinal)); // this native assembly only appears in Windows builds. + + if (_expectedRid.StartsWith("win", StringComparison.Ordinal) && !_expectedRid.Contains("arm")) + { + Assert.Contains("aspnetcorev2_inprocess", actualAssemblies); + } + + _output.WriteLine("==== missing assemblies from the manifest ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the manifest ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + + Assert.All(manifestFileLines, line => + { + var parts = line.Split('|'); + Assert.Equal(4, parts.Length); + Assert.Equal("Microsoft.AspNetCore.App", parts[1]); + if (parts[2].Length > 0) + { + Assert.True(Version.TryParse(parts[2], out _), "Assembly version must be convertable to System.Version"); + } + Assert.True(Version.TryParse(parts[3], out _), "File version must be convertable to System.Version"); + }); } [Fact] public void ItContainsValidRuntimeConfigFile() { - var runtimeConfigFilePath = Path.Combine(GetMetadataOutput(), "Microsoft.AspNetCore.App.runtimeconfig.json"); + var runtimeConfigFilePath = Path.Combine(TestData.GetMetadataOutput(), "Microsoft.AspNetCore.App.runtimeconfig.json"); AssertEx.FileExists(runtimeConfigFilePath); - AssertEx.FileDoesNotExists(Path.Combine(GetMetadataOutput(), "Microsoft.AspNetCore.App.runtimeconfig.dev.json")); + AssertEx.FileDoesNotExists(Path.Combine(TestData.GetMetadataOutput(), "Microsoft.AspNetCore.App.runtimeconfig.dev.json")); var runtimeConfig = JObject.Parse(File.ReadAllText(runtimeConfigFilePath)); @@ -36,11 +101,10 @@ public void ItContainsValidRuntimeConfigFile() [Fact] public void ItContainsValidDepsJson() { - var depsFilePath = Path.Combine(GetMetadataOutput(), "Microsoft.AspNetCore.App.deps.json"); - var rid = TestData.GetSharedFxRuntimeIdentifier(); + var depsFilePath = Path.Combine(TestData.GetMetadataOutput(), "Microsoft.AspNetCore.App.deps.json"); - var target = $".NETCoreApp,Version=v{TestData.GetPackageVersion().Substring(0, 3)}/{rid}"; - var ridPackageId = $"runtime.{rid}.Microsoft.AspNetCore.App"; + var target = $".NETCoreApp,Version=v{TestData.GetPackageVersion().Substring(0, 3)}/{_expectedRid}"; + var ridPackageId = $"runtime.{_expectedRid}.Microsoft.AspNetCore.App"; AssertEx.FileExists(depsFilePath); @@ -49,7 +113,7 @@ public void ItContainsValidDepsJson() Assert.Equal(target, (string)depsFile["runtimeTarget"]["name"]); Assert.NotNull(depsFile["compilationOptions"]); Assert.Empty(depsFile["compilationOptions"]); - Assert.NotEmpty(depsFile["runtimes"][rid]); + Assert.NotEmpty(depsFile["runtimes"][_expectedRid]); Assert.All(depsFile["libraries"], item => { var prop = Assert.IsType(item); @@ -59,7 +123,7 @@ public void ItContainsValidDepsJson() }); Assert.NotNull(depsFile["libraries"][$"Microsoft.AspNetCore.App/{TestData.GetPackageVersion()}"]); - Assert.NotNull(depsFile["libraries"][$"runtime.{rid}.Microsoft.AspNetCore.App/{TestData.GetPackageVersion()}"]); + Assert.NotNull(depsFile["libraries"][$"runtime.{_expectedRid}.Microsoft.AspNetCore.App/{TestData.GetPackageVersion()}"]); Assert.Equal(2, depsFile["libraries"].Values().Count()); var targetLibraries = depsFile["targets"][target]; @@ -73,17 +137,17 @@ public void ItContainsValidDepsJson() Assert.All(runtimeLibrary["runtime"], item => { var obj = Assert.IsType(item); - Assert.StartsWith($"runtimes/{rid}/lib/{_expectedTfm}/", obj.Name); + Assert.StartsWith($"runtimes/{_expectedRid}/lib/{_expectedTfm}/", obj.Name); Assert.NotEmpty(obj.Value["assemblyVersion"].Value()); Assert.NotEmpty(obj.Value["fileVersion"].Value()); }); - if (TestData.GetSharedFxRuntimeIdentifier().StartsWith("win")) + if (_expectedRid.StartsWith("win")) { Assert.All(runtimeLibrary["native"], item => { var obj = Assert.IsType(item); - Assert.StartsWith($"runtimes/{rid}/native/", obj.Name); + Assert.StartsWith($"runtimes/{_expectedRid}/native/", obj.Name); }); } else @@ -95,14 +159,12 @@ public void ItContainsValidDepsJson() [Fact] public void ItContainsVersionFile() { - var versionFile = Path.Combine(GetMetadataOutput(), ".version"); + var versionFile = Path.Combine(TestData.GetMetadataOutput(), ".version"); AssertEx.FileExists(versionFile); var lines = File.ReadAllLines(versionFile); Assert.Equal(2, lines.Length); Assert.Equal(TestData.GetRepositoryCommit(), lines[0]); Assert.Equal(TestData.GetPackageVersion(), lines[1]); } - - private string GetMetadataOutput() => TestData.GetTestDataValue("SharedFxMetadataOutput:Microsoft.AspNetCore.App"); } } diff --git a/src/Framework/test/TestData.cs b/src/Framework/test/TestData.cs index a33613aff80e..1e86e1f809be 100644 --- a/src/Framework/test/TestData.cs +++ b/src/Framework/test/TestData.cs @@ -16,6 +16,12 @@ public class TestData public static string GetSharedFxRuntimeIdentifier() => GetTestDataValue("SharedFxRid"); + public static string GetSharedFxDependencies() => GetTestDataValue("SharedFxDependencies"); + + public static string GetMetadataOutput() => GetTestDataValue("MetadataOutputPath"); + + public static string GetManifestOutputDir() => GetTestDataValue("ManifestOutputDir"); + public static string GetTestDataValue(string key) => typeof(TestData).Assembly.GetCustomAttributes().Single(d => d.Key == key).Value; }