diff --git a/NuGet.config b/NuGet.config index a57f4eaac523..7711f990206e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -24,8 +24,12 @@ + + + + @@ -35,11 +39,13 @@ + + @@ -68,10 +74,13 @@ + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0dd6a6b1aab6..57a146246309 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -15,42 +15,42 @@ b73682307aa0128c5edbec94c2e6a070d13ae6bb - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b @@ -59,14 +59,14 @@ https://github.com/dotnet/core-setup 7d57652f33493fa022125b7f63aad0d70c52d810 - + https://github.com/dotnet/emsdk - dd379007ea0e38b82e87ca5fd61bb43b432eaf7a + b2bf6cec0cb4ce281802ac3951bdd14287aad112 - + https://github.com/dotnet/emsdk - dd379007ea0e38b82e87ca5fd61bb43b432eaf7a + b2bf6cec0cb4ce281802ac3951bdd14287aad112 @@ -131,13 +131,13 @@ https://github.com/dotnet/roslyn 450493a9b4ec6337bced0120e97cb76f4ed783db - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 https://dev.azure.com/devdiv/DevDiv/_git/NuGet-NuGet.Client-Trusted @@ -226,99 +226,99 @@ 51441adcd6c424ae7315d66ce7e96baf34d70369 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 4a2048b77c7de671b08320e346c73da6fd6d9aeb + e1078413a088bdc4c4d5b3cd45faeda03d7d1076 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 4a2048b77c7de671b08320e346c73da6fd6d9aeb + e1078413a088bdc4c4d5b3cd45faeda03d7d1076 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 4a2048b77c7de671b08320e346c73da6fd6d9aeb + e1078413a088bdc4c4d5b3cd45faeda03d7d1076 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 4a2048b77c7de671b08320e346c73da6fd6d9aeb + e1078413a088bdc4c4d5b3cd45faeda03d7d1076 - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf - 75bc144dfb125fb821e28adb648dd35618b23693 + b11f25ba2d9d291ca38621d7ba15ad9563e96d30 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 @@ -339,30 +339,30 @@ 41f3afd466695ac2460260431537fe4d779ff446 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-winforms - 96d636b0e1c0e7b43433f6c5f4920c61e448955a + 6502cec45fb6ee15a78a39105e6cd9ccf2e6c364 - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf - 75bc144dfb125fb821e28adb648dd35618b23693 + b11f25ba2d9d291ca38621d7ba15ad9563e96d30 https://github.com/dotnet/xdt @@ -469,89 +469,89 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 209bf5cfd6f0b329c31faa125790e1d1d820cdb5 + 4e6235b8f9af12335ecd58a0a06b8f4105af2de0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b @@ -585,9 +585,9 @@ 216020cfc0f97a6dd5075191faa55c61a7c27609 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 8381bdb01fe4a26e1f61370e779c78bb73ecc95b + 3879076d9a06ce098d37c3882fb1845a6627335b https://github.com/dotnet/arcade-services diff --git a/eng/Versions.props b/eng/Versions.props index 833761c8d7ef..60539ff11370 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -81,61 +81,61 @@ - 9.0.19-servicing.26370.1 + 9.0.20-servicing.26414.2 - 9.0.19 - 9.0.19-servicing.26367.24 - 9.0.19 - 9.0.19 - 9.0.19-servicing.26367.24 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 + 9.0.20 + 9.0.20-servicing.26413.15 + 9.0.20 + 9.0.20 + 9.0.20-servicing.26413.15 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 8.0.0-rc.1.23414.4 - 9.0.19-servicing.26367.24 - 9.0.19-servicing.26367.24 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 + 9.0.20-servicing.26413.15 + 9.0.20-servicing.26413.15 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 2.1.0 - 9.0.19 + 9.0.20 8.0.0 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 8.0.0 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 - 9.0.19 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 + 9.0.20 4.5.1 4.5.5 8.0.5 4.5.4 - 9.0.19 - 9.0.19 + 9.0.20 + 9.0.20 - 9.0.19-servicing.26371.1 - 9.0.19-servicing.26371.1 - 9.0.19 - 9.0.19 + 9.0.20-servicing.26421.5 + 9.0.20-servicing.26421.5 + 9.0.20 + 9.0.20 @@ -217,19 +217,19 @@ - 9.0.19 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19 - 9.0.19 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 - 9.0.19-servicing.26370.16 + 9.0.20 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20 + 9.0.20 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 + 9.0.20-servicing.26414.7 @@ -239,8 +239,8 @@ - 9.0.19-rtm.26371.2 - 9.0.19-rtm.26371.2 + 9.0.20-rtm.26421.6 + 9.0.20-rtm.26421.6 @@ -319,7 +319,7 @@ 15.0.9617 18.0.9617 - 9.0.19 + 9.0.20 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100PackageVersion) 9.0.100$([System.Text.RegularExpressions.Regex]::Match($(EmscriptenWorkloadManifestVersion), `-(?!rtm)[A-z]*[\.]*\d*`)) diff --git a/src/BuiltInTools/AspireService/Models/RunSessionRequest.cs b/src/BuiltInTools/AspireService/Models/RunSessionRequest.cs index 32d52181449f..c98a008c44a8 100644 --- a/src/BuiltInTools/AspireService/Models/RunSessionRequest.cs +++ b/src/BuiltInTools/AspireService/Models/RunSessionRequest.cs @@ -76,7 +76,7 @@ internal class RunSessionRequest ProjectPath = projectLaunchConfig.ProjectPath, Debug = string.Equals(projectLaunchConfig.LaunchMode, DebugLaunchMode, StringComparison.OrdinalIgnoreCase), Arguments = Arguments, - Environment = Environment.Select(envVar => new KeyValuePair(envVar.Name, envVar.Value!)), + Environment = Environment.Select(envVar => new KeyValuePair(envVar.Name, envVar.Value ?? "")), LaunchProfile = projectLaunchConfig.LaunchProfile, DisableLaunchProfile = projectLaunchConfig.DisableLaunchProfile }; diff --git a/src/BuiltInTools/DotNetDeltaApplier/StartupHook.cs b/src/BuiltInTools/DotNetDeltaApplier/StartupHook.cs index 59787ed4f47b..f4080ea5a032 100644 --- a/src/BuiltInTools/DotNetDeltaApplier/StartupHook.cs +++ b/src/BuiltInTools/DotNetDeltaApplier/StartupHook.cs @@ -84,6 +84,10 @@ private static async Task ReceiveAndApplyUpdatesAsync(NamedPipeClientStream pipe var payloadType = (RequestType)await pipeClient.ReadByteAsync(cancellationToken); switch (payloadType) { + case RequestType.SetEnvironmentVariables: + await SetEnvironmentVariablesAsync(pipeClient, cancellationToken).ConfigureAwait(false); + break; + case RequestType.ManagedCodeUpdate: // Shouldn't get initial managed code updates when the debugger is attached. // The debugger itself applies these updates when launching process with the debugger attached. @@ -123,6 +127,29 @@ private static async Task ReceiveAndApplyUpdatesAsync(NamedPipeClientStream pipe } } + private static async Task SetEnvironmentVariablesAsync(NamedPipeClientStream pipeClient, CancellationToken cancellationToken) + { + var environmentVariableCount = await pipeClient.ReadInt32Async(cancellationToken).ConfigureAwait(false); + + Log($"Setting environment variables ({environmentVariableCount})"); + + for (var i = 0; i < environmentVariableCount; i++) + { + var name = await pipeClient.ReadStringAsync(cancellationToken).ConfigureAwait(false); + var value = await pipeClient.ReadStringAsync(cancellationToken).ConfigureAwait(false); + try + { + Environment.SetEnvironmentVariable(name, value); + } + catch (Exception e) + { + Log($"Unable to set environment variable '{name}' = '{value}': {e.Message}"); + } + } + + await pipeClient.WriteAsync([(byte)ResponseType.EnvironmentVariablesSet], cancellationToken).ConfigureAwait(false); + } + private static async ValueTask ReadAndApplyManagedCodeUpdateAsync( NamedPipeClientStream pipeClient, HotReloadAgent agent, diff --git a/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs b/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs index 62686ddc226c..7feb4e525f42 100644 --- a/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs +++ b/src/BuiltInTools/HotReloadAgent.PipeRpc/NamedPipeContract.cs @@ -22,9 +22,15 @@ internal interface IUpdateRequest : IRequest internal enum RequestType { - ManagedCodeUpdate = 1, - StaticAssetUpdate = 2, - InitialUpdatesCompleted = 3, + SetEnvironmentVariables = 1, + ManagedCodeUpdate = 2, + StaticAssetUpdate = 3, + InitialUpdatesCompleted = 4, +} + +internal enum ResponseType : byte +{ + EnvironmentVariablesSet = 2, } internal readonly struct ManagedCodeUpdateRequest(IReadOnlyList deltas, ResponseLoggingLevel responseLoggingLevel) : IUpdateRequest diff --git a/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs b/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs index a8333af46546..5751b304481f 100644 --- a/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs +++ b/src/BuiltInTools/dotnet-watch/Browser/BrowserRefreshServer.cs @@ -37,6 +37,7 @@ internal sealed class BrowserRefreshServer : IAsyncDisposable, IStaticAssetChang private readonly TaskCompletionSource _terminateWebSocket; private readonly TaskCompletionSource _browserConnected; private readonly string? _environmentHostName; + private readonly ImmutableArray _autoReloadWebSocketOrigins; // initialized by StartAsync private IHost? _refreshServer; @@ -52,6 +53,7 @@ public BrowserRefreshServer(EnvironmentOptions options, IReporter reporter) _terminateWebSocket = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _browserConnected = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _environmentHostName = EnvironmentVariables.AutoReloadWSHostName; + _autoReloadWebSocketOrigins = EnvironmentVariables.AutoReloadWSOrigins; } public async ValueTask DisposeAsync() @@ -118,10 +120,21 @@ public async ValueTask StartAsync(CancellationToken cancellationToken) builder.UseUrls($"http://{hostName}:0"); } + var allowedHosts = new List() { "localhost", "127.0.0.1", "[::1]" }; + if (!_autoReloadWebSocketOrigins.IsDefault) + { + allowedHosts.AddRange(_autoReloadWebSocketOrigins); + } + + if (_environmentHostName != null) + { + allowedHosts.Add(_environmentHostName); + } + builder.Configure(app => { app.UseWebSockets(); - app.Run(WebSocketRequestAsync); + app.Run(context => WebSocketRequestAsync(context, [.. allowedHosts])); }); }) .Build(); @@ -159,11 +172,19 @@ private IEnumerable GetServerUrls(IHost server) ]; } - private async Task WebSocketRequestAsync(HttpContext context) + private async Task WebSocketRequestAsync(HttpContext context, ImmutableArray allowedHosts) { if (!context.WebSockets.IsWebSocketRequest) { - context.Response.StatusCode = 400; + context.Response.StatusCode = StatusCodes.Status400BadRequest; + return; + } + + // check the domain of the Origin header: + if (!Uri.TryCreate(context.Request.Headers.Origin.FirstOrDefault(), UriKind.Absolute, out var originUri) || + !allowedHosts.Contains(originUri.Host, StringComparer.OrdinalIgnoreCase)) + { + context.Response.StatusCode = StatusCodes.Status403Forbidden; return; } diff --git a/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs b/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs index 650336813222..9d9e740b44c9 100644 --- a/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs +++ b/src/BuiltInTools/dotnet-watch/EnvironmentVariables.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Immutable; + namespace Microsoft.DotNet.Watch; internal static class EnvironmentVariables @@ -46,6 +48,14 @@ public static class Names public static string TestOutputDir => Environment.GetEnvironmentVariable("__DOTNET_WATCH_TEST_OUTPUT_DIR") ?? ""; public static string? AutoReloadWSHostName => Environment.GetEnvironmentVariable("DOTNET_WATCH_AUTO_RELOAD_WS_HOSTNAME"); + + /// + /// A list of additional domains, other than localhost and , + /// allowed as origins of connections to the broser refresh web socket. + /// Use when the browser opens the app on a custom domain. + /// + public static ImmutableArray AutoReloadWSOrigins = ReadList("DOTNET_WATCH_AUTO_RELOAD_WS_ORIGINS", separators: [';', ',']); + public static string? BrowserPath => Environment.GetEnvironmentVariable("DOTNET_WATCH_BROWSER_PATH"); private static bool ReadBool(string variableName) @@ -53,4 +63,9 @@ private static bool ReadBool(string variableName) private static TimeSpan ReadTimeSpan(string variableName, TimeSpan defaultValue) => Environment.GetEnvironmentVariable(variableName) is var value && long.TryParse(value, out var intValue) && intValue >= 0 ? TimeSpan.FromMilliseconds(intValue) : defaultValue; + + private static ImmutableArray ReadList(string variableName, char[] separators) + => Environment.GetEnvironmentVariable(variableName) is { } value + ? [.. value.Split(separators, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)] + : []; } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs index 617d7d733856..a370363d128c 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs @@ -31,7 +31,7 @@ public override void Dispose() // Do nothing. } - public override void CreateConnection(string namedPipeName, CancellationToken cancellationToken) + public override void CreateConnection(string namedPipeName, IReadOnlyCollection<(string name, string value)> environmentVariables, CancellationToken cancellationToken) { } diff --git a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs index 2499e85e13c1..6ca7a21090c2 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyHostedDeltaApplier.cs @@ -19,10 +19,10 @@ public override void Dispose() _wasmApplier.Dispose(); } - public override void CreateConnection(string namedPipeName, CancellationToken cancellationToken) + public override void CreateConnection(string namedPipeName, IReadOnlyCollection<(string name, string value)> environmentVariables, CancellationToken cancellationToken) { - _wasmApplier.CreateConnection(namedPipeName, cancellationToken); - _hostApplier.CreateConnection(namedPipeName, cancellationToken); + _wasmApplier.CreateConnection(namedPipeName, environmentVariables, cancellationToken); + _hostApplier.CreateConnection(namedPipeName, environmentVariables, cancellationToken); } public override Task WaitForProcessRunningAsync(CancellationToken cancellationToken) diff --git a/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs b/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs index 15c4ea831d9b..cc13196a5532 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs @@ -132,7 +132,7 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project // It is important to first create the named pipe connection (delta applier is the server) // and then start the process (named pipe client). Otherwise, the connection would fail. - deltaApplier.CreateConnection(namedPipeName, processCommunicationCancellationSource.Token); + deltaApplier.CreateConnection(namedPipeName, projectOptions.LaunchEnvironmentVariables, processCommunicationCancellationSource.Token); processSpec.OnExit += (_, _) => { diff --git a/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs index 5d7f507984cc..02e678789179 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/DefaultDeltaApplier.cs @@ -17,7 +17,7 @@ internal sealed class DefaultDeltaApplier(IReporter reporter) : SingleProcessDel private NamedPipeServerStream? _pipe; private bool _managedCodeUpdateFailedOrCancelled; - public override void CreateConnection(string namedPipeName, CancellationToken cancellationToken) + public override void CreateConnection(string namedPipeName, IReadOnlyCollection<(string name, string value)> environmentVariables, CancellationToken cancellationToken) { _pipe = new NamedPipeServerStream(namedPipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous | PipeOptions.CurrentUserOnly); @@ -38,6 +38,10 @@ async Task> ConnectAsync() var capabilities = (await ClientInitializationResponse.ReadAsync(_pipe, cancellationToken)).Capabilities; Reporter.Verbose($"Capabilities: '{capabilities}'"); + + // Initialize process: + await SetEnvironmentVariablesAsync(environmentVariables, cancellationToken); + return [.. capabilities.Split(' ')]; } catch (EndOfStreamException) @@ -50,7 +54,7 @@ async Task> ConnectAsync() // pipe might throw another exception when forcibly closed on process termination: if (!cancellationToken.IsCancellationRequested) { - Reporter.Error($"Failed to read capabilities: {e.Message}"); + Reporter.Error($"Failed to read capabilities: {e}"); } return []; @@ -58,6 +62,32 @@ async Task> ConnectAsync() } } + public async ValueTask SetEnvironmentVariablesAsync(IReadOnlyCollection<(string name, string value)> environmentVariables, CancellationToken cancellationToken) + { + if (environmentVariables.Count == 0) + { + return; + } + + Debug.Assert(_pipe != null); + + // Send a request to set environment variables: + await _pipe.WriteAsync((byte)RequestType.SetEnvironmentVariables, cancellationToken); + await _pipe.WriteAsync(environmentVariables.Count, cancellationToken); + foreach (var (name, value) in environmentVariables) + { + await _pipe.WriteAsync(name, cancellationToken); + await _pipe.WriteAsync(value, cancellationToken); + } + + // Wait until the environment variables are set in the target process: + var responseType = (ResponseType)await _pipe.ReadByteAsync(cancellationToken); + if (responseType != ResponseType.EnvironmentVariablesSet) + { + throw new InvalidOperationException($"Unexpected response received from the agent: {responseType}"); + } + } + public override Task WaitForProcessRunningAsync(CancellationToken cancellationToken) // Should only be called after CreateConnection => _capabilitiesTask ?? throw new InvalidOperationException(); diff --git a/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs index 852c9295e949..154bb04cfc4c 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/DeltaApplier.cs @@ -14,7 +14,7 @@ internal abstract class DeltaApplier(IReporter reporter) : IDisposable public static readonly string StartupHookPath = Path.Combine(AppContext.BaseDirectory, "hotreload", "Microsoft.Extensions.DotNetDeltaApplier.dll"); - public abstract void CreateConnection(string namedPipeName, CancellationToken cancellationToken); + public abstract void CreateConnection(string namedPipeName, IReadOnlyCollection<(string name, string value)> environmentVariables, CancellationToken cancellationToken); /// /// Waits for the application process to start. diff --git a/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs b/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs index c68073001705..6d0e82c2740c 100644 --- a/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs +++ b/src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs @@ -61,18 +61,6 @@ public EnvironmentOptions EnvironmentOptions var environmentBuilder = EnvironmentVariablesBuilder.FromCurrentEnvironment(); var namedPipeName = Guid.NewGuid().ToString(); - foreach (var (name, value) in projectOptions.LaunchEnvironmentVariables) - { - // ignore dotnet-watch reserved variables -- these shouldn't be set by the project - if (name.Equals(EnvironmentVariables.Names.AspNetCoreHostingStartupAssemblies, StringComparison.OrdinalIgnoreCase) || - name.Equals(EnvironmentVariables.Names.DotNetStartupHooks, StringComparison.OrdinalIgnoreCase)) - { - continue; - } - - environmentBuilder.SetVariable(name, value); - } - // override any project settings: environmentBuilder.SetVariable(EnvironmentVariables.Names.DotnetWatch, "1"); environmentBuilder.SetVariable(EnvironmentVariables.Names.DotnetWatchIteration, (Iteration + 1).ToString(CultureInfo.InvariantCulture)); diff --git a/test/Microsoft.NET.TestFramework/TestCommandLine.cs b/test/Microsoft.NET.TestFramework/TestCommandLine.cs index 2519a063e819..7d71ff429037 100644 --- a/test/Microsoft.NET.TestFramework/TestCommandLine.cs +++ b/test/Microsoft.NET.TestFramework/TestCommandLine.cs @@ -43,7 +43,7 @@ public static TestCommandLine Parse(string[] args) { RemainingArgs = new List() }; - Stack argStack = new(args.Reverse()); + Stack argStack = new(((IEnumerable)args).Reverse()); while (argStack.Any()) { diff --git a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs index 0914da6c407f..e5ff04117461 100644 --- a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs +++ b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs @@ -650,6 +650,9 @@ public async Task Aspire() App.Start(testAsset, ["-lp", "http"], relativeProjectDirectory: "WatchAspire.AppHost", testFlags: TestFlags.ReadKeyFromStdin); + // DEBUG_* environment variables should be set for app host process: + await App.WaitUntilOutputContains("Setting environment variables (3)"); + await App.AssertWaitingForChanges(); // check that Aspire server output is logged via dotnet-watch reporter: