private static string GetRuntimeIdentifier(DeploymentParameters deploymentParameters) { var architecture = deploymentParameters.RuntimeArchitecture; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return("win7-" + architecture); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return("linux-" + architecture); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return("osx-" + architecture); } throw new InvalidOperationException("Unrecognized operation system platform"); }
protected void InvokeUserApplicationCleanup() { using (Logger.BeginScope("UserAdditionalCleanup")) { if (DeploymentParameters.UserAdditionalCleanup != null) { // User cleanup. try { DeploymentParameters.UserAdditionalCleanup(DeploymentParameters); } catch (Exception exception) { Logger.LogWarning("User cleanup code failed with exception : {exception}", exception.Message); } } } }
private static string GetRuntimeIdentifier(DeploymentParameters deploymentParameters) { var architecture = deploymentParameters.RuntimeArchitecture; if (OperatingSystem.IsWindows()) { return("win-" + architecture); } if (OperatingSystem.IsLinux()) { return("linux-" + architecture); } if (OperatingSystem.IsMacOS()) { return("osx-" + architecture); } throw new InvalidOperationException("Unrecognized operation system platform"); }
protected virtual async Task <IISDeploymentResult> DeployAsync(DeploymentParameters parameters) { if (!parameters.EnvironmentVariables.ContainsKey(DebugEnvironmentVariable)) { parameters.EnvironmentVariables[DebugEnvironmentVariable] = "4"; } if (parameters.ServerType == ServerType.IISExpress) { parameters.ServerConfigTemplateContent = parameters.ServerConfigTemplateContent ?? File.ReadAllText("IISExpress.config"); } _deployer = IISApplicationDeployerFactory.Create(parameters, LoggerFactory); var result = await _deployer.DeployAsync(); return(new IISDeploymentResult(result, Logger)); }
public DeploymentParameters(DeploymentParameters parameters) { foreach (var propertyInfo in typeof(DeploymentParameters).GetProperties()) { if (propertyInfo.CanWrite) { propertyInfo.SetValue(this, propertyInfo.GetValue(parameters)); } } foreach (var kvp in parameters.EnvironmentVariables) { EnvironmentVariables.Add(kvp); } foreach (var kvp in parameters.PublishEnvironmentVariables) { PublishEnvironmentVariables.Add(kvp); } }
protected virtual async Task <IISDeploymentResult> DeployAsync(DeploymentParameters parameters) { if (!parameters.EnvironmentVariables.ContainsKey(DebugEnvironmentVariable)) { parameters.EnvironmentVariables[DebugEnvironmentVariable] = "4"; } // Currently hosting throws if the Servertype = IIS. if (parameters.ServerType == ServerType.IIS) { _deployer = new IISDeployer(parameters, LoggerFactory); } else { _deployer = ApplicationDeployerFactory.Create(parameters, LoggerFactory); } var result = await _deployer.DeployAsync(); return(new IISDeploymentResult(result, Logger)); }
public override async Task <PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger) { if (ApplicationPath != deploymentParameters.ApplicationPath) { throw new InvalidOperationException("ApplicationPath mismatch"); } if (deploymentParameters.PublishEnvironmentVariables.Any()) { throw new InvalidOperationException("DeploymentParameters.PublishEnvironmentVariables not supported"); } if (!string.IsNullOrEmpty(deploymentParameters.PublishedApplicationRootPath)) { throw new InvalidOperationException("DeploymentParameters.PublishedApplicationRootPath not supported"); } if (deploymentParameters.RestoreOnPublish) { throw new InvalidOperationException("DeploymentParameters.RestoreOnPublish not supported"); } var dotnetPublishParameters = new DotnetPublishParameters { TargetFramework = deploymentParameters.TargetFramework, Configuration = deploymentParameters.Configuration, ApplicationType = deploymentParameters.ApplicationType, RuntimeArchitecture = deploymentParameters.RuntimeArchitecture }; if (!_publishCache.TryGetValue(dotnetPublishParameters, out var publishedApplication)) { publishedApplication = await base.Publish(deploymentParameters, logger); _publishCache.Add(dotnetPublishParameters, publishedApplication); } return(new PublishedApplication(CopyPublishedOutput(publishedApplication, logger), logger)); }
/// <summary> /// Creates a deployer instance based on settings in <see cref="DeploymentParameters"/>. /// </summary> /// <param name="deploymentParameters"></param> /// <param name="loggerFactory"></param> /// <returns></returns> public static ApplicationDeployer Create(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) { if (deploymentParameters == null) { throw new ArgumentNullException(nameof(deploymentParameters)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } switch (deploymentParameters.ServerType) { case ServerType.IISExpress: return(new IIS.IISExpressDeployer(deploymentParameters, loggerFactory)); case ServerType.IIS: return(new IISDeployer(deploymentParameters, loggerFactory)); default: return(ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)); } }
public IISExpressDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) : base(deploymentParameters, loggerFactory) { }
protected void StartTimer() { Logger.LogInformation($"Deploying {DeploymentParameters.ToString()}"); _stopwatch.Start(); }
public NginxDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) : base(deploymentParameters, loggerFactory) { }
public virtual Task <PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger) { var publishDirectory = CreateTempDirectory(); using (logger.BeginScope("dotnet-publish")) { if (string.IsNullOrEmpty(deploymentParameters.TargetFramework)) { throw new Exception($"A target framework must be specified in the deployment parameters for applications that require publishing before deployment"); } var parameters = $"publish " + $" --output \"{publishDirectory.FullName}\"" + $" --framework {deploymentParameters.TargetFramework}" + $" --configuration {deploymentParameters.Configuration}" // avoids triggering builds of dependencies of the test app which could cause issues like https://github.com/dotnet/arcade/issues/2941 + $" --no-dependencies" + $" /p:TargetArchitecture={deploymentParameters.RuntimeArchitecture}" + (deploymentParameters.RestoreDependencies ? "" : " --no-restore"); if (deploymentParameters.ApplicationType == ApplicationType.Standalone) { parameters += $" --runtime {GetRuntimeIdentifier(deploymentParameters)}"; } else { // Workaround for https://github.com/aspnet/websdk/issues/422 parameters += " -p:UseAppHost=false"; } parameters += $" {deploymentParameters.AdditionalPublishParameters}"; var startInfo = new ProcessStartInfo { FileName = DotnetCommandName, Arguments = parameters, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, WorkingDirectory = deploymentParameters.ApplicationPath, }; ProcessHelpers.AddEnvironmentVariablesToProcess(startInfo, deploymentParameters.PublishEnvironmentVariables, logger); var hostProcess = new Process() { StartInfo = startInfo }; logger.LogInformation($"Executing command {DotnetCommandName} {parameters}"); hostProcess.StartAndCaptureOutAndErrToLogger("dotnet-publish", logger); // A timeout is passed to Process.WaitForExit() for two reasons: // // 1. When process output is read asynchronously, WaitForExit() without a timeout blocks until child processes // are killed, which can cause hangs due to MSBuild NodeReuse child processes started by dotnet.exe. // With a timeout, WaitForExit() returns when the parent process is killed and ignores child processes. // https://stackoverflow.com/a/37983587/102052 // // 2. If "dotnet publish" does hang indefinitely for some reason, tests should fail fast with an error message. var timeout = deploymentParameters.PublishTimeout ?? TimeSpan.FromMinutes(5); if (hostProcess.WaitForExit(milliseconds: (int)timeout.TotalMilliseconds)) { if (hostProcess.ExitCode != 0) { var message = $"{DotnetCommandName} publish exited with exit code : {hostProcess.ExitCode}"; logger.LogError(message); throw new Exception(message); } } else { var message = $"{DotnetCommandName} publish failed to exit after {timeout.TotalMinutes} minutes"; logger.LogError(message); throw new Exception(message); } logger.LogInformation($"{DotnetCommandName} publish finished with exit code : {hostProcess.ExitCode}"); } return(Task.FromResult(new PublishedApplication(publishDirectory.FullName, logger))); }
public PublishOnlyDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) : base(deploymentParameters, loggerFactory) { }
public ApplicationDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) { DeploymentParameters = deploymentParameters; LoggerFactory = loggerFactory; Logger = LoggerFactory.CreateLogger(GetType().FullName); }
public DeploymentResult(ILoggerFactory loggerFactory, DeploymentParameters deploymentParameters, string applicationBaseUri) : this(loggerFactory, deploymentParameters : deploymentParameters, applicationBaseUri : applicationBaseUri, contentRoot : string.Empty, hostShutdownToken : CancellationToken.None) { }
public virtual Task <PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger) { var publishDirectory = CreateTempDirectory(); using (logger.BeginScope("dotnet-publish")) { if (string.IsNullOrEmpty(deploymentParameters.TargetFramework)) { throw new Exception($"A target framework must be specified in the deployment parameters for applications that require publishing before deployment"); } var parameters = $"publish " + $" --output \"{publishDirectory.FullName}\"" + $" --framework {deploymentParameters.TargetFramework}" + $" --configuration {deploymentParameters.Configuration}" + (deploymentParameters.RestoreOnPublish ? string.Empty : " --no-restore -p:VerifyMatchingImplicitPackageVersion=false"); // Set VerifyMatchingImplicitPackageVersion to disable errors when Microsoft.NETCore.App's version is overridden externally // This verification doesn't matter if we are skipping restore during tests. if (deploymentParameters.ApplicationType == ApplicationType.Standalone) { parameters += $" --runtime {GetRuntimeIdentifier(deploymentParameters)}"; } parameters += $" {deploymentParameters.AdditionalPublishParameters}"; var startInfo = new ProcessStartInfo { FileName = DotnetCommandName, Arguments = parameters, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, WorkingDirectory = deploymentParameters.ApplicationPath, }; ProcessHelpers.AddEnvironmentVariablesToProcess(startInfo, deploymentParameters.PublishEnvironmentVariables, logger); var hostProcess = new Process() { StartInfo = startInfo }; logger.LogInformation($"Executing command {DotnetCommandName} {parameters}"); hostProcess.StartAndCaptureOutAndErrToLogger("dotnet-publish", logger); // A timeout is passed to Process.WaitForExit() for two reasons: // // 1. When process output is read asynchronously, WaitForExit() without a timeout blocks until child processes // are killed, which can cause hangs due to MSBuild NodeReuse child processes started by dotnet.exe. // With a timeout, WaitForExit() returns when the parent process is killed and ignores child processes. // https://stackoverflow.com/a/37983587/102052 // // 2. If "dotnet publish" does hang indefinitely for some reason, tests should fail fast with an error message. const int timeoutMinutes = 5; if (hostProcess.WaitForExit(milliseconds: timeoutMinutes * 60 * 1000)) { if (hostProcess.ExitCode != 0) { var message = $"{DotnetCommandName} publish exited with exit code : {hostProcess.ExitCode}"; logger.LogError(message); throw new Exception(message); } } else { var message = $"{DotnetCommandName} publish failed to exit after {timeoutMinutes} minutes"; logger.LogError(message); throw new Exception(message); } logger.LogInformation($"{DotnetCommandName} publish finished with exit code : {hostProcess.ExitCode}"); } return(Task.FromResult(new PublishedApplication(publishDirectory.FullName, logger))); }
public SelfHostDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory) : base(deploymentParameters, loggerFactory) { }