diff --git a/src/Microsoft.Tye.Hosting/ProcessRunner.cs b/src/Microsoft.Tye.Hosting/ProcessRunner.cs index 5957dd2a..6c4e55df 100644 --- a/src/Microsoft.Tye.Hosting/ProcessRunner.cs +++ b/src/Microsoft.Tye.Hosting/ProcessRunner.cs @@ -35,20 +35,7 @@ namespace Microsoft.Tye.Hosting { await PurgeFromPreviousRun(); - var tasks = new Task[application.Services.Count]; - var index = 0; - foreach (var s in application.Services) - { - tasks[index++] = s.Value.ServiceType switch - { - ServiceType.Executable => LaunchService(application, s.Value), - ServiceType.Project => LaunchService(application, s.Value), - - _ => Task.CompletedTask, - }; - } - - await Task.WhenAll(tasks); + await BuildAndRunProjects(application); } public Task StopAsync(Application application) @@ -56,67 +43,92 @@ namespace Microsoft.Tye.Hosting return KillRunningProcesses(application.Services); } - private async Task LaunchService(Application application, Service service) + private async Task BuildAndRunProjects(Application application) { - var serviceDescription = service.Description; - var serviceName = serviceDescription.Name; - - var path = ""; - var workingDirectory = ""; - var args = ""; - - if (serviceDescription.RunInfo is ProjectRunInfo project) + foreach (var service in application.Services.Values) { - path = project.RunCommand; - workingDirectory = project.ProjectFile.Directory.FullName; - args = project.Args == null ? project.RunArguments : project.RunArguments + " " + project.Args; - service.Status.ProjectFilePath = project.ProjectFile.FullName; - } - else if (serviceDescription.RunInfo is ExecutableRunInfo executable) - { - path = executable.Executable; - workingDirectory = executable.WorkingDirectory!; - args = executable.Args ?? ""; - } - else - { - throw new InvalidOperationException("Unsupported ServiceType."); - } + var serviceDescription = service.Description; - // If this is a dll then use dotnet to run it - if (Path.GetExtension(path) == ".dll") - { - args = $"\"{path}\" {args}".Trim(); - path = "dotnet"; - } + string path; + string args; + string workingDirectory; + if (serviceDescription.RunInfo is ProjectRunInfo project) + { + path = project.RunCommand; + workingDirectory = project.ProjectFile.Directory.FullName; + args = project.Args == null ? project.RunArguments : project.RunArguments + " " + project.Args; + service.Status.ProjectFilePath = project.ProjectFile.FullName; + } + else if (serviceDescription.RunInfo is ExecutableRunInfo executable) + { + path = executable.Executable; + workingDirectory = executable.WorkingDirectory!; + args = executable.Args ?? ""; + } + else + { + continue; + } - service.Status.ExecutablePath = path; - service.Status.WorkingDirectory = workingDirectory; - service.Status.Args = args; + // If this is a dll then use dotnet to run it + if (Path.GetExtension(path) == ".dll") + { + args = $"\"{path}\" {args}".Trim(); + path = "dotnet"; + } - var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); + service.Status.ExecutablePath = path; + service.Status.WorkingDirectory = workingDirectory; + service.Status.Args = args; - 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); + // TODO instead of always building with projects, try building with sln if available. + 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"); + service.Logs.OnNext($"dotnet build \"{service.Status.ProjectFilePath}\" /nologo"); - var buildResult = await ProcessUtil.RunAsync("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo", throwOnError: false, workingDirectory: workingDirectory); + var buildResult = await ProcessUtil.RunAsync("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo", throwOnError: false, workingDirectory: workingDirectory); - service.Logs.OnNext(buildResult.StandardOutput); + 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; + if (buildResult.ExitCode != 0) + { + _logger.LogInformation("Building {ProjectFile} failed with exit code {ExitCode}: \r\n" + buildResult.StandardOutput, service.Status.ProjectFilePath, buildResult.ExitCode); + return; + } } } + foreach (var s in application.Services) + { + switch (s.Value.ServiceType) + { + case ServiceType.Executable: + LaunchService(application, s.Value); + break; + case ServiceType.Project: + LaunchService(application, s.Value); + break; + }; + } + } + + private void LaunchService(Application application, Service service) + { + var serviceDescription = service.Description; + var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); + var serviceName = serviceDescription.Name; + + // Set by BuildAndRunService + var args = service.Status.Args!; + var path = service.Status.ExecutablePath!; + var workingDirectory = service.Status.WorkingDirectory!; + 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