From 9593c1967c1740c62ffc824a1837bc2f3c4ab1bf Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 29 Mar 2024 16:40:49 -0700 Subject: [PATCH 01/34] improve Peaky tests and environment configuration --- Directory.Packages.props | 8 +- Dockerfile | 1 - PeakyTests.ipynb | 2 +- .../PeakyTestDiscovery.cs | 4 +- .../PeakyTests.cs | 4 +- .../CommandExecutionTests.cs | 134 +++++++++--------- src/Microsoft.TryDotNet/ContentGenerator.cs | 34 ++--- .../PeakyTests/AgentTests.cs | 67 --------- .../PeakyTests/EnvironmentSettings.cs | 39 +---- .../PeakyTests/OrchestratorDeploymentTests.cs | 49 +------ .../PeakyTests/SelfTests.cs | 103 ++++++++++++++ src/Microsoft.TryDotNet/Program.cs | 55 ++++--- .../Properties/launchSettings.json | 25 +++- 13 files changed, 256 insertions(+), 269 deletions(-) delete mode 100644 src/Microsoft.TryDotNet/PeakyTests/AgentTests.cs create mode 100644 src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index ab56aaee6..4ae03b4a0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,11 +12,11 @@ - + - - - + + + diff --git a/Dockerfile b/Dockerfile index 99b361c5d..14a2b402b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,7 +39,6 @@ COPY --from=build-env /App/out . # Set up to run and expose app on port 80 EXPOSE 80 -ENV ASPNETCORE_ENVIRONMENT=Production ENV ASPNETCORE_URLS=http://*:80/ # This is a workaround for the fact that the Try .NET website is not yet container-aware diff --git a/PeakyTests.ipynb b/PeakyTests.ipynb index 2ddfbeac8..75a0b67dc 100644 --- a/PeakyTests.ipynb +++ b/PeakyTests.ipynb @@ -41,7 +41,7 @@ "outputs": [], "source": [ "var tests = await peakyClient.GetTestsAsync();\n", - "tests" + "tests.Display();" ] }, { diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PeakyTestDiscovery.cs b/src/Microsoft.TryDotNet.IntegrationTests/PeakyTestDiscovery.cs index ea0b6cf99..2c4e348c8 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/PeakyTestDiscovery.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/PeakyTestDiscovery.cs @@ -7,13 +7,11 @@ namespace Microsoft.TryDotNet.IntegrationTests; -public class PeakyTestDiscovery : PeakyXunitTestBase, IDisposable +public class PeakyTestDiscovery : PeakyXunitTestBase { private static readonly Uri _testDiscoveryUri = new("https://mls-monitoring.azurewebsites.net/tests/staging/orchestrator?deployment=true"); private readonly PeakyClient _peakyClient = new(_testDiscoveryUri); public override PeakyClient PeakyClient => _peakyClient; - - public void Dispose() => _peakyClient.Dispose(); } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PeakyTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/PeakyTests.cs index 94822f260..0590e04e7 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/PeakyTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/PeakyTests.cs @@ -11,7 +11,7 @@ namespace Microsoft.TryDotNet.IntegrationTests; -public class PeakyTests : IDisposable +public class PeakyTests { private readonly ITestOutputHelper _output; @@ -32,6 +32,4 @@ public async Task The_peaky_test_passes(Uri url) result.Passed.Should().BeTrue(); } - - public void Dispose() => _peakyClient.Dispose(); } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs b/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs index 0da275f30..67f9113c1 100644 --- a/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs +++ b/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs @@ -11,51 +11,53 @@ namespace Microsoft.TryDotNet.Tests; public class CommandExecutionTests { - [Fact(Skip = "Failing in CI")] + [Fact] public async Task can_compile_projects_with_user_code_in_region() { await using var applicationBuilderFactory = new WebApplicationFactory(); var c = applicationBuilderFactory.CreateDefaultClient(); - var requests = @"{ - ""commands"": [ - { - ""commandType"": ""OpenProject"", - ""command"": { - ""project"": { - ""files"": [ - { - ""relativeFilePath"": ""program.cs"", - ""content"": ""using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\n\nnamespace Program\n{\n class Program\n {\n static void Main(string[] args)\n {\n #region controller\n\n #endregion\n }\n }\n}"" - } - ] - } - }, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22||6"" - }, - { - ""commandType"": ""OpenDocument"", - ""command"": { - ""relativeFilePath"": ""./program.cs"", - ""regionName"": ""controller"" - }, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22||7"" - }, - { - ""commandType"": ""SubmitCode"", - ""command"": { - ""code"": ""var a = 123;"" - }, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22||8"" - }, - { - ""commandType"": ""CompileProject"", - ""command"": {}, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22"" - } - ] -}"; + var requests = """ + { + "commands": [ + { + "commandType": "OpenProject", + "command": { + "project": { + "files": [ + { + "relativeFilePath": "program.cs", + "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\n\nnamespace Program\n{\n class Program\n {\n static void Main(string[] args)\n {\n #region controller\n\n #endregion\n }\n }\n}" + } + ] + } + }, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22||6" + }, + { + "commandType": "OpenDocument", + "command": { + "relativeFilePath": "./program.cs", + "regionName": "controller" + }, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22||7" + }, + { + "commandType": "SubmitCode", + "command": { + "code": "var a = 123;" + }, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22||8" + }, + { + "commandType": "CompileProject", + "command": {}, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22" + } + ] + } + """; var requestBody = JsonContent.Create(JsonDocument.Parse(requests).RootElement); @@ -82,32 +84,34 @@ public async Task can_open_document_with_user_code_in_region() var c = applicationBuilderFactory.CreateDefaultClient(); - var requests = @"{ - ""commands"": [ - { - ""commandType"": ""OpenProject"", - ""command"": { - ""project"": { - ""files"": [ - { - ""relativeFilePath"": ""program.cs"", - ""content"": ""using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\n\nnamespace Program\n{\n class Program\n {\n static void Main(string[] args)\n {\n #region controller\nConsole.WriteLine(123);\n #endregion\n }\n }\n}"" - } - ] - } - }, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22||6"" - }, - { - ""commandType"": ""OpenDocument"", - ""command"": { - ""relativeFilePath"": ""program.cs"", - ""regionName"": ""controller"" - }, - ""token"": ""595d327c-b14f-5ad7-7da0-2579cbfa9961::22||7"" - } - ] -}"; + var requests = """ + { + "commands": [ + { + "commandType": "OpenProject", + "command": { + "project": { + "files": [ + { + "relativeFilePath": "program.cs", + "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\n\nnamespace Program\n{\n class Program\n {\n static void Main(string[] args)\n {\n #region controller\nConsole.WriteLine(123);\n #endregion\n }\n }\n}" + } + ] + } + }, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22||6" + }, + { + "commandType": "OpenDocument", + "command": { + "relativeFilePath": "program.cs", + "regionName": "controller" + }, + "token": "595d327c-b14f-5ad7-7da0-2579cbfa9961::22||7" + } + ] + } + """; var requestBody = JsonContent.Create(JsonDocument.Parse(requests).RootElement); diff --git a/src/Microsoft.TryDotNet/ContentGenerator.cs b/src/Microsoft.TryDotNet/ContentGenerator.cs index 1fe290a38..0fdf34581 100644 --- a/src/Microsoft.TryDotNet/ContentGenerator.cs +++ b/src/Microsoft.TryDotNet/ContentGenerator.cs @@ -38,22 +38,24 @@ public static Task GenerateEditorPageAsync(HttpRequest request) var configString = JsonSerializer.Serialize(configuration); - var value =$@" - - - - TryDotNet Editor - - - - - - - - - - -"; + var value =$""" + + + + + TryDotNet Editor + + + + + + + + + + + + """; return Task.FromResult(value); } diff --git a/src/Microsoft.TryDotNet/PeakyTests/AgentTests.cs b/src/Microsoft.TryDotNet/PeakyTests/AgentTests.cs deleted file mode 100644 index 1f5da491a..000000000 --- a/src/Microsoft.TryDotNet/PeakyTests/AgentTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#nullable disable - -using System.Net; -using System.Text; -using Newtonsoft.Json; -using Peaky; - -namespace Microsoft.TryDotNet.PeakyTests; - -public class AgentTests : IPeakyTest, IApplyToApplication -{ - private readonly HttpClientWithTelemetry _httpClient; - - public AgentTests(HttpClientWithTelemetry httpClient) - { - _httpClient = httpClient; - } - - public async Task Valid_script_code_sent_to_run_endpoint_returns_200() - { - await RunCode( - "/workspace/run", - "Console.WriteLine(\"{0}!\");"); - } - - public async Task Valid_console_app_code_sent_to_run_endpoint_returns_200() - { - await RunCode( - "/workspace/run", - "using System;\n namespace Test {{public class Program\n {{\n public static void Main()\n {{\n Console.WriteLine(\"{0}!\");\n }}\n }}}}", - "console"); - } - - private async Task RunCode(string uri, string sourceCode, string workspaceType = null) - { - var guidForConsoleOutput = Guid.NewGuid().ToString(); - - var sourceCodeJson = JsonConvert.SerializeObject(new - { - source = string.Format(sourceCode, guidForConsoleOutput), - workspaceType - }); - - var contentPost = new StringContent(sourceCodeJson, Encoding.UTF8, "application/json"); - - var request = new HttpRequestMessage - { - Content = contentPost, - Method = HttpMethod.Post, - RequestUri = new Uri(uri, UriKind.RelativeOrAbsolute) - }; - - var response = await _httpClient.SendAsync(request); - - response.ShouldSucceed(HttpStatusCode.OK); - - return await response.Content.ReadAsStringAsync(); - } - - public bool AppliesToApplication(string application) - { - return application == "trydotnet"; - } -} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet/PeakyTests/EnvironmentSettings.cs b/src/Microsoft.TryDotNet/PeakyTests/EnvironmentSettings.cs index 54da6e16f..03b88c67a 100644 --- a/src/Microsoft.TryDotNet/PeakyTests/EnvironmentSettings.cs +++ b/src/Microsoft.TryDotNet/PeakyTests/EnvironmentSettings.cs @@ -5,44 +5,13 @@ namespace Microsoft.TryDotNet.PeakyTests; -public class EnvironmentSettings : IEquatable +public record EnvironmentSettings(string RegionId, string HostOrigin, bool IsHttpsEnabled) { - public string HostOrigin { get; set; } + public static EnvironmentSettings ForLocal { get; } = new("localhost", "http://localhost:7061", false); - public bool IsHttpsEnabled { get; set; } + public static EnvironmentSettings ForProduction { get; } = new("production", "https://trydotnet.microsoft.com", true); - public string RegionId { get; set; } - - public static EnvironmentSettings ForLocal { get; } = new() - { - HostOrigin = "http://localhost:7061", - IsHttpsEnabled = false, - RegionId = "localhost" - }; - - public static EnvironmentSettings ForProduction { get; } = new() - { - HostOrigin = "https://trydotnet.microsoft.com", - IsHttpsEnabled = true, - RegionId = "production" - }; - - public static EnvironmentSettings ForPreProduction { get; } = new() - { - HostOrigin = "https://try-ppe.dot.net/", - IsHttpsEnabled = true, - RegionId = "ppe" - }; - - public override bool Equals(object obj) => Equals(obj as EnvironmentSettings); - - public override int GetHashCode() => throw new NotSupportedException(); - - public bool Equals(EnvironmentSettings other) => - other != null && - HostOrigin.Equals(other.HostOrigin) && - IsHttpsEnabled == other.IsHttpsEnabled && - RegionId.Equals(other.RegionId); + public static EnvironmentSettings ForPreProduction { get; } = new("ppe", "https://try-ppe.dot.net/", true); public override string ToString() { diff --git a/src/Microsoft.TryDotNet/PeakyTests/OrchestratorDeploymentTests.cs b/src/Microsoft.TryDotNet/PeakyTests/OrchestratorDeploymentTests.cs index 6c6bf4245..7ff5c0965 100644 --- a/src/Microsoft.TryDotNet/PeakyTests/OrchestratorDeploymentTests.cs +++ b/src/Microsoft.TryDotNet/PeakyTests/OrchestratorDeploymentTests.cs @@ -11,13 +11,13 @@ namespace Microsoft.TryDotNet.PeakyTests; -public class OrchestratorDeploymentTests : IPeakyTest, IApplyToApplication, IHaveTags +public class ExternalTests : IPeakyTest, IApplyToApplication, IHaveTags { private readonly HttpClientWithTelemetry _httpClient; private readonly HttpClientWithXsrfCookies _httpClientWithXsrfCookies; private readonly TestTarget _testTarget; - public OrchestratorDeploymentTests( + public ExternalTests( HttpClientWithTelemetry httpClient, HttpClientWithXsrfCookies httpClientWithXsrfCookies, TestTarget testTarget) @@ -136,46 +136,7 @@ public async Task Snippet_without_Xsrf_returns_401() return await response.Content.ReadAsStringAsync(); } - - public async Task Compile_of_valid_workspace_with_Xsrf_and_hostOrigin_returns_200() - { - var cacheAvoidingValue = Guid.NewGuid().ToString(); - - var sourceCode = $"using System;\n public class Program\n {{\n public static void Main()\n {{\n Console.WriteLine(\"{cacheAvoidingValue}!\");\n }}\n }}"; - - var workspace = new - { - workspaceType = "script", - buffers = new[] - { - new - { - id = "Program.cs", - content = sourceCode, - position = 0 - } - - } - }; - - var contentPost = new StringContent(JsonConvert.SerializeObject(workspace), Encoding.UTF8, "application/json"); - - var request = new HttpRequestMessage - { - Content = contentPost, - Method = HttpMethod.Post, - RequestUri = new Uri("/workspace/run?hostOrigin=https%3A%2F%2Ftry.dot.net%2F", UriKind.RelativeOrAbsolute) - }; - - var response = await _httpClientWithXsrfCookies.SendAsync(request); - - response.ShouldSucceed(HttpStatusCode.OK); - - var result = await response.Content.ReadAsStringAsync(); - - result.Should().Contain(cacheAvoidingValue); - } - + public async Task Compile_without_Xsrf_returns_400() { var cacheAvoidingValue = Guid.NewGuid(); @@ -185,7 +146,7 @@ public async Task Compile_without_Xsrf_returns_400() var workspace = new { - workspaceType = "script", + workspaceType = "console", buffers = new[] { new @@ -223,7 +184,7 @@ public async Task Compile_without_hostOrigin_returns_401() var workspace = new { - workspaceType = "script", + workspaceType = "console", buffers = new[] { new diff --git a/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs new file mode 100644 index 000000000..5676f9c9e --- /dev/null +++ b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs @@ -0,0 +1,103 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#nullable disable +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.DotNet.Interactive; +using Microsoft.DotNet.Interactive.Commands; +using Microsoft.DotNet.Interactive.CSharpProject; +using Microsoft.DotNet.Interactive.CSharpProject.Build; +using Microsoft.DotNet.Interactive.CSharpProject.Commands; +using Microsoft.DotNet.Interactive.Events; +using Peaky; + +namespace Microsoft.TryDotNet.PeakyTests; + +public class SelfTests : IPeakyTest, IHaveTags, IApplyToApplication +{ + public async Task Console_package_is_prebuilt() + { + var package = await Package.GetOrCreateConsolePackageAsync(enableBuild: false); + + package.Directory.Exists.Should().BeTrue(); + + var subdirectories = package.Directory.GetDirectories(); + + subdirectories.Should().Contain(d => d.Name == "bin"); + subdirectories.Should().Contain(d => d.Name == "obj"); + package.Directory.GetFiles().Should().Contain(f => f.Name == "console.csproj.interactive.workspaceData.cache"); + + return package; + } + + public async Task Can_get_signature_help() + { + using var kernel = await Program.CreateKernelAsync(); + + await kernel.SendAsync(new OpenProject(new Project(new[] { new ProjectFile("Program.cs", @"// content will be replaced") }))); + await kernel.SendAsync(new OpenDocument("Program.cs")); + + var code = """ + + public class Program + { + public static void Main(string[] args) + { + var fileInfo = new System.IO.FileInfo("test.file"); + fileInfo.CopyTo( + } + } + + """; + + var result = await kernel.SendAsync(new RequestSignatureHelp(code, new LinePosition(6, 24))); + using var _ = new AssertionScope(); + + var sigHelpProduced = result.Events + .Should() + .ContainSingle(e => e is SignatureHelpProduced) + .Which + .As(); + + sigHelpProduced + .ActiveSignatureIndex + .Should() + .Be(0); + sigHelpProduced + .ActiveParameterIndex + .Should() + .Be(0); + sigHelpProduced + .Signatures + .Should() + .BeEquivalentTo(new[] + { + new SignatureInformation( + "FileInfo FileInfo.CopyTo(string destFileName)", + new FormattedValue("text/markdown", "Copies an existing file to a new file, disallowing the overwriting of an existing file."), + new[] + { + new ParameterInformation( + "string destFileName", + new FormattedValue("text/markdown", "**destFileName**: The name of the new file to copy to.")) + }), + new SignatureInformation( + "FileInfo FileInfo.CopyTo(string destFileName, bool overwrite)", + new FormattedValue("text/markdown", "Copies an existing file to a new file, allowing the overwriting of an existing file."), + new[] + { + new ParameterInformation( + "string destFileName", + new FormattedValue("text/markdown", "**destFileName**: The name of the new file to copy to.")), + new ParameterInformation( + "bool overwrite", + new FormattedValue("text/markdown", "**overwrite**: true to allow an existing file to be overwritten; otherwise, false.")) + }) + }); + } + + public string[] Tags => new[] { "kernel" }; + + public bool AppliesToApplication(string application) => application == "trydotnet"; +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 8976f2341..0ac91b393 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -14,9 +14,10 @@ namespace Microsoft.TryDotNet; public class Program { - public static void Main(string[] args) + private static Package _consolePackage; { var app = CreateWebApplication(new WebApplicationOptions { Args = args }); + var app = await CreateWebApplicationAsync(new WebApplicationOptions { Args = args }); app.Run(); } @@ -32,45 +33,36 @@ public static IEnumerable ReadCommands(JsonElement bundl } } - public static WebApplication CreateWebApplication(WebApplicationOptions options) + public static async Task CreateWebApplicationAsync(WebApplicationOptions options) { var builder = WebApplication.CreateBuilder(options); builder.Services.AddCors( opts => opts.AddPolicy("trydotnet", policy => policy.AllowAnyOrigin())); - EnvironmentSettings environmentSettings; + _consolePackage = await Package.GetOrCreateConsolePackageAsync(enableBuild: false); - // FIX: (CreateWebApplication) - // if (builder.Environment.IsProduction()) - // { - builder.Services.AddProductionEnvironmentSettings(out environmentSettings); - - builder.Services.AddHostOriginAuth(new HostOriginPolicies(HostOriginPolicies.ForProduction)); - // } - // else - // { - // builder.Services.AddLocalEnvironmentSettings(out environmentSettings); - // - // builder.Services.AddHostOriginAuth(new HostOriginPolicies(HostOriginPolicies.ForLocal)); - // - // builder.Services.AddDataProtection(); - // } - - builder.Services.AddPeakyTests(registry => - registry.Add( - "production", - "trydotnet", - new Uri(environmentSettings.HostOrigin))); - - builder.Services.AddTransient(_ => new TestPageRenderer("/peaky.js", styleSheets: new[] { new PathString("/peaky.css") })); + builder.Services.AddPeakyTests(tests => + { + tests.Add( + "Development", + "trydotnet", + new Uri(EnvironmentSettings.ForLocal.HostOrigin)); + tests.Add( + "Staging", + "trydotnet", + new Uri(EnvironmentSettings.ForPreProduction.HostOrigin)); + tests.Add( + "Production", + "trydotnet", + new Uri(EnvironmentSettings.ForProduction.HostOrigin)); + }); CSharpProjectKernel.RegisterEventsAndCommands(); var app = builder.Build(); - // FIX: (CreateWebApplication) why is this commented out? - // app.UseHttpsRedirection(); + app.UseHttpsRedirection(); app.UseCors("trydotnet"); app.UseBlazorFrameworkFiles("/wasmrunner"); app.UsePeaky(); @@ -91,7 +83,8 @@ public static WebApplication CreateWebApplication(WebApplicationOptions options) await using (var requestBody = request.Body) { - using var kernel = new CSharpProjectKernel("project-kernel"); + using var kernel = await CreateKernelAsync(); + var body = await new StreamReader(requestBody).ReadToEndAsync(); var bundle = JsonDocument.Parse(body).RootElement; @@ -114,4 +107,8 @@ public static WebApplication CreateWebApplication(WebApplicationOptions options) return app; } + internal static async Task CreateKernelAsync() + { + return new CSharpProjectKernel("csharp.console", PackageFinder.Create(() => Task.FromResult(_consolePackage))); + } } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet/Properties/launchSettings.json b/src/Microsoft.TryDotNet/Properties/launchSettings.json index 56fb57b55..dbddb5333 100644 --- a/src/Microsoft.TryDotNet/Properties/launchSettings.json +++ b/src/Microsoft.TryDotNet/Properties/launchSettings.json @@ -9,7 +9,7 @@ } }, "profiles": { - "Microsoft.TryDotNet": { + "TryDotNet-Development": { "commandName": "Project", "launchBrowser": true, "launchUrl": "editor", @@ -19,6 +19,29 @@ "applicationUrl": "https://localhost:7061;http://localhost:5061", "dotnetRunMessages": true }, + + "TryDotNet-Staging": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "editor", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Staging" + }, + "applicationUrl": "https://localhost:7061;http://localhost:5061", + "dotnetRunMessages": true + }, + + "TryDotNet-Production": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "editor", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production" + }, + "applicationUrl": "https://localhost:7061;http://localhost:5061", + "dotnetRunMessages": true + }, + "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, From 7d104b41be51e464827cce424108b5946c8e5f51 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 29 Mar 2024 16:41:04 -0700 Subject: [PATCH 02/34] prebuild console package at app startup --- Directory.Packages.props | 5 +--- .../ApiEndpointSimulatorGenerator.cs | 1 - .../PeakyTests/SelfTests.cs | 2 +- src/Microsoft.TryDotNet/Program.cs | 23 +++++++++++++------ 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4ae03b4a0..9a6d348f8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,6 @@ true - @@ -12,7 +11,7 @@ - + @@ -27,9 +26,7 @@ - - \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.SimulatorGenerator/ApiEndpointSimulatorGenerator.cs b/src/Microsoft.TryDotNet.SimulatorGenerator/ApiEndpointSimulatorGenerator.cs index 3a85cb9da..cb75d7bd6 100644 --- a/src/Microsoft.TryDotNet.SimulatorGenerator/ApiEndpointSimulatorGenerator.cs +++ b/src/Microsoft.TryDotNet.SimulatorGenerator/ApiEndpointSimulatorGenerator.cs @@ -508,7 +508,6 @@ static void Main(string[] args){ private static async Task ExecuteScenario(ApiContractScenario scenario) { - await using var applicationBuilderFactory = new WebApplicationFactory(); var c = applicationBuilderFactory.CreateDefaultClient(); diff --git a/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs index 5676f9c9e..5ede125b3 100644 --- a/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs +++ b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs @@ -33,7 +33,7 @@ public async Task Console_package_is_prebuilt() public async Task Can_get_signature_help() { - using var kernel = await Program.CreateKernelAsync(); + using var kernel = Program.CreateKernel(); await kernel.SendAsync(new OpenProject(new Project(new[] { new ProjectFile("Program.cs", @"// content will be replaced") }))); await kernel.SendAsync(new OpenDocument("Program.cs")); diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 0ac91b393..58af4920a 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -6,6 +6,7 @@ using System.Text.Json; using Microsoft.DotNet.Interactive.Connection; using Microsoft.DotNet.Interactive.CSharpProject; +using Microsoft.DotNet.Interactive.CSharpProject.Build; using Microsoft.DotNet.Interactive.Events; using Microsoft.TryDotNet.PeakyTests; using Peaky; @@ -14,15 +15,18 @@ namespace Microsoft.TryDotNet; public class Program { - private static Package _consolePackage; + private static Package? _consolePackage; + + public static async Task Main(string[] args) { - var app = CreateWebApplication(new WebApplicationOptions { Args = args }); + await EnsurePrebuildPackageIsReadyAsync(); + var app = await CreateWebApplicationAsync(new WebApplicationOptions { Args = args }); - app.Run(); + await app.RunAsync(); } - public static IEnumerable ReadCommands(JsonElement bundle) + private static IEnumerable ReadCommands(JsonElement bundle) { foreach (var commandEnvelope in bundle.GetProperty("commands").EnumerateArray()) { @@ -83,7 +87,7 @@ public static async Task CreateWebApplicationAsync(WebApplicatio await using (var requestBody = request.Body) { - using var kernel = await CreateKernelAsync(); + using var kernel = CreateKernel(); var body = await new StreamReader(requestBody).ReadToEndAsync(); @@ -107,8 +111,13 @@ public static async Task CreateWebApplicationAsync(WebApplicatio return app; } - internal static async Task CreateKernelAsync() + + private static async Task EnsurePrebuildPackageIsReadyAsync() { - return new CSharpProjectKernel("csharp.console", PackageFinder.Create(() => Task.FromResult(_consolePackage))); + var package = await Package.GetOrCreateConsolePackageAsync(true); + await package.EnsureReadyAsync(); } + + internal static CSharpProjectKernel CreateKernel() => + new("csharp.console", PackageFinder.Create(() => Task.FromResult(_consolePackage))); } \ No newline at end of file From 1767d210673f2f81f34e5620e9457af549f28727 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 1 Apr 2024 13:21:13 -0700 Subject: [PATCH 03/34] turn off HTTPS redirection --- src/Microsoft.TryDotNet/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 58af4920a..22c75bfd6 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -66,7 +66,7 @@ public static async Task CreateWebApplicationAsync(WebApplicatio var app = builder.Build(); - app.UseHttpsRedirection(); + // app.UseHttpsRedirection(); app.UseCors("trydotnet"); app.UseBlazorFrameworkFiles("/wasmrunner"); app.UsePeaky(); From 258f07026987c0f816c8a0b08b31d0843d80cee3 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 1 Apr 2024 13:21:25 -0700 Subject: [PATCH 04/34] remove empty cell --- Developer-guide.ipynb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Developer-guide.ipynb b/Developer-guide.ipynb index d9191a281..2c3a02a5c 100644 --- a/Developer-guide.ipynb +++ b/Developer-guide.ipynb @@ -376,11 +376,6 @@ "\n", "The core of Try .NET is powered by the `CSharpProjectKernel`, which serves as the backend for .NET Interactive." ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] } ], "metadata": { From 77f9b62d9f3550fc945c2b6dd4ccb4396667da9b Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 2 Apr 2024 10:43:36 -0700 Subject: [PATCH 05/34] TrySetException --- src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs index 7eaf39a36..d7fb23097 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs @@ -21,7 +21,9 @@ public async Task Start() var uriFound = false; _process = CommandLine.StartProcess( "dotnet", - @"Microsoft.TryDotNet.dll --urls=""http://127.0.0.1:0""", + """ + Microsoft.TryDotNet.dll --urls="http://127.0.0.1:0" + """, new DirectoryInfo(ToolPublishedPath), output: output => { @@ -39,7 +41,7 @@ public async Task Start() }, error: error => { - completionSource.SetException(new Exception(error)); + completionSource.TrySetException(new Exception(error)); }); return (await completionSource.Task.Timeout(TimeSpan.FromMinutes(1), $"ASP.NET Process failed to start. Output =\n{buffer})")).ToLocalHost(); From 632ca06c54ef9bc755630ee69fb8802a5be6be0d Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 2 Apr 2024 10:43:40 -0700 Subject: [PATCH 06/34] cleanup --- src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs | 1 - .../Microsoft.TryDotNet.IntegrationTests.csproj | 1 - .../PlaywrightTestBase.cs | 7 ++++--- .../TryDotNetFixture.cs | 7 ++----- test.cmd | 2 -- 5 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 test.cmd diff --git a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs index 3880590e2..929616219 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs @@ -17,7 +17,6 @@ public class EditorTests : PlaywrightTestBase { public EditorTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) { - } [IntegrationTestFact] diff --git a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj index 0a384f49c..92fa52f4c 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj +++ b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj @@ -4,7 +4,6 @@ net8.0 enable false - false GeneratedLocation.cs $(MSBuildThisFileDirectory)bin\$(Configuration)\tool false diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs index 43e3d6fd5..9437f0d65 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs @@ -10,12 +10,13 @@ namespace Microsoft.TryDotNet.IntegrationTests; [Collection("Chromium Edge")] public abstract class PlaywrightTestBase : IClassFixture, IClassFixture { - public PlaywrightFixture Playwright { get; } - public TryDotNetFixture TryDotNet { get; } - protected PlaywrightTestBase(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) { Playwright = playwright; TryDotNet = tryDotNet; } + + public PlaywrightFixture Playwright { get; } + + public TryDotNetFixture TryDotNet { get; } } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs index fb0e2be79..116d9185e 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs @@ -10,24 +10,21 @@ namespace Microsoft.TryDotNet.IntegrationTests; public class TryDotNetFixture : IDisposable, IAsyncLifetime { private AspNetProcess? _process; + public Uri? Url { get; private set; } public async Task InitializeAsync() { - _process = new AspNetProcess(); Url = await _process.Start(); - } - public Task DisposeAsync() - { + { _process!.Dispose(); return Task.CompletedTask; } - public void Dispose() { _process?.Dispose(); diff --git a/test.cmd b/test.cmd deleted file mode 100644 index 6635b2fff..000000000 --- a/test.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0eng\build.ps1" -test -binaryLog %* From 3f3d406cb4dc59b8d550714e60ede52ac567921b Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 2 Apr 2024 11:28:42 -0700 Subject: [PATCH 07/34] improve integration test error output --- .../AspNetProcess.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs index d7fb23097..1be5afac3 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs @@ -19,6 +19,9 @@ public async Task Start() var completionSource = new TaskCompletionSource(); var buffer = new StringBuilder(); var uriFound = false; + + var allOutput = new StringBuilder(); + _process = CommandLine.StartProcess( "dotnet", """ @@ -27,6 +30,8 @@ public async Task Start() new DirectoryInfo(ToolPublishedPath), output: output => { + allOutput.Append(output); + if (!uriFound) { buffer.AppendLine(output); @@ -41,6 +46,13 @@ public async Task Start() }, error: error => { + error = $""" + {allOutput} + + ERROR: + ------ + {error} + """; completionSource.TrySetException(new Exception(error)); }); From 88d6c860aa11140b86ed416c98c2e7b91be6a95f Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 2 Apr 2024 12:28:58 -0700 Subject: [PATCH 08/34] remove integration test artifact output from Linux build --- azure-pipelines-CI.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 27d8178fe..993b8c14d 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -208,12 +208,6 @@ extends: artifactName: Linux_test_results_and_dumps displayName: Publish Test results and Blame dumps condition: failed() - - output: pipelineArtifact - targetPath: $(Build.SourcesDirectory)/artifacts/bin/Microsoft.TryDotNet.IntegrationTests/$(_BuildConfig)/net8.0/playwright_screenshots - artifactName: Linux_playwright_screenshots - displayName: Publish Playwright screen shots - condition: always() - continueOnError: true variables: # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: From 99ad00d686247c96e25d1823640b5502f29f8273 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 3 Apr 2024 18:22:04 -0700 Subject: [PATCH 09/34] add PocketLogger to integration tests --- Directory.Packages.props | 3 +++ azure-pipelines-CI.yml | 4 ++++ azure-pipelines.yml | 4 ++++ .../EditorTests.cs | 2 ++ .../Microsoft.TryDotNet.IntegrationTests.csproj | 11 +++++++++-- .../TryDotNetFixture.cs | 11 ++++++++--- .../TryDotNetJsIntegrationTests.cs | 2 ++ .../WasmRunnerTests.cs | 11 +++++------ 8 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9a6d348f8..b57821c33 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,7 +16,10 @@ + + + diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 993b8c14d..3cc66ca0e 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -35,6 +35,8 @@ variables: value: '8.0.101' - name: NodeJSVersion value: '16.13.0' +- name: PocketLoggerLogPath + value: $(Build.SourcesDirectory)/artifacts/log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: RunIntegrationTests @@ -171,6 +173,7 @@ extends: $(_TestArgs) displayName: Build env: + POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) @@ -260,6 +263,7 @@ extends: $(_TestArgs) displayName: Build env: + POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 801fffc30..7f39cad69 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,6 +27,8 @@ variables: value: '8.0.101' - name: NodeJSVersion value: '16.13.0' + - name: PocketLoggerLogPath + value: $(Build.SourcesDirectory)/artifacts/log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: RunIntegrationTests @@ -123,6 +125,7 @@ stages: $(_TestArgs) displayName: Build env: + POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) @@ -225,6 +228,7 @@ stages: $(_TestArgs) displayName: Build env: + POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) diff --git a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs index 929616219..ab4b52698 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs @@ -10,9 +10,11 @@ using FluentAssertions; using Microsoft.Playwright; +using Pocket.For.Xunit; namespace Microsoft.TryDotNet.IntegrationTests; +[LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] public class EditorTests : PlaywrightTestBase { public EditorTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) diff --git a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj index 92fa52f4c..e2e07e481 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj +++ b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj @@ -15,13 +15,20 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all all + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + diff --git a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs index 116d9185e..305b77526 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Reactive.Disposables; using System.Threading.Tasks; using Xunit; @@ -10,23 +11,27 @@ namespace Microsoft.TryDotNet.IntegrationTests; public class TryDotNetFixture : IDisposable, IAsyncLifetime { private AspNetProcess? _process; - + private readonly CompositeDisposable _disposables = new(); + public Uri? Url { get; private set; } public async Task InitializeAsync() { _process = new AspNetProcess(); + + _disposables.Add(_process); + Url = await _process.Start(); } public Task DisposeAsync() { - _process!.Dispose(); + Dispose(); return Task.CompletedTask; } public void Dispose() { - _process?.Dispose(); + _disposables.Dispose(); } } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs index ea6aecc78..9c3295336 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs @@ -8,10 +8,12 @@ using FluentAssertions; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Playwright; +using Pocket.For.Xunit; using Xunit; namespace Microsoft.TryDotNet.IntegrationTests; +[LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] public class TryDotNetJsIntegrationTests : PlaywrightTestBase, IClassFixture { public LearnFixture Learn { get; } diff --git a/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs index 1a4d2135d..ae4583c89 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs @@ -6,11 +6,16 @@ using FluentAssertions; using Microsoft.Playwright; +using Pocket.For.Xunit; namespace Microsoft.TryDotNet.IntegrationTests; +[LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] public class WasmRunnerTests : PlaywrightTestBase { + public WasmRunnerTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) + { + } [IntegrationTestFact] public async Task can_load_wasmrunner() @@ -81,11 +86,5 @@ public async Task can_run_assembly_and_produce_output() .ContainSingle(m => m.type == "wasmRunner-stdout") .Which .message.Should().Be("Hello World!\n"); - - } - - - public WasmRunnerTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) - { } } \ No newline at end of file From 26c756373f8aa78f16d30501a6b9b4c2ffc0fe4a Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 4 Apr 2024 09:41:38 -0700 Subject: [PATCH 10/34] make Linux integration tests go away --- azure-pipelines-CI.yml | 4 ++-- azure-pipelines.yml | 13 ++----------- .../IntegrationTestFactAttribute.cs | 1 - 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 3cc66ca0e..8ca1bf70f 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -39,8 +39,6 @@ variables: value: $(Build.SourcesDirectory)/artifacts/log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages -- name: RunIntegrationTests - value: true - name: Codeql.Enabled value: true @@ -105,6 +103,8 @@ extends: # displayName: Publish packages to artifacts container variables: + - name: RunIntegrationTests + value: true # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: DotNet-Blob-Feed diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7f39cad69..5491e7850 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,8 +31,6 @@ variables: value: $(Build.SourcesDirectory)/artifacts/log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - - name: RunIntegrationTests - value: true - name: Codeql.Enabled value: true @@ -57,6 +55,8 @@ stages: name: NetCore1ESPool-Internal demands: ImageOverride -equals windows.vs2022.amd64 variables: + - name: RunIntegrationTests + value: true # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: DotNet-Blob-Feed @@ -251,15 +251,6 @@ stages: artifactType: container condition: failed() - - task: PublishBuildArtifacts@1 - displayName: Publish Playwright screen shots - inputs: - pathToPublish: $(Build.SourcesDirectory)/artifacts/bin/Microsoft.TryDotNet.IntegrationTests/Release/net8.0/playwright_screenshots - artifactName: Linux_playwright_screenshots - artifactType: container - condition: always() - continueOnError: true - #---------------------------------------------------------------------------------------------------------------------# # Post Build # #---------------------------------------------------------------------------------------------------------------------# diff --git a/src/Microsoft.TryDotNet.IntegrationTests/IntegrationTestFactAttribute.cs b/src/Microsoft.TryDotNet.IntegrationTests/IntegrationTestFactAttribute.cs index e87296a2f..995adfc48 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/IntegrationTestFactAttribute.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/IntegrationTestFactAttribute.cs @@ -13,7 +13,6 @@ internal class IntegrationTestFactAttribute : FactAttribute private const string EnvironmentVariableName = "RunIntegrationTests"; public IntegrationTestFactAttribute(string? skipReason = null) - { var variableValue = Environment.GetEnvironmentVariable(EnvironmentVariableName) ?? "false"; switch (variableValue.ToLowerInvariant()) From 4685a137bfb7d2074575d0b117b0c99d04a45579 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 4 Apr 2024 12:18:19 -0700 Subject: [PATCH 11/34] publish all artifacts --- azure-pipelines-CI.yml | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 8ca1bf70f..095ba34ea 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -86,21 +86,10 @@ extends: outputParentDirectory: $(Build.SourcesDirectory)/artifacts outputs: - output: pipelineArtifact - targetPath: $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) - artifactName: Windows_test_results_and_dumps - displayName: Publish Test results and Blame dumps - condition: failed() - - output: pipelineArtifact - targetPath: $(Build.SourcesDirectory)/artifacts/bin/Microsoft.TryDotNet.IntegrationTests/$(_BuildConfig)/net8.0/playwright_screenshots - artifactName: Windows_playwright_screenshots - displayName: Publish Playwright screen shots + targetPath: $(Build.SourcesDirectory)/artifacts + artifactName: Windows_artifacts + displayName: Publish Windows artifacts condition: always() - continueOnError: true - # Packages are not being generated - # - output: pipelineArtifact - # targetPath: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig) - # artifactName: packages - # displayName: Publish packages to artifacts container variables: - name: RunIntegrationTests @@ -207,10 +196,10 @@ extends: outputParentDirectory: $(Build.SourcesDirectory)/artifacts outputs: - output: pipelineArtifact - targetPath: $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) - artifactName: Linux_test_results_and_dumps - displayName: Publish Test results and Blame dumps - condition: failed() + targetPath: $(Build.SourcesDirectory)/artifacts + artifactName: Linux_artifacts + displayName: Publish Linux artifacts + condition: always() variables: # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: From 8533583c2c1f780240a6647f81f16758509943dc Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 4 Apr 2024 12:42:02 -0700 Subject: [PATCH 12/34] logging improvements --- .../LogEvents.SubscribeToPocketLogger.cs | 21 +++++++++++++++++++ .../CodeRunnerTests.cs | 1 - .../CommandExecutionTests.cs | 18 +++++++++++++--- .../Microsoft.TryDotNet.Tests.csproj | 14 +++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/Microsoft.TryDotNet.Tests/(Pocket)/Logger/LogEvents.SubscribeToPocketLogger.cs diff --git a/src/Microsoft.TryDotNet.Tests/(Pocket)/Logger/LogEvents.SubscribeToPocketLogger.cs b/src/Microsoft.TryDotNet.Tests/(Pocket)/Logger/LogEvents.SubscribeToPocketLogger.cs new file mode 100644 index 000000000..95f513606 --- /dev/null +++ b/src/Microsoft.TryDotNet.Tests/(Pocket)/Logger/LogEvents.SubscribeToPocketLogger.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.DotNet.Interactive.CSharpProject; +using Microsoft.DotNet.Interactive.Events; +using Xunit.Abstractions; + +namespace Pocket; + +internal partial class LogEvents +{ + public static IDisposable SubscribeToPocketLogger(this ITestOutputHelper output) => + Subscribe( + e => output.WriteLine(e.ToLogString()), + new[] + { + typeof(LogEvents).Assembly, + typeof(KernelEvent).Assembly, + typeof(CSharpProjectKernel).Assembly + }); +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.Tests/CodeRunnerTests.cs b/src/Microsoft.TryDotNet.Tests/CodeRunnerTests.cs index 5f63db219..4b40cb9b4 100644 --- a/src/Microsoft.TryDotNet.Tests/CodeRunnerTests.cs +++ b/src/Microsoft.TryDotNet.Tests/CodeRunnerTests.cs @@ -50,7 +50,6 @@ public async Task It_can_run_a_main_method_with_parameters() outputs.Select(o => o.Trim()).Should().BeEquivalentTo( "123"); - } diff --git a/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs b/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs index 67f9113c1..92d637732 100644 --- a/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs +++ b/src/Microsoft.TryDotNet.Tests/CommandExecutionTests.cs @@ -5,12 +5,23 @@ using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.DotNet.Interactive.Connection; using Microsoft.DotNet.Interactive.CSharpProject.Events; +using Pocket; +using Pocket.For.Xunit; using Xunit; +using Xunit.Abstractions; namespace Microsoft.TryDotNet.Tests; -public class CommandExecutionTests +[LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] +public class CommandExecutionTests : IDisposable { + private readonly CompositeDisposable _disposables = new(); + + public CommandExecutionTests(ITestOutputHelper output) + { + _disposables.Add(output.SubscribeToPocketLogger()); + } + [Fact] public async Task can_compile_projects_with_user_code_in_region() { @@ -73,8 +84,7 @@ public async Task can_compile_projects_with_user_code_in_region() var assemblyProduced = events.OfType().SingleOrDefault(); assemblyProduced.Should().NotBeNull(); - assemblyProduced!.Assembly - .Value.Should().NotBeNullOrWhiteSpace(); + assemblyProduced!.Assembly.Value.Should().NotBeNullOrWhiteSpace(); } [Fact] @@ -129,4 +139,6 @@ public async Task can_open_document_with_user_code_in_region() documentOpened.Should().NotBeNull(); documentOpened!.Content.Should().Contain("Console.WriteLine(123);"); } + + public void Dispose() => _disposables.Dispose(); } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.Tests/Microsoft.TryDotNet.Tests.csproj b/src/Microsoft.TryDotNet.Tests/Microsoft.TryDotNet.Tests.csproj index 689863543..d88e88435 100644 --- a/src/Microsoft.TryDotNet.Tests/Microsoft.TryDotNet.Tests.csproj +++ b/src/Microsoft.TryDotNet.Tests/Microsoft.TryDotNet.Tests.csproj @@ -15,6 +15,20 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + + all + + + all + + + all + runtime; build; native; contentfiles; analyzers + + + all + runtime; build; native; contentfiles; analyzers + From d684da833a08c2c489d6d92fe7264afdf610b1f6 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 5 Apr 2024 13:04:28 -0700 Subject: [PATCH 13/34] PocketLogger and logging updates --- Directory.Packages.props | 14 ++--- .../AspNetProcess.cs | 36 +++++++++---- .../Microsoft.TryDotNet.csproj | 8 ++- src/Microsoft.TryDotNet/Program.cs | 51 ++++++++++++++++++- 4 files changed, 88 insertions(+), 21 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b57821c33..748119e51 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,23 +11,25 @@ - - + + - - - + + + + + - + diff --git a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs index 1be5afac3..b2a48f2d5 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs @@ -7,6 +7,8 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Pocket; +using static Pocket.Logger; namespace Microsoft.TryDotNet.IntegrationTests; @@ -16,8 +18,9 @@ public partial class AspNetProcess : IDisposable public async Task Start() { + using var operation = Log.OnEnterAndConfirmOnExit(); + var completionSource = new TaskCompletionSource(); - var buffer = new StringBuilder(); var uriFound = false; var allOutput = new StringBuilder(); @@ -30,11 +33,11 @@ public async Task Start() new DirectoryInfo(ToolPublishedPath), output: output => { + operation.Info(output); allOutput.Append(output); if (!uriFound) { - buffer.AppendLine(output); var matches = Regex.Match(output, @"listening on:\s*(?http(s)?://(\d+\.){3}(\d+)(:\d+)?)"); if (matches.Success) { @@ -46,17 +49,28 @@ public async Task Start() }, error: error => { - error = $""" - {allOutput} - - ERROR: - ------ - {error} - """; - completionSource.TrySetException(new Exception(error)); + var outputAndError = $""" + {allOutput} + + ERROR: + ------ + {error} + """; + + operation.Fail(message: error); + + completionSource.TrySetException(new Exception(outputAndError)); }); - return (await completionSource.Task.Timeout(TimeSpan.FromMinutes(1), $"ASP.NET Process failed to start. Output =\n{buffer})")).ToLocalHost(); + var timeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromMinutes(1); + + var readyAtUrl = await completionSource.Task.Timeout(timeout, $"ASP.NET process not ready within {timeout.TotalSeconds}s. Output =\n{allOutput})"); + + var localHostUrl = readyAtUrl.ToLocalHost(); + + operation.Succeed(); + + return localHostUrl; } public void Dispose() diff --git a/src/Microsoft.TryDotNet/Microsoft.TryDotNet.csproj b/src/Microsoft.TryDotNet/Microsoft.TryDotNet.csproj index dc821bf2d..79c4c83d7 100644 --- a/src/Microsoft.TryDotNet/Microsoft.TryDotNet.csproj +++ b/src/Microsoft.TryDotNet/Microsoft.TryDotNet.csproj @@ -16,12 +16,16 @@ all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + all + + + + diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 22c75bfd6..fe4bb11af 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -2,14 +2,22 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Net.Mime; +using System.Reflection; using System.Text; using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.DotNet.Interactive; using Microsoft.DotNet.Interactive.Connection; using Microsoft.DotNet.Interactive.CSharpProject; using Microsoft.DotNet.Interactive.CSharpProject.Build; +using Microsoft.DotNet.Interactive.Documents; using Microsoft.DotNet.Interactive.Events; using Microsoft.TryDotNet.PeakyTests; using Peaky; +using Pocket; +using Serilog.Sinks.RollingFileAlternate; +using static Pocket.Logger; +using SerilogLoggerConfiguration = Serilog.LoggerConfiguration; namespace Microsoft.TryDotNet; @@ -19,6 +27,8 @@ public class Program public static async Task Main(string[] args) { + StartLogging(); + await EnsurePrebuildPackageIsReadyAsync(); var app = await CreateWebApplicationAsync(new WebApplicationOptions { Args = args }); @@ -118,6 +128,43 @@ private static async Task EnsurePrebuildPackageIsReadyAsync() await package.EnsureReadyAsync(); } - internal static CSharpProjectKernel CreateKernel() => + internal static CSharpProjectKernel CreateKernel() => new("csharp.console", PackageFinder.Create(() => Task.FromResult(_consolePackage))); -} \ No newline at end of file + + + private static readonly Assembly[] _assembliesEmittingPocketLoggerLogs = + [ + typeof(Program).Assembly, // Microsoft.TryDotNet.dll + typeof(Kernel).Assembly, // Microsoft.DotNet.Interactive.dll + typeof(CSharpProjectKernel).Assembly, // Microsoft.DotNet.Interactive.CSharpProject.dll + typeof(InteractiveDocument).Assembly // Microsoft.DotNet.Interactive.Documents.dll + ]; + + private static void StartLogging() + { + if (Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile) + { + var logPath = new FileInfo(logFile).Directory; + + if (logPath is not null) + { + logPath = logPath.CreateSubdirectory("Try .NET logs"); + + var log = new SerilogLoggerConfiguration() + .WriteTo + .RollingFileAlternate(logPath.FullName, outputTemplate: "{Message}{NewLine}") + .CreateLogger(); + + LogEvents.Subscribe( + e => log.Information(e.ToLogString()), + _assembliesEmittingPocketLoggerLogs); + } + } + + TaskScheduler.UnobservedTaskException += (_, args) => + { + Log.Warning($"{nameof(TaskScheduler.UnobservedTaskException)}", args.Exception); + args.SetObserved(); + }; + } +} From dfd5e17aebde45bd8180cf5b123478bc89fc370b Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 5 Apr 2024 16:11:13 -0700 Subject: [PATCH 14/34] fix warning --- src/Microsoft.TryDotNet.IntegrationTests/CommandLine.cs | 4 ++-- src/Microsoft.TryDotNet/Program.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.TryDotNet.IntegrationTests/CommandLine.cs b/src/Microsoft.TryDotNet.IntegrationTests/CommandLine.cs index 5b36a8908..b911a308f 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/CommandLine.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/CommandLine.cs @@ -198,10 +198,10 @@ private static ConfirmationLogger ConfirmOnExit( [CallerMemberName] string? operationName = null) { return new ConfirmationLogger( - operationName: operationName, + operationName: operationName ?? "", category: Log.Category, message: "> {command} {args}", - args: new[] { command, args }, + args: [command, args], logOnStart: true); } diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index fe4bb11af..0e3f03912 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Text; using System.Text.Json; -using Microsoft.CodeAnalysis; using Microsoft.DotNet.Interactive; using Microsoft.DotNet.Interactive.Connection; using Microsoft.DotNet.Interactive.CSharpProject; From 01126e1195c87c9240b695c53e8071bab7cd77bc Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Sat, 6 Apr 2024 12:01:33 -0700 Subject: [PATCH 15/34] remove separate screenshot publishing step --- azure-pipelines.yml | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5491e7850..7ef6d29e8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -141,29 +141,12 @@ stages: condition: and(ne(variables['KeepDumps'], 'true'), ne(variables['SkipTests'], 'true')) - task: PublishBuildArtifacts@1 - displayName: Publish Test results and Blame dumps - inputs: - pathToPublish: $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) - artifactName: Windows_test_results_and_dumps - artifactType: container - condition: failed() - - - task: PublishBuildArtifacts@1 - displayName: Publish Playwright screen shots + displayName: Publish Windows artifacts inputs: - pathToPublish: $(Build.SourcesDirectory)\artifacts\bin\Microsoft.TryDotNet.IntegrationTests\Release\net8.0\playwright_screenshots - artifactName: Windows_playwright_screenshots + pathToPublish: $(Build.SourcesDirectory)/artifacts/ + artifactName: Windows_artifacts artifactType: container condition: always() - continueOnError: true - - # Packages are not being generated - # - task: PublishBuildArtifacts@1 - # displayName: Publish packages to artifacts container - # inputs: - # pathToPublish: $(Build.SourcesDirectory)\artifacts\packages\$(_BuildConfig) - # artifactName: packages - # artifactType: container - template: /eng/common/templates/jobs/jobs.yml parameters: From 42999eba087ca52bbb44716cc98feab052287e00 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 8 Apr 2024 13:22:26 -0700 Subject: [PATCH 16/34] disable PDB converter --- eng/Versions.props | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/Versions.props b/eng/Versions.props index 245d6b729..cfa17af61 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,6 +6,7 @@ true false true + false -parallel none From f9ba993fcc2d83aa24133c36aa61846183e8e835 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 8 Apr 2024 14:15:23 -0700 Subject: [PATCH 17/34] don't publish to symbol server --- azure-pipelines-CI.yml | 1 - azure-pipelines.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 095ba34ea..4e7c6d146 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -116,7 +116,6 @@ extends: /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - /p:PublishToSymbolServer=true # else - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: - name: _SignType diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7ef6d29e8..dfa894f40 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -79,7 +79,6 @@ stages: /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) /p:OfficialBuildId=$(BUILD.BUILDNUMBER) - /p:PublishToSymbolServer=true # else - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: - name: _SignType From 4394c6029b4f74ae1db2be18e003f0e80df5af21 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 8 Apr 2024 14:49:23 -0700 Subject: [PATCH 18/34] update log path --- azure-pipelines-CI.yml | 2 +- azure-pipelines.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index 4e7c6d146..d16dd67c3 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -36,7 +36,7 @@ variables: - name: NodeJSVersion value: '16.13.0' - name: PocketLoggerLogPath - value: $(Build.SourcesDirectory)/artifacts/log + value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: Codeql.Enabled diff --git a/azure-pipelines.yml b/azure-pipelines.yml index dfa894f40..d13d44636 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -28,7 +28,7 @@ variables: - name: NodeJSVersion value: '16.13.0' - name: PocketLoggerLogPath - value: $(Build.SourcesDirectory)/artifacts/log + value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: Codeql.Enabled From 0e98905dab4f24e46919662aad4ee3e570b186d9 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 9 Apr 2024 09:19:59 -0700 Subject: [PATCH 19/34] false --- Directory.Build.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 58d125494..f392ed875 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,7 +10,8 @@ false false - + false + $(NoWarn);NU5104 From 66a7964a1125df3d0cb5fc648ff3026c403f9c1a Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 9 Apr 2024 11:02:18 -0700 Subject: [PATCH 20/34] turn on logging regardless of environment variable --- src/Microsoft.TryDotNet/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 0e3f03912..6a66202ed 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -141,7 +141,7 @@ internal static CSharpProjectKernel CreateKernel() => private static void StartLogging() { - if (Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile) + if (true /* Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile */ ) { var logPath = new FileInfo(logFile).Directory; From eef2fcaa1ef229d2325edcaae0d4221f968627aa Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 9 Apr 2024 13:03:50 -0700 Subject: [PATCH 21/34] update Microsoft.DotNet.Interactive.CSharpProject version --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 748119e51..4a21dc3fc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + From ede9e668e92b16c7d91130dda1a72f75fce08480 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 9 Apr 2024 13:07:53 -0700 Subject: [PATCH 22/34] update package versions --- Directory.Packages.props | 8 ++++---- src/Microsoft.TryDotNet/Program.cs | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4a21dc3fc..a12fe24ec 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 6a66202ed..979d61aaa 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -141,10 +141,12 @@ internal static CSharpProjectKernel CreateKernel() => private static void StartLogging() { - if (true /* Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile */ ) + if (Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile) { var logPath = new FileInfo(logFile).Directory; + Console.WriteLine($"Logging to: {logPath}"); + if (logPath is not null) { logPath = logPath.CreateSubdirectory("Try .NET logs"); From e88becca0a4d6409685475ca16bdd3a1c88fbc41 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 9 Apr 2024 18:07:55 -0700 Subject: [PATCH 23/34] update Microsoft.DotNet.Interactive.CSharpProject version --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a12fe24ec..7e59cf6b9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + From eade20910a6d2293d05d8645aaee21c527fe9721 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 10 Apr 2024 09:53:26 -0700 Subject: [PATCH 24/34] set POCKETLOGGER_LOG_PATH globally --- azure-pipelines.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d13d44636..7373c47e0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -57,6 +57,8 @@ stages: variables: - name: RunIntegrationTests value: true + - name: POCKETLOGGER_LOG_PATH + value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: DotNet-Blob-Feed @@ -159,6 +161,8 @@ stages: pool: vmImage: ubuntu-20.04 variables: + - name: POCKETLOGGER_LOG_PATH + value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - name: _SignType From bcb461906c82be104930b8454dca6ea8a6a3a189 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 10 Apr 2024 19:32:29 -0700 Subject: [PATCH 25/34] reorganize test fixtures, improve logging --- Directory.Packages.props | 8 +- azure-pipelines.yml | 16 ++-- global.json | 4 +- .../(Pocket)/Logger/Class1.cs | 29 ++++++ .../AsyncLazy.cs | 26 +++++ ...nDefinitionForIntegratedServicesFixture.cs | 14 +++ .../EditorTests.cs | 77 +++++++-------- .../IntegratedServicesFixture.cs | 60 ++++++++++++ .../LearnFixture.cs | 62 ------------ .../LearnServer.cs | 96 +++++++++++++++++++ ...icrosoft.TryDotNet.IntegrationTests.csproj | 9 +- .../PlaywrightFixture.cs | 51 ---------- .../PlaywrightSession.cs | 47 +++++++++ .../PlaywrightTestBase.cs | 53 ++++++++-- .../TryDotNetFixture.cs | 37 ------- .../TryDotNetJsIntegrationTests.cs | 28 +++--- .../{AspNetProcess.cs => TryDotNetServer.cs} | 49 ++++++---- .../WasmRunnerTests.cs | 20 ++-- src/Microsoft.TryDotNet/Program.cs | 4 +- 19 files changed, 427 insertions(+), 263 deletions(-) create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/(Pocket)/Logger/Class1.cs create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/AsyncLazy.cs create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/CollectionDefinitionForIntegratedServicesFixture.cs create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs delete mode 100644 src/Microsoft.TryDotNet.IntegrationTests/LearnFixture.cs create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/LearnServer.cs delete mode 100644 src/Microsoft.TryDotNet.IntegrationTests/PlaywrightFixture.cs create mode 100644 src/Microsoft.TryDotNet.IntegrationTests/PlaywrightSession.cs delete mode 100644 src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs rename src/Microsoft.TryDotNet.IntegrationTests/{AspNetProcess.cs => TryDotNetServer.cs} (61%) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7e59cf6b9..31254fd7a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7373c47e0..a2cb46612 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,8 +27,6 @@ variables: value: '8.0.101' - name: NodeJSVersion value: '16.13.0' - - name: PocketLoggerLogPath - value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log - name: TryDotNetPackagesPath value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: Codeql.Enabled @@ -129,7 +127,7 @@ stages: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) + - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame workingDirectory: $(Build.SourcesDirectory) condition: ne(variables['SkipTests'], 'true') @@ -162,7 +160,7 @@ stages: vmImage: ubuntu-20.04 variables: - name: POCKETLOGGER_LOG_PATH - value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log + value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - name: _SignType @@ -217,7 +215,7 @@ stages: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) - - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) + - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame workingDirectory: $(Build.SourcesDirectory) condition: ne(variables['SkipTests'], 'true') @@ -230,12 +228,12 @@ stages: condition: and(ne(variables['KeepDumps'], 'true'), ne(variables['SkipTests'], 'true')) - task: PublishBuildArtifacts@1 - displayName: Publish Test results and Blame dumps + displayName: Publish Linux artifacts inputs: - pathToPublish: $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) - artifactName: Linux_test_results_and_dumps + pathToPublish: $(Build.SourcesDirectory)/artifacts/ + artifactName: Linux_artifacts artifactType: container - condition: failed() + condition: always() #---------------------------------------------------------------------------------------------------------------------# # Post Build # diff --git a/global.json b/global.json index b967c3a19..fd3c5267b 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "8.0.202", + "version": "8.0.204", "allowPrerelease": true, "rollForward": "latestMinor" }, "tools": { - "dotnet": "8.0.202", + "dotnet": "8.0.204", "rollForward": "latestMinor" }, "msbuild-sdks": { diff --git a/src/Microsoft.TryDotNet.IntegrationTests/(Pocket)/Logger/Class1.cs b/src/Microsoft.TryDotNet.IntegrationTests/(Pocket)/Logger/Class1.cs new file mode 100644 index 000000000..3495494c6 --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/(Pocket)/Logger/Class1.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Reflection; +using Microsoft.DotNet.Interactive; +using Microsoft.DotNet.Interactive.CSharpProject; +using Microsoft.DotNet.Interactive.Documents; +using Microsoft.TryDotNet.IntegrationTests; +using Xunit.Abstractions; + +namespace Pocket; + +internal partial class LogEvents +{ + public static IDisposable SubscribeToPocketLogger(this ITestOutputHelper output) => + Subscribe( + e => output.WriteLine(e.ToLogString()), + AssembliesPublishingPocketLoggerEvents); + + public static Assembly[] AssembliesPublishingPocketLoggerEvents => + [ + typeof(Microsoft.TryDotNet.Program).Assembly, // Microsoft.TryDotNet.dll + typeof(Kernel).Assembly, // Microsoft.DotNet.Interactive.dll + typeof(CSharpProjectKernel).Assembly, // Microsoft.DotNet.Interactive.CSharpProject.dll + typeof(InteractiveDocument).Assembly, // Microsoft.DotNet.Interactive.Documents.dll, + typeof(IntegratedServicesFixture).Assembly // Microsoft.TryDotNet.IntegrationTests.dll + ]; +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/AsyncLazy.cs b/src/Microsoft.TryDotNet.IntegrationTests/AsyncLazy.cs new file mode 100644 index 000000000..df8efa1dd --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/AsyncLazy.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.TryDotNet.IntegrationTests; + +internal class AsyncLazy +{ + private readonly Lazy> _lazy; + + public AsyncLazy(Func> initialize) + { + if (initialize is null) + { + throw new ArgumentNullException(nameof(initialize)); + } + +#pragma warning disable VSTHRD011 // Use AsyncLazy + _lazy = new Lazy>(initialize); +#pragma warning restore VSTHRD011 // Use AsyncLazy + } + + public Task ValueAsync() => _lazy.Value; +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/CollectionDefinitionForIntegratedServicesFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/CollectionDefinitionForIntegratedServicesFixture.cs new file mode 100644 index 000000000..0002158a3 --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/CollectionDefinitionForIntegratedServicesFixture.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Xunit; + +namespace Microsoft.TryDotNet.IntegrationTests; + +[CollectionDefinition(nameof(IntegratedServicesFixture), DisableParallelization = true)] +public class CollectionDefinitionForIntegratedServicesFixture : ICollectionFixture +{ + // This class has no code, and is never created. Its purpose is simply + // to be the place to apply [CollectionDefinition] and all the + // ICollectionFixture<> interfaces. +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs index ab4b52698..4e34e60f3 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/EditorTests.cs @@ -8,24 +8,24 @@ using System.Threading.Tasks; using FluentAssertions; - using Microsoft.Playwright; using Pocket.For.Xunit; +using Xunit.Abstractions; namespace Microsoft.TryDotNet.IntegrationTests; [LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] public class EditorTests : PlaywrightTestBase { - public EditorTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) + public EditorTests(IntegratedServicesFixture services, ITestOutputHelper output) : base(services, output) { } [IntegrationTestFact] public async Task can_load_monaco_editor() { - var page = await Playwright.Browser!.NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + var page = await NewPageAsync(); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var isVisible = await page.Locator("div[role = \"code\"]").IsVisibleAsync(); @@ -38,7 +38,7 @@ public async Task can_load_monaco_editor() public async Task can_load_the_wasm_runner() { var wasmRunnerLoaded = false; - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); await page.RouteAsync("**/*", async route => { @@ -50,7 +50,7 @@ await page.RouteAsync("**/*", async route => await route.ContinueAsync(); }); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator("div[role = \"code\"]").IsVisibleAsync(); @@ -62,9 +62,9 @@ await page.RouteAsync("**/*", async route => [IntegrationTestFact] public async Task wasm_runner_is_not_visible_to_screenReaders() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "editor"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator("div[role = \"code\"]").IsVisibleAsync(); @@ -79,9 +79,9 @@ public async Task wasm_runner_is_not_visible_to_screenReaders() [IntegrationTestFact] public async Task wasm_runner_is_not_part_of_tab_navigation() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator("div[role = \"code\"]").IsVisibleAsync(); @@ -93,16 +93,17 @@ public async Task wasm_runner_is_not_part_of_tab_navigation() } + [IntegrationTestFact] public async Task notifies_when_editor_is_ready() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); var readyAwaiter = interceptor.AwaitForMessage("HostEditorReady"); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var found = await readyAwaiter; @@ -113,11 +114,11 @@ public async Task notifies_when_editor_is_ready() [IntegrationTestFact] public async Task can_open_project() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -145,10 +146,10 @@ await page.DispatchMessage(new [IntegrationTestFact] public async Task can_open_document() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -189,10 +190,10 @@ await page.DispatchMessage(new [IntegrationTestFact] public async Task can_open_document_and_populate_editor_from_region() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -233,10 +234,10 @@ await page.DispatchMessage(new [IntegrationTestFact] public async Task minimap_is_not_visible() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.TestScreenShotAsync(); var minimap = page.Locator("div.minimap"); @@ -247,10 +248,10 @@ public async Task minimap_is_not_visible() [IntegrationTestFact] public async Task can_show_minimap() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.DispatchMessage(new { @@ -272,10 +273,10 @@ await page.DispatchMessage(new [IntegrationTestFact] public async Task can_configure_theme() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.DispatchMessage(new { @@ -294,10 +295,10 @@ await page.DispatchMessage(new [Obsolete] public async Task when_user_code_in_editor_diagnostics_are_produced() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -361,10 +362,10 @@ await editor.TypeAsync(@"///////////////////////// [Obsolete] public async Task when_user_code_in_editor_is_executed_display_events_are_produced() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -420,10 +421,10 @@ static void Main() {{ [Obsolete] public async Task user_typing_code_gets_completion() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -479,10 +480,10 @@ static void Main() {{ [Obsolete] public async Task user_typing_code_gets_signatureHelp() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -544,10 +545,10 @@ Writes the current line terminator to the standard output stream. [Obsolete] public async Task when_user_code_in_editor_is_executed_it_produces_runResult_event() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -602,10 +603,10 @@ static void Main() {{ [Obsolete] public async Task when_user_code_in_editor_is_executed_it_produces_runResult_event_with_outputs() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); @@ -662,10 +663,10 @@ static void Main() {{ [Obsolete] public async Task user_code_in_editor_is_executed() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - await page.GotoAsync(TryDotNet.Url + "editor?enableLogging=true"); + await page.GotoAsync((await Services.GetTryDotNetServerAsync()).Url + "editor?enableLogging=true"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); var projectLoadedAwaiter = interceptor.AwaitForMessage("ProjectOpened"); diff --git a/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs new file mode 100644 index 000000000..ab1471ae7 --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs @@ -0,0 +1,60 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Pocket; + +namespace Microsoft.TryDotNet.IntegrationTests; + +public class IntegratedServicesFixture : IDisposable +{ + private static readonly CompositeDisposable _disposables = new(); + + private static readonly AsyncLazy _lazyTryDotNetServer; + private static readonly AsyncLazy _lazyLearnServer; + private static readonly AsyncLazy _lazyPlaywright; + private static int _instanceCount; + + static IntegratedServicesFixture() + { + _lazyTryDotNetServer = new AsyncLazy(StartTryDotNetServer); + _lazyLearnServer = new AsyncLazy(StartLearnServer); + _lazyPlaywright = new AsyncLazy(StartPlaywright); + } + + public IntegratedServicesFixture() + { + Interlocked.Increment(ref _instanceCount); + } + + private static async Task StartLearnServer() + { + var server = await LearnServer.StartAsync(); + _disposables.Add(server); + return server; + } + + private static async Task StartTryDotNetServer() + { + var server = await TryDotNetServer.StartAsync(); + _disposables.Add(server); + return server; + } + + private static async Task StartPlaywright() + { + var server = await PlaywrightSession.StartAsync(); + _disposables.Add(server); + return server; + } + + public Task GetTryDotNetServerAsync() => _lazyTryDotNetServer.ValueAsync(); + + public Task GetLearnServerAsync() => _lazyLearnServer.ValueAsync(); + + public Task GetPlaywrightAsync() => _lazyPlaywright.ValueAsync(); + + public void Dispose() => _disposables.Dispose(); +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/LearnFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/LearnFixture.cs deleted file mode 100644 index 9a42cdf26..000000000 --- a/src/Microsoft.TryDotNet.IntegrationTests/LearnFixture.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.TryDotNet.IntegrationTests; - -public partial class LearnFixture : IDisposable, IAsyncLifetime -{ - private Process? _httpServer; - - public Uri? Url { get; private set; } - - public void Dispose() - { - _httpServer?.Kill(true); - _httpServer?.Dispose(); - _httpServer = null; - } - - public async Task InitializeAsync() - { - if (_httpServer is null) - { - var completionSource = new TaskCompletionSource(); - var buffer = new StringBuilder(); - var uriFound = false; - _httpServer = CommandLine.StartProcess("pwsh", "-c npx http-server --cors", new DirectoryInfo(SitePath), (output) => - { - if (!uriFound) - { - buffer.AppendLine(output); - var allText = buffer.ToString(); - var match = Regex.Match(allText, @".*(?http://\d+\.\d+\.\d+\.\d+:\d+).*", - RegexOptions.Multiline); - if (match.Success) - { - if (Uri.TryCreate(match.Groups["uri"].Value, UriKind.Absolute, out var uri)) - { - uriFound = true; - completionSource.SetResult(uri); - } - } - } - }); - - Url = (await completionSource.Task).ToLocalHost(); - } - } - - public Task DisposeAsync() - { - Dispose(); - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/LearnServer.cs b/src/Microsoft.TryDotNet.IntegrationTests/LearnServer.cs new file mode 100644 index 000000000..70d54723d --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/LearnServer.cs @@ -0,0 +1,96 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Pocket; +using static Pocket.Logger; + +namespace Microsoft.TryDotNet.IntegrationTests; + +public class LearnServer : IDisposable +{ + private Process? _process; + + private LearnServer(Process process, Uri url) + { + _process = process; + Url = url; + } + + public Uri Url { get; } + + public static async Task StartAsync() + { + using var operation = Log.OnEnterAndConfirmOnExit(); + + var uriFound = false; + var allOutput = new StringBuilder(); + var completionSource = new TaskCompletionSource(); + + var buffer = new StringBuilder(); + + var process = CommandLine.StartProcess( + "pwsh", + "-c npx http-server --cors", + new DirectoryInfo(BuildProperties.LearnMockSitePath), + output => + { + if (!uriFound) + { + buffer.AppendLine(output); + var allText = buffer.ToString(); + var match = Regex.Match(allText, @".*(?http://\d+\.\d+\.\d+\.\d+:\d+).*", + RegexOptions.Multiline); + if (match.Success) + { + if (Uri.TryCreate(match.Groups["uri"].Value, UriKind.Absolute, out var uri)) + { + uriFound = true; + completionSource.SetResult(uri.ToLocalHost()); + } + } + } + }, + error: error => + { + var outputAndError = $""" + {allOutput} + + ERROR: + ------ + {error} + """; + + operation.Fail(message: error); + + completionSource.TrySetException(new Exception(outputAndError)); + }); + + operation.Info(("Process ID", process.Id), ("Process Name", process.ProcessName)); + + var timeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromMinutes(1); + + var url = await completionSource.Task.Timeout(timeout, $"node process not ready within {timeout.TotalSeconds}s. Output =\n{allOutput})"); + + operation.Succeed(); + + return new LearnServer(process, url); + } + + public void Dispose() + { + if (_process is { } process) + { + using var operation = Log.OnEnterAndConfirmOnExit(arg: ("Process ID", process.Id)); + _process = null; + process.Kill(true); + process.Dispose(); + operation.Succeed(); + } + } +} diff --git a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj index e2e07e481..aa8fda100 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj +++ b/src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj @@ -51,12 +51,11 @@ diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightFixture.cs deleted file mode 100644 index c6ff01c21..000000000 --- a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightFixture.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Microsoft.Playwright; -using Xunit; - -[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)] - -namespace Microsoft.TryDotNet.IntegrationTests; - -public class PlaywrightFixture : IDisposable, IAsyncLifetime -{ - private IPlaywright? _playwrightSession; - public IBrowser? Browser { get; private set; } - - public async Task InitializeAsync() - { - var exitCode = Playwright.Program.Main(new[] { "install", "chromium" }); - if (exitCode != 0) - { - throw new Exception($"Playwright exited with code {exitCode}"); - } - - _playwrightSession = await Playwright.Playwright.CreateAsync().Timeout(TimeSpan.FromMinutes(5), "Timeout creating Playwright session"); - - var browserTypeLaunchOptions = new BrowserTypeLaunchOptions(); - if (Debugger.IsAttached) - { - browserTypeLaunchOptions.Headless = false; - browserTypeLaunchOptions.Devtools = true; - } - - Browser = await _playwrightSession.Chromium.LaunchAsync(browserTypeLaunchOptions).Timeout(TimeSpan.FromMinutes(5), "Timeout launching browser"); - } - - - public Task DisposeAsync() - { - _playwrightSession!.Dispose(); - return Task.CompletedTask; - } - - - public void Dispose() - { - _playwrightSession?.Dispose(); - } -} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightSession.cs b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightSession.cs new file mode 100644 index 000000000..9ee612230 --- /dev/null +++ b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightSession.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Microsoft.Playwright; + +namespace Microsoft.TryDotNet.IntegrationTests; + +public class PlaywrightSession : IDisposable +{ + private IPlaywright _playwright; + + public PlaywrightSession(IPlaywright playwright, IBrowser browser) + { + _playwright = playwright; + Browser = browser; + } + + public IBrowser Browser { get; } + + public static async Task StartAsync() + { + var exitCode = Playwright.Program.Main(["install", "chromium"]); + if (exitCode is not 0) + { + throw new Exception($"Playwright exited with code {exitCode}"); + } + + var session = await Playwright.Playwright.CreateAsync().Timeout(TimeSpan.FromMinutes(5), "Timeout creating Playwright session"); + + var browserTypeLaunchOptions = new BrowserTypeLaunchOptions(); + + if (Debugger.IsAttached) + { + browserTypeLaunchOptions.Headless = false; + browserTypeLaunchOptions.Devtools = true; + } + + var browser = await session.Chromium.LaunchAsync(browserTypeLaunchOptions).Timeout(TimeSpan.FromMinutes(5), "Timeout launching browser"); + + return new PlaywrightSession(session, browser); + } + + public void Dispose() => _playwright.Dispose(); +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs index 9437f0d65..0bddf5878 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/PlaywrightTestBase.cs @@ -1,22 +1,55 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. - +using System; +using System.Threading.Tasks; +using Microsoft.Playwright; +using Pocket; using Xunit; +using Xunit.Abstractions; + +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)] namespace Microsoft.TryDotNet.IntegrationTests; -[CollectionDefinition("Chromium Edge", DisableParallelization = true)] -[Collection("Chromium Edge")] -public abstract class PlaywrightTestBase : IClassFixture, IClassFixture +[Collection(nameof(IntegratedServicesFixture))] +public abstract class PlaywrightTestBase : IDisposable { - protected PlaywrightTestBase(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) + private readonly CompositeDisposable _disposables = new(); + + protected PlaywrightTestBase( + IntegratedServicesFixture services, + ITestOutputHelper output) + { + Services = services; + Output = output; + } + + public IntegratedServicesFixture Services { get; } + + public ITestOutputHelper Output { get; } + + protected async Task NewPageAsync() { - Playwright = playwright; - TryDotNet = tryDotNet; + var playwright = await Services.GetPlaywrightAsync(); + return await playwright.Browser.NewPageAsync(); } - public PlaywrightFixture Playwright { get; } + protected async Task TryDotNetUrlAsync() + { + var server = await Services.GetTryDotNetServerAsync(); + return server.Url; + } + + protected async Task LearnUrlAsync() + { + var server = await Services.GetLearnServerAsync(); + return server.Url; + } + + public void Dispose() + { + _disposables.Dispose(); + } +} - public TryDotNetFixture TryDotNet { get; } -} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs deleted file mode 100644 index 305b77526..000000000 --- a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetFixture.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Reactive.Disposables; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.TryDotNet.IntegrationTests; - -public class TryDotNetFixture : IDisposable, IAsyncLifetime -{ - private AspNetProcess? _process; - private readonly CompositeDisposable _disposables = new(); - - public Uri? Url { get; private set; } - - public async Task InitializeAsync() - { - _process = new AspNetProcess(); - - _disposables.Add(_process); - - Url = await _process.Start(); - } - - public Task DisposeAsync() - { - Dispose(); - return Task.CompletedTask; - } - - public void Dispose() - { - _disposables.Dispose(); - } -} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs index 9c3295336..653e366be 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetJsIntegrationTests.cs @@ -10,32 +10,30 @@ using Microsoft.Playwright; using Pocket.For.Xunit; using Xunit; +using Xunit.Abstractions; namespace Microsoft.TryDotNet.IntegrationTests; [LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] -public class TryDotNetJsIntegrationTests : PlaywrightTestBase, IClassFixture +public class TryDotNetJsIntegrationTests : PlaywrightTestBase { - public LearnFixture Learn { get; } - - public TryDotNetJsIntegrationTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet, LearnFixture learn) : base(playwright, tryDotNet) + public TryDotNetJsIntegrationTests(IntegratedServicesFixture services, ITestOutputHelper output) : base(services, output) { - Learn = learn; } [IntegrationTestFact] public async Task loads_trydotnet_editor() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); - var learnRoot = Learn.Url!; - var trydotnetOrigin = TryDotNet.Url!; + var learnRoot = (await Services.GetLearnServerAsync()).Url; + var trydotnetOrigin = await TryDotNetUrlAsync(); var trydotnetUrl = new Uri(trydotnetOrigin, "api/trydotnet.min.js"); var param = new Dictionary { ["trydotnetUrl"] = trydotnetUrl.ToString(), - ["trydotnetOrigin"] = trydotnetOrigin.ToString(), + ["trydotnetOrigin"] = trydotnetOrigin.ToString() }; var pageUri = new Uri(QueryHelpers.AddQueryString(new Uri(learnRoot,"DocsHost.html").ToString(), param!)); @@ -49,12 +47,12 @@ public async Task loads_trydotnet_editor() [IntegrationTestFact] public async Task can_load_code() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - var learnRoot = Learn.Url!; - var trydotnetOrigin = TryDotNet.Url!; + var learnRoot = (await Services.GetLearnServerAsync()).Url; + var trydotnetOrigin = (await Services.GetTryDotNetServerAsync()).Url; var trydotnetUrl = new Uri(trydotnetOrigin, "api/trydotnet.min.js"); var param = new Dictionary @@ -80,12 +78,12 @@ public async Task can_load_code() [IntegrationTestFact] public async Task outputs_are_rendered() { - var page = await Playwright.Browser!.NewPageAsync(); + var page = await NewPageAsync(); var interceptor = new MessageInterceptor(); await interceptor.InstallAsync(page); - var learnRoot = Learn.Url!; - var trydotnetOrigin = TryDotNet.Url!; + var learnRoot = await LearnUrlAsync(); + var trydotnetOrigin = await TryDotNetUrlAsync(); var trydotnetUrl = new Uri(trydotnetOrigin, "api/trydotnet.min.js"); var param = new Dictionary diff --git a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetServer.cs similarity index 61% rename from src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs rename to src/Microsoft.TryDotNet.IntegrationTests/TryDotNetServer.cs index b2a48f2d5..2edde9040 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/AspNetProcess.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/TryDotNetServer.cs @@ -8,29 +8,36 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Pocket; -using static Pocket.Logger; +using static Pocket.Logger; namespace Microsoft.TryDotNet.IntegrationTests; -public partial class AspNetProcess : IDisposable +public class TryDotNetServer : IDisposable { private Process? _process; - public async Task Start() + private TryDotNetServer(Process process, Uri url) + { + Url = url; + _process = process; + } + + public Uri Url { get; } + + public static async Task StartAsync() { using var operation = Log.OnEnterAndConfirmOnExit(); - var completionSource = new TaskCompletionSource(); var uriFound = false; - var allOutput = new StringBuilder(); + var completionSource = new TaskCompletionSource(); - _process = CommandLine.StartProcess( + var process = CommandLine.StartProcess( "dotnet", """ - Microsoft.TryDotNet.dll --urls="http://127.0.0.1:0" - """, - new DirectoryInfo(ToolPublishedPath), + Microsoft.TryDotNet.dll --urls="http://127.0.0.1:0" + """, + new DirectoryInfo(BuildProperties.TryDotNetPublishLocation), output: output => { operation.Info(output); @@ -43,7 +50,7 @@ public async Task Start() { uriFound = true; var result = new Uri(matches.Groups["URI"].Value, UriKind.Absolute); - completionSource.SetResult(result); + completionSource.SetResult(result.ToLocalHost()); } } }, @@ -62,22 +69,26 @@ public async Task Start() completionSource.TrySetException(new Exception(outputAndError)); }); - var timeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromMinutes(1); + operation.Info(("Process ID", process.Id), ("Process Name", process.ProcessName)); - var readyAtUrl = await completionSource.Task.Timeout(timeout, $"ASP.NET process not ready within {timeout.TotalSeconds}s. Output =\n{allOutput})"); + var timeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromMinutes(1); - var localHostUrl = readyAtUrl.ToLocalHost(); + var url = await completionSource.Task.Timeout(timeout, $"ASP.NET process not ready within {timeout.TotalSeconds}s. Output =\n{allOutput})"); operation.Succeed(); - return localHostUrl; + return new TryDotNetServer(process, url); } public void Dispose() { - var process = _process; - _process = null; - process?.Kill(true); - process?.Dispose(); + if (_process is { } process) + { + using var operation = Log.OnEnterAndConfirmOnExit(arg: ("Process ID", process.Id)); + _process = null; + process.Kill(true); + process.Dispose(); + operation.Succeed(); + } } -} +} \ No newline at end of file diff --git a/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs b/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs index ae4583c89..9354b9efc 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/WasmRunnerTests.cs @@ -7,21 +7,23 @@ using Microsoft.Playwright; using Pocket.For.Xunit; +using Xunit.Abstractions; namespace Microsoft.TryDotNet.IntegrationTests; [LogToPocketLogger(FileNameEnvironmentVariable = "POCKETLOGGER_LOG_PATH")] public class WasmRunnerTests : PlaywrightTestBase { - public WasmRunnerTests(PlaywrightFixture playwright, TryDotNetFixture tryDotNet) : base(playwright, tryDotNet) + public WasmRunnerTests(IntegratedServicesFixture services, ITestOutputHelper output) : base(services, output) { + } [IntegrationTestFact] public async Task can_load_wasmrunner() { - var page = await Playwright.Browser!.NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "wasmrunner"); + var page = await NewPageAsync(); + await page.GotoAsync(await TryDotNetUrlAsync() + "wasmrunner"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator(@"id=wasmRunner-sentinel").IsHiddenAsync(); @@ -31,8 +33,8 @@ public async Task can_load_wasmrunner() [IntegrationTestFact] public async Task can_run_assembly() { - var page = await Playwright.Browser!.NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "wasmrunner"); + var page = await NewPageAsync(); + await page.GotoAsync(await TryDotNetUrlAsync() + "wasmrunner"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator(@"id=wasmRunner-sentinel").IsHiddenAsync(); @@ -51,8 +53,8 @@ public async Task can_run_assembly() [IntegrationTestFact] public async Task can_run_assembly_2() { - var page = await Playwright.Browser!.NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "wasmrunner"); + var page = await NewPageAsync(); + await page.GotoAsync(await TryDotNetUrlAsync() + "wasmrunner"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator(@"id=wasmRunner-sentinel").IsHiddenAsync(); @@ -71,8 +73,8 @@ public async Task can_run_assembly_2() [IntegrationTestFact] public async Task can_run_assembly_and_produce_output() { - var page = await Playwright.Browser!.NewPageAsync(); - await page.GotoAsync(TryDotNet.Url + "wasmrunner"); + var page = await NewPageAsync(); + await page.GotoAsync(await TryDotNetUrlAsync() + "wasmrunner"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); await page.Locator(@"id=wasmRunner-sentinel").IsHiddenAsync(); diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index 979d61aaa..c2631023b 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -139,7 +139,7 @@ internal static CSharpProjectKernel CreateKernel() => typeof(InteractiveDocument).Assembly // Microsoft.DotNet.Interactive.Documents.dll ]; - private static void StartLogging() + public static void StartLogging(Assembly[]? assembliesToSubscribe = null) { if (Environment.GetEnvironmentVariable("POCKETLOGGER_LOG_PATH") is { } logFile) { @@ -158,7 +158,7 @@ private static void StartLogging() LogEvents.Subscribe( e => log.Information(e.ToLogString()), - _assembliesEmittingPocketLoggerLogs); + assembliesToSubscribe ?? _assembliesEmittingPocketLoggerLogs); } } From 6c8005d2029425a1e80248255c1b9524a8fc4720 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 11 Apr 2024 09:22:35 -0700 Subject: [PATCH 26/34] move prebuilds into artifacts folder --- azure-pipelines.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a2cb46612..7c69fed1b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,8 +27,6 @@ variables: value: '8.0.101' - name: NodeJSVersion value: '16.13.0' - - name: TryDotNetPackagesPath - value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: Codeql.Enabled value: true @@ -55,6 +53,8 @@ stages: variables: - name: RunIntegrationTests value: true + - name: TryDotNetPrebuildsPath + value: $(Build.SourcesDirectory)\artifacts\trydotnet-prebuilds - name: POCKETLOGGER_LOG_PATH value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log # Enable signing for internal, non-PR builds @@ -125,7 +125,7 @@ stages: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PACKAGES_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame @@ -159,6 +159,8 @@ stages: pool: vmImage: ubuntu-20.04 variables: + - name: TryDotNetPrebuildsPath + value: $(Build.SourcesDirectory)/artifacts/trydotnet-prebuilds - name: POCKETLOGGER_LOG_PATH value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log # Enable signing for internal, non-PR builds @@ -213,7 +215,7 @@ stages: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PACKAGES_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame From f21ddb34a96c50a3365ed6c3794175a144be2cdc Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Thu, 11 Apr 2024 19:29:45 -0700 Subject: [PATCH 27/34] update to latest Microsoft.DotNet.Interactive.CSharpProject --- Directory.Packages.props | 2 +- azure-pipelines-CI.yml | 4 ++-- azure-pipelines.yml | 4 ++-- .../IntegratedServicesFixture.cs | 17 ++++++++++++++--- src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs | 12 ++++++------ src/Microsoft.TryDotNet/Program.cs | 14 +++++++------- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 31254fd7a..27084d447 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index d16dd67c3..e65a6fafb 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -162,7 +162,7 @@ extends: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) displayName: Test / Blame @@ -252,7 +252,7 @@ extends: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPackagesPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) displayName: Test / Blame diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7c69fed1b..e33ef7df0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -125,7 +125,7 @@ stages: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPrebuildsPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame @@ -215,7 +215,7 @@ stages: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PACKAGES_PATH: $(TryDotNetPrebuildsPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt displayName: Test / Blame diff --git a/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs b/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs index ab1471ae7..c18d3d969 100644 --- a/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs +++ b/src/Microsoft.TryDotNet.IntegrationTests/IntegratedServicesFixture.cs @@ -1,14 +1,15 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.Interactive.CSharpProject.Build; using Pocket; +using Xunit; namespace Microsoft.TryDotNet.IntegrationTests; -public class IntegratedServicesFixture : IDisposable +public class IntegratedServicesFixture : IAsyncLifetime { private static readonly CompositeDisposable _disposables = new(); @@ -24,6 +25,12 @@ static IntegratedServicesFixture() _lazyPlaywright = new AsyncLazy(StartPlaywright); } + public async Task InitializeAsync() + { + var consolePrebuild = await Prebuild.GetOrCreateConsolePrebuildAsync(true); + await consolePrebuild.EnsureReadyAsync(); + } + public IntegratedServicesFixture() { Interlocked.Increment(ref _instanceCount); @@ -56,5 +63,9 @@ private static async Task StartPlaywright() public Task GetPlaywrightAsync() => _lazyPlaywright.ValueAsync(); - public void Dispose() => _disposables.Dispose(); + public Task DisposeAsync() + { + _disposables.Dispose(); + return Task.CompletedTask; + } } \ No newline at end of file diff --git a/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs index 5ede125b3..1e73616e1 100644 --- a/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs +++ b/src/Microsoft.TryDotNet/PeakyTests/SelfTests.cs @@ -16,19 +16,19 @@ namespace Microsoft.TryDotNet.PeakyTests; public class SelfTests : IPeakyTest, IHaveTags, IApplyToApplication { - public async Task Console_package_is_prebuilt() + public async Task Console_prebuild_is_ready() { - var package = await Package.GetOrCreateConsolePackageAsync(enableBuild: false); + var prebuild = await Prebuild.GetOrCreateConsolePrebuildAsync(enableBuild: false); - package.Directory.Exists.Should().BeTrue(); + prebuild.Directory.Exists.Should().BeTrue(); - var subdirectories = package.Directory.GetDirectories(); + var subdirectories = prebuild.Directory.GetDirectories(); subdirectories.Should().Contain(d => d.Name == "bin"); subdirectories.Should().Contain(d => d.Name == "obj"); - package.Directory.GetFiles().Should().Contain(f => f.Name == "console.csproj.interactive.workspaceData.cache"); + prebuild.Directory.GetFiles().Should().Contain(f => f.Name == "console.csproj.interactive.workspaceData.cache"); - return package; + return prebuild; } public async Task Can_get_signature_help() diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index c2631023b..de12cd3e8 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -22,13 +22,13 @@ namespace Microsoft.TryDotNet; public class Program { - private static Package? _consolePackage; + private static Prebuild? _consolePrebuild; public static async Task Main(string[] args) { StartLogging(); - await EnsurePrebuildPackageIsReadyAsync(); + await EnsurePrebuildPrebuildIsReadyAsync(); var app = await CreateWebApplicationAsync(new WebApplicationOptions { Args = args }); @@ -53,7 +53,7 @@ public static async Task CreateWebApplicationAsync(WebApplicatio builder.Services.AddCors( opts => opts.AddPolicy("trydotnet", policy => policy.AllowAnyOrigin())); - _consolePackage = await Package.GetOrCreateConsolePackageAsync(enableBuild: false); + _consolePrebuild = await Prebuild.GetOrCreateConsolePrebuildAsync(enableBuild: false); builder.Services.AddPeakyTests(tests => { @@ -121,14 +121,14 @@ public static async Task CreateWebApplicationAsync(WebApplicatio return app; } - private static async Task EnsurePrebuildPackageIsReadyAsync() + private static async Task EnsurePrebuildPrebuildIsReadyAsync() { - var package = await Package.GetOrCreateConsolePackageAsync(true); - await package.EnsureReadyAsync(); + var prebuild = await Prebuild.GetOrCreateConsolePrebuildAsync(true); + await prebuild.EnsureReadyAsync(); } internal static CSharpProjectKernel CreateKernel() => - new("csharp.console", PackageFinder.Create(() => Task.FromResult(_consolePackage))); + new("csharp.console", PrebuildFinder.Create(() => Task.FromResult(_consolePrebuild))); private static readonly Assembly[] _assembliesEmittingPocketLoggerLogs = From af09d41bfbd0c06d886834d663d7dbbf4a0965da Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 12 Apr 2024 14:44:08 -0700 Subject: [PATCH 28/34] update pipeline --- azure-pipelines.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e33ef7df0..97c56870d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -29,6 +29,8 @@ variables: value: '16.13.0' - name: Codeql.Enabled value: true + - name: system.debug + value: true stages: - stage: build @@ -53,7 +55,7 @@ stages: variables: - name: RunIntegrationTests value: true - - name: TryDotNetPrebuildsPath + - name: TRYDOTNET_PREBUILDS_PATH value: $(Build.SourcesDirectory)\artifacts\trydotnet-prebuilds - name: POCKETLOGGER_LOG_PATH value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log @@ -159,7 +161,7 @@ stages: pool: vmImage: ubuntu-20.04 variables: - - name: TryDotNetPrebuildsPath + - name: TRYDOTNET_PREBUILDS_PATH value: $(Build.SourcesDirectory)/artifacts/trydotnet-prebuilds - name: POCKETLOGGER_LOG_PATH value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log From b2efd0ebe7ccebf19f87463abd8480b8c6bb0b15 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 12 Apr 2024 15:07:04 -0700 Subject: [PATCH 29/34] more .yml updates and .NET SDK version update --- azure-pipelines-CI.yml | 18 +++++++++++------- azure-pipelines.yml | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/azure-pipelines-CI.yml b/azure-pipelines-CI.yml index e65a6fafb..87c259fc2 100644 --- a/azure-pipelines-CI.yml +++ b/azure-pipelines-CI.yml @@ -32,13 +32,9 @@ variables: - name: _DotNetArtifactsCategory value: .NETCore - name: DotNetSdkVersion - value: '8.0.101' + value: '8.0.204' - name: NodeJSVersion value: '16.13.0' -- name: PocketLoggerLogPath - value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log -- name: TryDotNetPackagesPath - value: $(Build.SourcesDirectory)/artifacts/.trydotnet/packages - name: Codeql.Enabled value: true @@ -92,6 +88,10 @@ extends: condition: always() variables: + - name: TRYDOTNET_PREBUILDS_PATH + value: $(Build.SourcesDirectory)\artifacts\trydotnet-prebuilds + - name: POCKETLOGGER_LOG_PATH + value: $(Build.SourcesDirectory)\artifacts\logs\pocketlogger.log - name: RunIntegrationTests value: true # Enable signing for internal, non-PR builds @@ -162,7 +162,7 @@ extends: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) displayName: Test / Blame @@ -200,6 +200,10 @@ extends: displayName: Publish Linux artifacts condition: always() variables: + - name: TRYDOTNET_PREBUILDS_PATH + value: $(Build.SourcesDirectory)/artifacts/trydotnet-prebuilds + - name: POCKETLOGGER_LOG_PATH + value: $(Build.SourcesDirectory)/artifacts/logs/pocketlogger.log # Enable signing for internal, non-PR builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - name: _SignType @@ -252,7 +256,7 @@ extends: displayName: Build env: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) - TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPackagesPath) + TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPrebuildsPath) - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) displayName: Test / Blame diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 97c56870d..c90f694ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -24,7 +24,7 @@ variables: - name: _DotNetArtifactsCategory value: .NETCore - name: DotNetSdkVersion - value: '8.0.101' + value: '8.0.204' - name: NodeJSVersion value: '16.13.0' - name: Codeql.Enabled From 0d1748f97e52c63cf4155c33bf5267bab4df3b62 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 15 Apr 2024 11:25:38 -0700 Subject: [PATCH 30/34] small rename --- src/Microsoft.TryDotNet/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.TryDotNet/Program.cs b/src/Microsoft.TryDotNet/Program.cs index de12cd3e8..56225cb95 100644 --- a/src/Microsoft.TryDotNet/Program.cs +++ b/src/Microsoft.TryDotNet/Program.cs @@ -28,7 +28,7 @@ public static async Task Main(string[] args) { StartLogging(); - await EnsurePrebuildPrebuildIsReadyAsync(); + await EnsurePrebuildIsReadyAsync(); var app = await CreateWebApplicationAsync(new WebApplicationOptions { Args = args }); @@ -121,7 +121,7 @@ public static async Task CreateWebApplicationAsync(WebApplicatio return app; } - private static async Task EnsurePrebuildPrebuildIsReadyAsync() + private static async Task EnsurePrebuildIsReadyAsync() { var prebuild = await Prebuild.GetOrCreateConsolePrebuildAsync(true); await prebuild.EnsureReadyAsync(); From da9d193aa197eb79e1b0efb98b35efa0bd5b1517 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 15 Apr 2024 11:27:15 -0700 Subject: [PATCH 31/34] disable test parallelism --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c90f694ba..6dc7280b8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -129,7 +129,7 @@ stages: POCKETLOGGER_LOG_PATH: $(PocketLoggerLogPath) TRYDOTNET_PREBUILDS_PATH: $(TryDotNetPrebuildsPath) - - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt + - script: dotnet test -l trx --no-build --blame-hang-timeout 15m --blame-hang-dump-type full -c $(_BuildConfig) --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig) --diag $(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/diag.txt -p:m=1 displayName: Test / Blame workingDirectory: $(Build.SourcesDirectory) condition: ne(variables['SkipTests'], 'true') From 28a8dabb7d0abc87ff077bb588675211e0019dc1 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Mon, 15 Apr 2024 16:26:25 -0700 Subject: [PATCH 32/34] package updates --- Directory.Packages.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 27084d447..11b248927 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,8 +11,9 @@ - + + From e2be2ee9156d412abe334ed1e6102e18d6c49c22 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 16 Apr 2024 10:50:22 -0700 Subject: [PATCH 33/34] build debug --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6dc7280b8..29ffb0049 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,7 +18,7 @@ variables: - name: _TeamName value: DotNetTry - name: _BuildConfig - value: Release + value: Debug - name: _PublishUsingPipelines value: true - name: _DotNetArtifactsCategory From 3246c4f4c0fc55dd76c98605e55c646550bcadfd Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Wed, 17 Apr 2024 11:55:42 -0700 Subject: [PATCH 34/34] update CSharpProject package version --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 11b248927..bc464a603 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - +