From 4f2a0edc978d17d21f1b06ecc7f3526dd57958c2 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 25 Feb 2019 09:50:01 -0800 Subject: [PATCH 1/4] Update Azure queues for Linux and MacOS builds (#7231) - aspnet/AspNetCore-Internal#1717 - use a specific Linux image --- .azure/pipelines/jobs/default-build.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index 7e79628ce3..6e9547976a 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -73,11 +73,17 @@ jobs: ${{ if ne(parameters.poolName, '') }}: name: ${{ parameters.poolName }} ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'macOS')) }}: - name: Hosted macOS + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: Hosted Mac Internal + ${{ if ne(variables['System.TeamProject'], 'internal') }}: + name: Hosted macOS vmImage: macOS-10.13 ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'Linux')) }}: - name: Hosted Ubuntu 1604 - vmImage: ubuntu-16.04 + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: dnceng-linux-internal-temp + ${{ if ne(variables['System.TeamProject'], 'internal') }}: + name: dnceng-linux-external-temp + vmImage: Linux_Ubuntu_16.04 ${{ if and(eq(parameters.poolName, ''), eq(parameters.agentOs, 'Windows')) }}: ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: dotnet-internal-temp @@ -160,4 +166,3 @@ jobs: - task: MicroBuildCleanup@1 displayName: Cleanup MicroBuild tasks condition: always() - From 5661c41909d6bd9a7aac9ab79d1da750291b4478 Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Tue, 26 Feb 2019 09:12:51 -0800 Subject: [PATCH 2/4] Add baseline version test (#7627) --- test/SharedFx.UnitTests/ConsoleReporter.cs | 71 +++++++++++++++++++ test/SharedFx.UnitTests/RetryHelper.cs | 65 +++++++++++++++++ .../SharedFx.UnitTests.csproj | 5 ++ test/SharedFx.UnitTests/SharedFxTests.cs | 63 ++++++++++++++++ test/SharedFx.UnitTests/TestData.cs | 2 + 5 files changed, 206 insertions(+) create mode 100644 test/SharedFx.UnitTests/ConsoleReporter.cs create mode 100644 test/SharedFx.UnitTests/RetryHelper.cs diff --git a/test/SharedFx.UnitTests/ConsoleReporter.cs b/test/SharedFx.UnitTests/ConsoleReporter.cs new file mode 100644 index 0000000000..190e805dc2 --- /dev/null +++ b/test/SharedFx.UnitTests/ConsoleReporter.cs @@ -0,0 +1,71 @@ +// 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.IO; +using McMaster.Extensions.CommandLineUtils; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ConsoleReporter : IReporter + { + private object _writeLock = new object(); + + public ConsoleReporter(IConsole console) + : this(console, verbose: false, quiet: false) + { } + + public ConsoleReporter(IConsole console, bool verbose, bool quiet) + { + Console = console; + IsVerbose = verbose; + IsQuiet = quiet; + } + + protected IConsole Console { get; } + public bool IsVerbose { get; } + public bool IsQuiet { get; } + + protected virtual void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + lock (_writeLock) + { + if (color.HasValue) + { + Console.ForegroundColor = color.Value; + } + + writer.WriteLine(message); + + if (color.HasValue) + { + Console.ResetColor(); + } + } + } + + public virtual void Error(string message) + => WriteLine(Console.Error, message, ConsoleColor.Red); + public virtual void Warn(string message) + => WriteLine(Console.Out, message, ConsoleColor.Yellow); + + public virtual void Output(string message) + { + if (IsQuiet) + { + return; + } + WriteLine(Console.Out, message, color: null); + } + + public virtual void Verbose(string message) + { + if (!IsVerbose) + { + return; + } + + WriteLine(Console.Out, message, ConsoleColor.DarkGray); + } + } +} diff --git a/test/SharedFx.UnitTests/RetryHelper.cs b/test/SharedFx.UnitTests/RetryHelper.cs new file mode 100644 index 0000000000..2d92113e36 --- /dev/null +++ b/test/SharedFx.UnitTests/RetryHelper.cs @@ -0,0 +1,65 @@ +// 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.Threading.Tasks; +using McMaster.Extensions.CommandLineUtils; + +namespace TriageBuildFailures +{ + internal static class RetryHelpers + { + /// + /// Constrain the exponential back-off to this many minutes. + /// + private const int MaxRetryMinutes = 15; + + private static int TotalRetriesUsed; + + public static int GetTotalRetriesUsed() + { + return TotalRetriesUsed; + } + + public static async Task RetryAsync(Func action, IReporter reporter) + { + await RetryAsync( + async () => + { + await action(); + return null; + }, + reporter); + } + + public static async Task RetryAsync(Func> action, IReporter reporter) + { + Exception firstException = null; + + var retriesRemaining = 10; + var retryDelayInMinutes = 1; + + while (retriesRemaining > 0) + { + try + { + return await action(); + } + catch (Exception e) + { + firstException = firstException ?? e; + reporter.Output($"Exception thrown! {e.Message}"); + reporter.Output($"Waiting {retryDelayInMinutes} minute(s) to retry ({retriesRemaining} left)..."); + await Task.Delay(retryDelayInMinutes * 60 * 1000); + + // Do exponential back-off, but limit it (1, 2, 4, 8, 15, 15, 15, ...) + // With MaxRetryMinutes=15 and MaxRetries=10, this will delay a maximum of 105 minutes + retryDelayInMinutes = Math.Min(2 * retryDelayInMinutes, MaxRetryMinutes); + retriesRemaining--; + TotalRetriesUsed++; + } + } + throw new InvalidOperationException("Max exception retries reached, giving up.", firstException); + } + } +} diff --git a/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj b/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj index e574f7d305..e439e2842b 100644 --- a/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj +++ b/test/SharedFx.UnitTests/SharedFx.UnitTests.csproj @@ -26,6 +26,10 @@ <_Parameter1>MicrosoftNETCoreAppPackageVersion <_Parameter2>$(RuntimeFrameworkVersion) + + <_Parameter1>PreviousAspNetCoreReleaseVersion + <_Parameter2>$(PreviousAspNetCoreReleaseVersion) + @@ -34,6 +38,7 @@ + diff --git a/test/SharedFx.UnitTests/SharedFxTests.cs b/test/SharedFx.UnitTests/SharedFxTests.cs index 36160360df..74956cde87 100644 --- a/test/SharedFx.UnitTests/SharedFxTests.cs +++ b/test/SharedFx.UnitTests/SharedFxTests.cs @@ -1,14 +1,77 @@ // 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.IO.Compression; +using System.Net; +using System.Reflection; +using System.Threading.Tasks; +using McMaster.Extensions.CommandLineUtils; using Newtonsoft.Json.Linq; +using TriageBuildFailures; using Xunit; namespace Microsoft.AspNetCore { public class SharedFxTests { + + [Theory] + [MemberData(nameof(GetSharedFxConfig))] + public async Task BaselineTest(SharedFxConfig config) + { + var previousVersion = TestData.GetPreviousAspNetCoreReleaseVersion(); + var url = new Uri($"https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/" + previousVersion + "/aspnetcore-runtime-internal-" + previousVersion + "-win-x64.zip"); + var zipName = "assemblies.zip"; + var nugetAssemblyVersions = new Dictionary(); + var root = TestData.GetDotNetRoot(); + var dir = Path.Combine(root, "shared", config.Name, config.Version); + + using (var testClient = new WebClient()) + { + var reporter = new ConsoleReporter(PhysicalConsole.Singleton); + await RetryHelpers.RetryAsync(async () => await testClient.DownloadFileTaskAsync(url, zipName), reporter); + } + + var zipPath = Path.Combine(AppContext.BaseDirectory, zipName); + + if (!Directory.Exists(AppContext.BaseDirectory + "unzipped")) + { + ZipFile.ExtractToDirectory(AppContext.BaseDirectory, "unzipped"); + } + + var nugetAssembliesPath = Path.Combine(AppContext.BaseDirectory, "unzipped", "shared", config.Name, previousVersion); + + var files = Directory.GetFiles(nugetAssembliesPath, "*.dll"); + foreach (var file in files) + { + try + { + var assemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + nugetAssemblyVersions.Add(dllName, assemblyVersion); + } + catch (BadImageFormatException) { } + } + + files = Directory.GetFiles(dir, "*.dll"); + + Assert.All(files, file => + { + try + { + var localAssemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + Assert.True(nugetAssemblyVersions.ContainsKey(dllName), $"Expected {dllName} to be in the downloaded dlls"); + Assert.True(localAssemblyVersion.CompareTo(nugetAssemblyVersions[dllName]) >= 0, $"Expected the local version of {dllName} to be greater than or equal to the already released version."); + } + catch (BadImageFormatException) { } + + }); + } + [Theory] [MemberData(nameof(GetSharedFxConfig))] public void ItContainsValidRuntimeConfigFile(SharedFxConfig config) diff --git a/test/SharedFx.UnitTests/TestData.cs b/test/SharedFx.UnitTests/TestData.cs index eb01f60e8b..dd024ae3bd 100644 --- a/test/SharedFx.UnitTests/TestData.cs +++ b/test/SharedFx.UnitTests/TestData.cs @@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore { public static string GetPackageVersion() => GetTestDataValue("PackageVersion"); + public static string GetPreviousAspNetCoreReleaseVersion() => GetTestDataValue("PreviousAspNetCoreReleaseVersion"); + public static string GetMicrosoftNETCoreAppPackageVersion() => GetTestDataValue("MicrosoftNETCoreAppPackageVersion"); public static string GetDotNetRoot() => GetTestDataValue("DotNetRoot"); From f8c3f02345045c42a49ada0dc9f5f06d0dd8dc92 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 26 Feb 2019 16:50:35 -0800 Subject: [PATCH 3/4] [2.1. test only] Remove checks for Microsoft.VisualStudio.Web.CodeGeneration.Design in templates (#7983) - see aspnet/AspNetCore-Internal#1759 --- src/Templating/test/Templates.Test/MvcTemplateTest.cs | 4 ++-- src/Templating/test/Templates.Test/RazorPagesTemplateTest.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Templating/test/Templates.Test/MvcTemplateTest.cs b/src/Templating/test/Templates.Test/MvcTemplateTest.cs index e8bb66ed4b..07a6e9f683 100644 --- a/src/Templating/test/Templates.Test/MvcTemplateTest.cs +++ b/src/Templating/test/Templates.Test/MvcTemplateTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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 Microsoft.AspNetCore.Testing.xunit; @@ -112,7 +112,7 @@ namespace Templates.Test { Assert.Contains(".db", projectFileContents); } - Assert.Contains("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); + Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); if (targetFrameworkOverride != null) { diff --git a/src/Templating/test/Templates.Test/RazorPagesTemplateTest.cs b/src/Templating/test/Templates.Test/RazorPagesTemplateTest.cs index 314f72cb1d..639efb9dc8 100644 --- a/src/Templating/test/Templates.Test/RazorPagesTemplateTest.cs +++ b/src/Templating/test/Templates.Test/RazorPagesTemplateTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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 Microsoft.AspNetCore.Testing.xunit; @@ -92,7 +92,7 @@ namespace Templates.Test { Assert.Contains(".db", projectFileContents); } - Assert.Contains("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); + Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents); if (targetFrameworkOverride != null) { From d2a4435ac8072edc97adb6f15c165698e4d6795f Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Thu, 28 Feb 2019 17:11:23 -0800 Subject: [PATCH 4/4] Update baseline test (#8014) --- test/SharedFx.UnitTests/SharedFxTests.cs | 55 +++++++++++++----------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/test/SharedFx.UnitTests/SharedFxTests.cs b/test/SharedFx.UnitTests/SharedFxTests.cs index 74956cde87..7d0c222298 100644 --- a/test/SharedFx.UnitTests/SharedFxTests.cs +++ b/test/SharedFx.UnitTests/SharedFxTests.cs @@ -36,40 +36,45 @@ namespace Microsoft.AspNetCore } var zipPath = Path.Combine(AppContext.BaseDirectory, zipName); + var tempDirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - if (!Directory.Exists(AppContext.BaseDirectory + "unzipped")) + try { - ZipFile.ExtractToDirectory(AppContext.BaseDirectory, "unzipped"); - } + Directory.CreateDirectory(tempDirectoryPath); + ZipFile.ExtractToDirectory(zipPath, tempDirectoryPath); + var nugetAssembliesPath = Path.Combine(tempDirectoryPath, "shared", config.Name, previousVersion); - var nugetAssembliesPath = Path.Combine(AppContext.BaseDirectory, "unzipped", "shared", config.Name, previousVersion); - - var files = Directory.GetFiles(nugetAssembliesPath, "*.dll"); - foreach (var file in files) - { - try + var files = Directory.GetFiles(nugetAssembliesPath, "*.dll"); + foreach (var file in files) { - var assemblyVersion = AssemblyName.GetAssemblyName(file).Version; - var dllName = Path.GetFileName(file); - nugetAssemblyVersions.Add(dllName, assemblyVersion); + try + { + var assemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + nugetAssemblyVersions.Add(dllName, assemblyVersion); + } + catch (BadImageFormatException) { } } - catch (BadImageFormatException) { } - } - files = Directory.GetFiles(dir, "*.dll"); + files = Directory.GetFiles(dir, "*.dll"); - Assert.All(files, file => - { - try + Assert.All(files, file => { - var localAssemblyVersion = AssemblyName.GetAssemblyName(file).Version; - var dllName = Path.GetFileName(file); - Assert.True(nugetAssemblyVersions.ContainsKey(dllName), $"Expected {dllName} to be in the downloaded dlls"); - Assert.True(localAssemblyVersion.CompareTo(nugetAssemblyVersions[dllName]) >= 0, $"Expected the local version of {dllName} to be greater than or equal to the already released version."); - } - catch (BadImageFormatException) { } + try + { + var localAssemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + Assert.Contains(dllName, nugetAssemblyVersions.Keys); + Assert.InRange(localAssemblyVersion.CompareTo(nugetAssemblyVersions[dllName]), 0, int.MaxValue); + } + catch (BadImageFormatException) { } - }); + }); + } + finally + { + Directory.Delete(tempDirectoryPath, true); + } } [Theory]