diff --git a/src/Microsoft.Tye.Core/ApplicationBuilderExtensions.cs b/src/Microsoft.Tye.Core/ApplicationBuilderExtensions.cs new file mode 100644 index 00000000..e38a36e7 --- /dev/null +++ b/src/Microsoft.Tye.Core/ApplicationBuilderExtensions.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Tye +{ + public static class ApplicationBuilderExtensions + { + public static async Task TransformProjectsIntoContainersAync(this ApplicationBuilder application, OutputContext output) + { + var targets = new[] { "Restore", "Publish" }; + + for (var i = 0; i < application.Services.Count; i++) + { + var service = application.Services[i]; + + if (!(service is ProjectServiceBuilder project)) + { + continue; + } + + if (!await ProjectReader.ReadProjectDetailsAsync(output, project, targets)) + { + return false; + } + + PopulateProjectDefaults(project); + + static string DetermineContainerImage(ProjectServiceBuilder project) + { + return $"mcr.microsoft.com/dotnet/core/sdk:{project.TargetFrameworkVersion}"; + } + + // We transform the project information into the following docker command: + // docker run -w /app -v {publishDir}:/app -it {image} dotnet {outputfile}.dll + + var containerImage = DetermineContainerImage(project); + var outputFileName = project.AssemblyName + ".dll"; + var containerService = new ContainerServiceBuilder(service.Name, containerImage) + { + Replicas = project.Replicas, + Args = $"dotnet {outputFileName} {project.Args}", + WorkingDirectory = "/app" + }; + + containerService.Volumes.Add(new VolumeBuilder(source: project.PublishDir, name: null, target: "/app")); + + // Make volume mapping works when running as a container + containerService.Volumes.AddRange(project.Volumes); + containerService.Bindings.AddRange(project.Bindings); + containerService.EnvironmentVariables.AddRange(project.EnvironmentVariables); + + application.Services[i] = containerService; + } + + return true; + } + + public static async Task BuildProjectsAsync(this ApplicationBuilder application, OutputContext output) + { + var targets = new string[] { "Restore", "Build" }; + foreach (var service in application.Services) + { + if (service is ProjectServiceBuilder project) + { + if (!await ProjectReader.ReadProjectDetailsAsync(output, project, targets)) + { + return false; + } + + PopulateProjectDefaults(project); + } + } + + return true; + } + + private static void PopulateProjectDefaults(ProjectServiceBuilder project) + { + if (project.Bindings.Count == 0 && project.IsAspNet) + { + // HTTP is the default binding + project.Bindings.Add(new BindingBuilder() + { + Protocol = "http" + }); + + project.Bindings.Add(new BindingBuilder() + { + Name = "https", + Protocol = "https" + }); + } + } + } +} diff --git a/src/Microsoft.Tye.Core/ApplicationFactory.cs b/src/Microsoft.Tye.Core/ApplicationFactory.cs index 7d77c857..96322280 100644 --- a/src/Microsoft.Tye.Core/ApplicationFactory.cs +++ b/src/Microsoft.Tye.Core/ApplicationFactory.cs @@ -14,7 +14,7 @@ namespace Microsoft.Tye { public static class ApplicationFactory { - public static async Task CreateAsync(OutputContext output, FileInfo source) + public static async Task CreateAsync(OutputContext output, FileInfo source, bool populateProjectInformation = true) { if (source is null) { @@ -57,11 +57,13 @@ namespace Microsoft.Tye var project = new ProjectServiceBuilder(configService.Name!, projectFile); service = project; - project.Build = configService.Build ?? true; project.Args = configService.Args; project.Replicas = configService.Replicas ?? 1; - await ProjectReader.ReadProjectDetailsAsync(output, project); + if (populateProjectInformation) + { + await ProjectReader.ReadProjectDetailsAsync(output, project); + } // We don't apply more container defaults here because we might need // to prompt for the registry name. diff --git a/src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs b/src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs index 0da6ad62..43a20c93 100644 --- a/src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs +++ b/src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs @@ -15,7 +15,6 @@ namespace Microsoft.Tye.ConfigModel public bool External { get; set; } public string? Image { get; set; } public string? Project { get; set; } - public bool? Build { get; set; } public string? Executable { get; set; } public string? WorkingDirectory { get; set; } public string? Args { get; set; } diff --git a/src/Microsoft.Tye.Core/ContainerServiceBuilder.cs b/src/Microsoft.Tye.Core/ContainerServiceBuilder.cs index 060fadd9..c31b4f9c 100644 --- a/src/Microsoft.Tye.Core/ContainerServiceBuilder.cs +++ b/src/Microsoft.Tye.Core/ContainerServiceBuilder.cs @@ -23,5 +23,7 @@ namespace Microsoft.Tye public List EnvironmentVariables { get; } = new List(); public List Volumes { get; } = new List(); + + public string? WorkingDirectory { get; set; } } } diff --git a/src/Microsoft.Tye.Core/OutputContext.cs b/src/Microsoft.Tye.Core/OutputContext.cs index 8b766504..ce77be09 100644 --- a/src/Microsoft.Tye.Core/OutputContext.cs +++ b/src/Microsoft.Tye.Core/OutputContext.cs @@ -178,22 +178,28 @@ namespace Microsoft.Tye public void StdOut(string line) { - if (output.Verbosity >= Verbosity.Debug) - { - output.Console.SetTerminalForegroundColor(ConsoleColor.Gray); - output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); - output.Console.ResetTerminalForegroundColor(); - } + //if (output.Verbosity >= Verbosity.Debug) + //{ + // output.Console.SetTerminalForegroundColor(ConsoleColor.Gray); + // output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); + // output.Console.ResetTerminalForegroundColor(); + //} + output.Console.SetTerminalForegroundColor(ConsoleColor.Gray); + output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); + output.Console.ResetTerminalForegroundColor(); } public void StdErr(string line) { - if (output.Verbosity >= Verbosity.Info) - { - output.Console.SetTerminalForegroundColor(ConsoleColor.Red); - output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); - output.Console.ResetTerminalForegroundColor(); - } + //if (output.Verbosity >= Verbosity.Info) + //{ + // output.Console.SetTerminalForegroundColor(ConsoleColor.Red); + // output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); + // output.Console.ResetTerminalForegroundColor(); + //} + output.Console.SetTerminalForegroundColor(ConsoleColor.Red); + output.Console.Out.WriteLine(new string(' ', output.indent + IndentAmount) + line); + output.Console.ResetTerminalForegroundColor(); } } diff --git a/src/Microsoft.Tye.Core/ProjectReader.cs b/src/Microsoft.Tye.Core/ProjectReader.cs index b90ea633..39afd80a 100644 --- a/src/Microsoft.Tye.Core/ProjectReader.cs +++ b/src/Microsoft.Tye.Core/ProjectReader.cs @@ -60,7 +60,7 @@ namespace Microsoft.Tye } } - public static Task ReadProjectDetailsAsync(OutputContext output, ProjectServiceBuilder project) + public static Task ReadProjectDetailsAsync(OutputContext output, ProjectServiceBuilder project, string[]? targets = null) { if (output is null) { @@ -74,7 +74,7 @@ namespace Microsoft.Tye EnsureMSBuildRegistered(output, project.ProjectFile); - EvaluateProject(output, project); + var result = EvaluateProject(output, project, targets); if (!SemVersion.TryParse(project.Version, out var version)) { @@ -83,7 +83,7 @@ namespace Microsoft.Tye project.Version = version.ToString(); } - return Task.CompletedTask; + return Task.FromResult(result); } private static void EnsureMSBuildRegistered(OutputContext? output, FileInfo projectFile) @@ -141,8 +141,10 @@ namespace Microsoft.Tye // Do not load MSBuild types before using EnsureMSBuildRegistered. [MethodImpl(MethodImplOptions.NoInlining)] - private static void EvaluateProject(OutputContext output, ProjectServiceBuilder project) + private static bool EvaluateProject(OutputContext output, ProjectServiceBuilder project, string[]? targets = null) { + var result = true; + var sw = Stopwatch.StartNew(); // We need to isolate projects from each other for testing. MSBuild does not support @@ -168,17 +170,19 @@ namespace Microsoft.Tye // Currently we only log at debug level. var logger = new ConsoleLogger( - verbosity: LoggerVerbosity.Normal, + verbosity: LoggerVerbosity.Quiet, write: message => output.WriteDebug(message), colorSet: null, colorReset: null); try { + targets ??= new[] { "Restore", "ResolveReferences", "ResolvePackageDependenciesDesignTime", "PrepareResources", "GetAssemblyAttributes" }; + + output.WriteDebugLine($"Executing targtes: {string.Join(", ", targets)}"); + AssemblyLoadContext.Default.Resolving += ResolveAssembly; - var result = projectInstance.Build( - targets: new[] { "Restore", "ResolveReferences", "ResolvePackageDependenciesDesignTime", "PrepareResources", "GetAssemblyAttributes", }, - loggers: new[] { logger, }); + result = projectInstance.Build(targets, loggers: new[] { logger }); // If the build fails, we're not really blocked from doing our work. // For now we just log the output to debug. There are errors that occur during @@ -234,6 +238,7 @@ namespace Microsoft.Tye output.WriteDebugLine($"Evaluation Took: {sw.Elapsed.TotalMilliseconds}ms"); + return result; // The Microsoft.Build.Locator doesn't handle the loading of other assemblies // that are shipped with MSBuild (ex NuGet). // @@ -246,14 +251,12 @@ namespace Microsoft.Tye // See: https://github.com/microsoft/MSBuildLocator/issues/86 Assembly? ResolveAssembly(AssemblyLoadContext context, AssemblyName assemblyName) { - if (assemblyName.Name is object && assemblyName.Name.StartsWith("NuGet.")) + var msbuildDirectory = Environment.GetEnvironmentVariable("MSBuildExtensionsPath")!; + var assemblyFilePath = Path.Combine(msbuildDirectory, assemblyName.Name + ".dll"); + + if (File.Exists(assemblyFilePath)) { - var msbuildDirectory = Environment.GetEnvironmentVariable("MSBuildExtensionsPath")!; - var assemblyFilePath = Path.Combine(msbuildDirectory, assemblyName.Name + ".dll"); - if (File.Exists(assemblyFilePath)) - { - return context.LoadFromAssemblyPath(assemblyFilePath); - } + return context.LoadFromAssemblyPath(assemblyFilePath); } return default; diff --git a/src/Microsoft.Tye.Core/ProjectServiceBuilder.cs b/src/Microsoft.Tye.Core/ProjectServiceBuilder.cs index 5c75daeb..514a58ef 100644 --- a/src/Microsoft.Tye.Core/ProjectServiceBuilder.cs +++ b/src/Microsoft.Tye.Core/ProjectServiceBuilder.cs @@ -19,8 +19,6 @@ namespace Microsoft.Tye public int Replicas { get; set; } = 1; - public bool Build { get; set; } - public string? Args { get; set; } public FrameworkCollection Frameworks { get; } = new FrameworkCollection(); diff --git a/src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs b/src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs index 6dd43491..33bd50da 100644 --- a/src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs +++ b/src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs @@ -45,13 +45,6 @@ namespace Tye.Serialization case "project": service.Project = YamlParser.GetScalarValue(key, child.Value); break; - case "build": - if (!bool.TryParse(YamlParser.GetScalarValue(key, child.Value), out var build)) - { - throw new TyeYamlException(child.Value.Start, CoreStrings.FormatMustBeABoolean(key)); - } - service.Build = build; - break; case "executable": service.Executable = YamlParser.GetScalarValue(key, child.Value); break; diff --git a/src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs b/src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs index 18b2b6a6..ebf2d4c7 100644 --- a/src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs +++ b/src/Microsoft.Tye.Hosting/Model/ProjectRunInfo.cs @@ -13,7 +13,6 @@ namespace Microsoft.Tye.Hosting.Model { ProjectFile = project.ProjectFile; Args = project.Args; - Build = project.Build; TargetFramework = project.TargetFramework; TargetFrameworkName = project.TargetFrameworkName; TargetFrameworkVersion = project.TargetFrameworkVersion; @@ -26,7 +25,6 @@ namespace Microsoft.Tye.Hosting.Model } public string? Args { get; } - public bool Build { get; } public FileInfo ProjectFile { get; } public string TargetFrameworkName { get; set; } = default!; public string TargetFrameworkVersion { get; set; } = default!; diff --git a/src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs b/src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs index 7d65e02b..d54091a8 100644 --- a/src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs +++ b/src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs @@ -10,7 +10,6 @@ namespace Microsoft.Tye.Hosting.Model.V1 { public V1RunInfoType Type { get; set; } public string? Args { get; set; } - public bool Build { get; set; } public string? Project { get; set; } public string? WorkingDirectory { get; set; } public List? VolumeMappings { get; set; } diff --git a/src/Microsoft.Tye.Hosting/ProcessRunner.cs b/src/Microsoft.Tye.Hosting/ProcessRunner.cs index 5957dd2a..46750d00 100644 --- a/src/Microsoft.Tye.Hosting/ProcessRunner.cs +++ b/src/Microsoft.Tye.Hosting/ProcessRunner.cs @@ -56,7 +56,7 @@ namespace Microsoft.Tye.Hosting return KillRunningProcesses(application.Services); } - private async Task LaunchService(Application application, Service service) + private Task LaunchService(Application application, Service service) { var serviceDescription = service.Description; var serviceName = serviceDescription.Name; @@ -96,27 +96,6 @@ namespace Microsoft.Tye.Hosting var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); - if (service.Status.ProjectFilePath != null && - service.Description.RunInfo is ProjectRunInfo project2 && - project2.Build && - _options.BuildProjects) - { - // Sometimes building can fail because of file locking (like files being open in VS) - _logger.LogInformation("Building project {ProjectFile}", service.Status.ProjectFilePath); - - service.Logs.OnNext($"dotnet build \"{service.Status.ProjectFilePath}\" /nologo"); - - var buildResult = await ProcessUtil.RunAsync("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo", throwOnError: false, workingDirectory: workingDirectory); - - service.Logs.OnNext(buildResult.StandardOutput); - - if (buildResult.ExitCode != 0) - { - _logger.LogInformation("Building {ProjectFile} failed with exit code {ExitCode}: \r\n" + buildResult.StandardOutput, service.Status.ProjectFilePath, buildResult.ExitCode); - return; - } - } - async Task RunApplicationAsync(IEnumerable<(int ExternalPort, int Port, string? Protocol)> ports) { // Make sure we yield before trying to start the process, this is important so we don't block startup @@ -298,6 +277,8 @@ namespace Microsoft.Tye.Hosting } service.Items[typeof(ProcessInfo)] = processInfo; + + return Task.CompletedTask; } private Task KillRunningProcesses(IDictionary services) diff --git a/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs b/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs deleted file mode 100644 index fda8213b..00000000 --- a/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Tye.Hosting.Model; - -namespace Microsoft.Tye.Hosting -{ - public class TransformProjectsIntoContainers : IApplicationProcessor - { - private readonly ILogger _logger; - - public TransformProjectsIntoContainers(ILogger logger) - { - _logger = logger; - } - - public Task StartAsync(Application application) - { - // This transforms a ProjectRunInfo into a container - var tasks = new List(); - foreach (var s in application.Services.Values) - { - if (s.Description.RunInfo is ProjectRunInfo project) - { - tasks.Add(TransformProjectToContainer(s, project)); - } - } - - return Task.WhenAll(tasks); - } - - private async Task TransformProjectToContainer(Service service, ProjectRunInfo project) - { - var serviceDescription = service.Description; - var serviceName = serviceDescription.Name; - - service.Status.ProjectFilePath = project.ProjectFile.FullName; - var targetFramework = project.TargetFramework; - - // Sometimes building can fail because of file locking (like files being open in VS) - _logger.LogInformation("Publishing project {ProjectFile}", service.Status.ProjectFilePath); - - var publishCommand = $"publish \"{service.Status.ProjectFilePath}\" --framework {targetFramework} /nologo"; - - service.Logs.OnNext($"dotnet {publishCommand}"); - - var buildResult = await ProcessUtil.RunAsync("dotnet", publishCommand, throwOnError: false); - - service.Logs.OnNext(buildResult.StandardOutput); - - if (buildResult.ExitCode != 0) - { - _logger.LogInformation("Publishing {ProjectFile} failed with exit code {ExitCode}: \r\n" + buildResult.StandardOutput, service.Status.ProjectFilePath, buildResult.ExitCode); - - // Null out the RunInfo so that - serviceDescription.RunInfo = null; - return; - } - - // We transform the project information into the following docker command: - // docker run -w /app -v {publishDir}:/app -it {image} dotnet {outputfile}.dll - - var containerImage = DetermineContainerImage(project); - var outputFileName = project.AssemblyName + ".dll"; - var dockerRunInfo = new DockerRunInfo(containerImage, $"dotnet {outputFileName} {project.Args}") - { - WorkingDirectory = "/app" - }; - - dockerRunInfo.VolumeMappings.Add(new DockerVolume(source: project.PublishOutputPath, name: null, target: "/app")); - - // Make volume mapping works when running as a container - dockerRunInfo.VolumeMappings.AddRange(project.VolumeMappings); - - // Change the project into a container info - serviceDescription.RunInfo = dockerRunInfo; - } - - private static string DetermineContainerImage(ProjectRunInfo project) - { - return $"mcr.microsoft.com/dotnet/core/sdk:{project.TargetFrameworkVersion}"; - } - - public Task StopAsync(Application application) - { - return Task.CompletedTask; - } - } -} diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index caf7780c..00d31e59 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -151,7 +151,6 @@ namespace Microsoft.Tye.Hosting { v1RunInfo.Type = V1RunInfoType.Project; v1RunInfo.Args = projectRunInfo.Args; - v1RunInfo.Build = projectRunInfo.Build; v1RunInfo.Project = projectRunInfo.ProjectFile.FullName; } diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index a56e8c3c..f27215d9 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -264,12 +264,6 @@ namespace Microsoft.Tye.Hosting new ProcessRunner(logger, replicaRegistry, ProcessRunnerOptions.FromArgs(args, servicesToDebug)) }; - // If the docker command is specified then transform the ProjectRunInfo into DockerRunInfo - if (args.Contains("--docker")) - { - processors.Insert(0, new TransformProjectsIntoContainers(logger)); - } - return new AggregateApplicationProcessor(processors); } diff --git a/src/tye/ApplicationBuilderExtensions.cs b/src/tye/ApplicationBuilderExtensions.cs index 5c5c6748..2a44e007 100644 --- a/src/tye/ApplicationBuilderExtensions.cs +++ b/src/tye/ApplicationBuilderExtensions.cs @@ -43,7 +43,10 @@ namespace Microsoft.Tye } else if (service is ContainerServiceBuilder container) { - var dockerRunInfo = new DockerRunInfo(container.Image, container.Args); + var dockerRunInfo = new DockerRunInfo(container.Image, container.Args) + { + WorkingDirectory = container.WorkingDirectory + }; foreach (var mapping in container.Volumes) { diff --git a/src/tye/Program.RunCommand.cs b/src/tye/Program.RunCommand.cs index 2f0ee040..77f6e456 100644 --- a/src/tye/Program.RunCommand.cs +++ b/src/tye/Program.RunCommand.cs @@ -7,6 +7,7 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.CommandLine.IO; using System.IO; +using System.Linq; using System.Threading; using Microsoft.Tye.ConfigModel; using Microsoft.Tye.Extensions; @@ -64,7 +65,7 @@ namespace Microsoft.Tye Required = false }); - command.Handler = CommandHandler.Create(async (console, path, debug) => + command.Handler = CommandHandler.Create(async (console, path, debug, docker, nobuild) => { // Workaround for https://github.com/dotnet/command-line-api/issues/723#issuecomment-593062654 if (path is null) @@ -72,8 +73,25 @@ namespace Microsoft.Tye throw new CommandException("No project or solution file was found."); } - var output = new OutputContext(console, Verbosity.Quiet); - var application = await ApplicationFactory.CreateAsync(output, path); + // Populate project information if docker is false and we're not building + var populateProjectInformation = nobuild && !docker; + var output = new OutputContext(console, Verbosity.Debug); + var application = await ApplicationFactory.CreateAsync(output, path, populateProjectInformation); + + if (docker) + { + if (!await application.TransformProjectsIntoContainersAync(output)) + { + return; + } + } + else if (!populateProjectInformation) + { + if (!await application.BuildProjectsAsync(output)) + { + return; + } + } await application.ProcessExtensionsAsync(ExtensionContext.OperationKind.LocalRun); diff --git a/test/E2ETest/TyeRunTests.cs b/test/E2ETest/TyeRunTests.cs index 2ca7803b..d38e71b1 100644 --- a/test/E2ETest/TyeRunTests.cs +++ b/test/E2ETest/TyeRunTests.cs @@ -61,7 +61,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var testUri = await GetServiceUrl(client, uri, "test-project"); @@ -88,7 +88,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var frontendUri = await GetServiceUrl(client, uri, "frontend"); var backendUri = await GetServiceUrl(client, uri, "backend"); @@ -119,7 +119,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, new[] { "--docker" }, async (app, uri) => + await RunHostingApplication(application, outputContext, new[] { "--docker" }, async (app, uri) => { // Make sure we're running containers Assert.True(app.Services.All(s => s.Value.Description.RunInfo is DockerRunInfo)); @@ -166,7 +166,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var frontendUri = await GetServiceUrl(client, uri, "frontend"); var backendUri = await GetServiceUrl(client, uri, "backend"); @@ -210,7 +210,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var frontendUri = await GetServiceUrl(client, uri, "frontend"); var backendUri = await GetServiceUrl(client, uri, "backend"); @@ -249,7 +249,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); var args = new[] { "--docker" }; - await RunHostingApplication(application, args, async (app, serviceApi) => + await RunHostingApplication(application, outputContext, args, async (app, serviceApi) => { var serviceUri = await GetServiceUrl(client, serviceApi, "volume-test"); @@ -264,7 +264,7 @@ namespace E2ETest Assert.Equal("Things saved to the volume!", await client.GetStringAsync(serviceUri)); }); - await RunHostingApplication(application, args, async (app, serviceApi) => + await RunHostingApplication(application, outputContext, args, async (app, serviceApi) => { var serviceUri = await GetServiceUrl(client, serviceApi, "volume-test"); @@ -306,6 +306,7 @@ namespace E2ETest { await RunHostingApplication( application, + outputContext, new[] { "--docker" }, async (app, uri) => { @@ -358,6 +359,7 @@ namespace E2ETest await RunHostingApplication( application, + outputContext, new[] { "--docker" }, async (app, uri) => { @@ -409,7 +411,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); var args = new[] { "--docker" }; - await RunHostingApplication(application, args, async (app, serviceApi) => + await RunHostingApplication(application, outputContext, args, async (app, serviceApi) => { var serviceUri = await GetServiceUrl(client, serviceApi, "volume-test"); @@ -437,7 +439,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var ingressUri = await GetServiceUrl(client, uri, "ingress"); var appAUri = await GetServiceUrl(client, uri, "appA"); @@ -486,7 +488,7 @@ namespace E2ETest var client = new HttpClient(new RetryHandler(handler)); - await RunHostingApplication(application, Array.Empty(), async (app, uri) => + await RunHostingApplication(application, outputContext, Array.Empty(), async (app, uri) => { var nginxUri = await GetServiceUrl(client, uri, "nginx"); var appAUri = await GetServiceUrl(client, uri, "appA"); @@ -534,8 +536,13 @@ namespace E2ETest return $"{binding.Protocol ?? "http"}://localhost:{binding.Port}"; } - private async Task RunHostingApplication(ApplicationBuilder application, string[] args, Func execute) + private async Task RunHostingApplication(ApplicationBuilder application, OutputContext outputContext, string[] args, Func execute) { + if (args.Contains("--docker")) + { + await application.TransformProjectsIntoContainersAync(outputContext); + } + await using var host = new TyeHost(application.ToHostingApplication(), args) { Sink = _sink, diff --git a/test/UnitTests/TyeDeserializationTests.cs b/test/UnitTests/TyeDeserializationTests.cs index fce81b84..23388699 100644 --- a/test/UnitTests/TyeDeserializationTests.cs +++ b/test/UnitTests/TyeDeserializationTests.cs @@ -180,7 +180,6 @@ ingress: .Single(); Assert.NotNull(otherService); Assert.Equal(otherService.Args, service.Args); - Assert.Equal(otherService.Build, service.Build); Assert.Equal(otherService.Executable, service.Executable); Assert.Equal(otherService.External, service.External); Assert.Equal(otherService.Image, service.Image);