From ea2f369e37ee99398f99db13ecd01ca53a418199 Mon Sep 17 00:00:00 2001 From: Orion Edwards Date: Fri, 9 Oct 2026 14:29:56 +1300 Subject: [PATCH 1/5] Update to .NET 10 - global.json SDK 8.0.303 -> 10.0.100 - Retarget net8.0 -> net10.0 (net48 retained on Windows) - Nuke.Common 8.0.0 -> 10.1.0 and nuke.globaltool 6.0.3 -> 10.1.0; adapt Build.cs to Nuke 10 APIs - Remove/condition package references that are in-box on net10.0 (NU1510) - Bump build/test-only packages flagged by NuGet audit: SourceLink 10.0.401, SSH.NET 2026.0.0, System.Drawing.Common 5.0.3 - Suppress SYSLIB0057/SYSLIB0014 where net48 compatibility requires the obsolete APIs - Resolve WebSocketStream and async LINQ ambiguities with new .NET 10 BCL types - Adjust compressed-size test expectations for zlib-ng on .NET 9+ Co-Authored-By: Claude Opus 5.5 --- .config/dotnet-tools.json | 2 +- .nuke/build.schema.json | 180 +++++++++--------- build/Build.cs | 7 +- build/_build.csproj | 4 +- global.json | 2 +- .../Halibut.TestProxy.csproj | 6 +- ...Halibut.TestUtils.CompatBinary.Base.csproj | 4 +- .../SettingsHelper.cs | 4 + ...libut.TestUtils.CompatBinary.v4_4_8.csproj | 4 +- ...but.TestUtils.CompatBinary.v5_0_236.csproj | 4 +- ...but.TestUtils.CompatBinary.v6_0_658.csproj | 5 +- .../Halibut.TestUtils.Contracts.csproj | 4 +- .../Halibut.Tests.DotMemory/Certificates.cs | 8 + .../Halibut.Tests.DotMemory.csproj | 4 +- source/Halibut.Tests/FriendlyHtmlPageTests.cs | 6 + source/Halibut.Tests/Halibut.Tests.csproj | 11 +- .../Support/AsyncEnumerableCompat.cs | 28 +++ source/Halibut.Tests/Support/Certificates.cs | 10 + .../SyncIoRecordingWebSocketStream.cs | 2 +- .../TempDisposableCertAndThumbprint.cs | 2 + .../TestServices/AsyncComplexObjectService.cs | 5 +- .../Protocol/MessageSerializerFixture.cs | 17 +- source/Halibut.Tests/UsageFixture.cs | 9 +- source/Halibut/Halibut.csproj | 13 +- .../Transport/ClientCertificateValidator.cs | 2 + source/Halibut/Transport/DiscoveryClient.cs | 2 + source/Halibut/Transport/SecureListener.cs | 2 + .../Transport/SecureWebSocketListener.cs | 2 + .../Transport/ServerCertificateInterceptor.cs | 2 + .../Transport/Streams/StreamFactory.cs | 2 +- .../Octopus.TestPortForwarder.csproj | 4 +- 31 files changed, 219 insertions(+), 138 deletions(-) create mode 100644 source/Halibut.Tests/Support/AsyncEnumerableCompat.cs diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 0dfbccc4e..3804712a3 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "nuke.globaltool": { - "version": "6.0.3", + "version": "10.1.0", "commands": [ "nuke" ] diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index b96a92417..d716ee559 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -1,23 +1,56 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/build", - "title": "Build Schema", "definitions": { - "build": { - "type": "object", + "Host": { + "type": "string", + "enum": [ + "AppVeyor", + "AzurePipelines", + "Bamboo", + "Bitbucket", + "Bitrise", + "GitHubActions", + "GitLab", + "Jenkins", + "Rider", + "SpaceAutomation", + "TeamCity", + "Terminal", + "TravisCI", + "VisualStudio", + "VSCode" + ] + }, + "ExecutableTarget": { + "type": "string", + "enum": [ + "Clean", + "Compile", + "CompileNet48", + "CompileNet80", + "CopyToLocalPackages", + "Default", + "Pack", + "PackTestPortForwarder", + "Restore", + "TestLinux", + "TestWindows", + "TestWindowsNet48", + "TestWindowsNet80" + ] + }, + "Verbosity": { + "type": "string", + "description": "", + "enum": [ + "Verbose", + "Normal", + "Minimal", + "Quiet" + ] + }, + "NukeBuild": { "properties": { - "AutoDetectBranch": { - "type": "boolean", - "description": "Whether to auto-detect the branch name - this is okay for a local build, but should not be used under CI" - }, - "Configuration": { - "type": "string", - "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", - "enum": [ - "Debug", - "Release" - ] - }, "Continue": { "type": "boolean", "description": "Indicates to continue a previously failed build attempt" @@ -27,34 +60,13 @@ "description": "Shows the help text for this build assembly" }, "Host": { - "type": "string", "description": "Host for execution. Default is 'automatic'", - "enum": [ - "AppVeyor", - "AzurePipelines", - "Bamboo", - "Bitbucket", - "Bitrise", - "GitHubActions", - "GitLab", - "Jenkins", - "Rider", - "SpaceAutomation", - "TeamCity", - "Terminal", - "TravisCI", - "VisualStudio", - "VSCode" - ] + "$ref": "#/definitions/Host" }, "NoLogo": { "type": "boolean", "description": "Disables displaying the NUKE logo" }, - "OCTOVERSION_CurrentBranch": { - "type": "string", - "description": "Branch name for OctoVersion to use to calculate the version number. Can be set via the environment variable OCTOVERSION_CurrentBranch" - }, "Partition": { "type": "string", "description": "Partition to use on CI" @@ -74,73 +86,65 @@ "type": "string", "description": "Root directory during build execution" }, - "RunDotMemoryTests": { - "type": "boolean", - "description": "True if dot memory tests should be run, otherwise false. Default to True for Windows and False for Linux" - }, "Skip": { "type": "array", "description": "List of targets to be skipped. Empty list skips all dependencies", "items": { - "type": "string", - "enum": [ - "Clean", - "Compile", - "CompileNet48", - "CompileNet80", - "CopyToLocalPackages", - "Default", - "Pack", - "PackTestPortForwarder", - "Restore", - "TestLinux", - "TestWindows", - "TestWindowsNet48", - "TestWindowsNet80" - ] + "$ref": "#/definitions/ExecutableTarget" } }, - "Solution": { - "type": "string", - "description": "Path to a solution file that is automatically loaded" - }, "Target": { "type": "array", "description": "List of targets to be invoked. Default is '{default_target}'", "items": { - "type": "string", - "enum": [ - "Clean", - "Compile", - "CompileNet48", - "CompileNet80", - "CopyToLocalPackages", - "Default", - "Pack", - "PackTestPortForwarder", - "Restore", - "TestLinux", - "TestWindows", - "TestWindowsNet48", - "TestWindowsNet80" - ] + "$ref": "#/definitions/ExecutableTarget" } }, - "TestFilter": { - "type": "string", - "description": "The test Filter passed to dotnet test e.g. TestCategory=Async" - }, "Verbosity": { - "type": "string", "description": "Logging verbosity during build execution. Default is 'Normal'", + "$ref": "#/definitions/Verbosity" + } + } + } + }, + "allOf": [ + { + "properties": { + "AutoDetectBranch": { + "type": "boolean", + "description": "Whether to auto-detect the branch name - this is okay for a local build, but should not be used under CI" + }, + "Configuration": { + "type": "string", + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", "enum": [ - "Minimal", - "Normal", - "Quiet", - "Verbose" + "Debug", + "Release" ] + }, + "OCTOVERSION_CurrentBranch": { + "type": "string", + "description": "Branch name for OctoVersion to use to calculate the version number. Can be set via the environment variable OCTOVERSION_CurrentBranch" + }, + "RunDotMemoryTests": { + "type": [ + "boolean", + "null" + ], + "description": "True if dot memory tests should be run, otherwise false. Default to True for Windows and False for Linux" + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + }, + "TestFilter": { + "type": "string", + "description": "The test Filter passed to dotnet test e.g. TestCategory=Async" } } + }, + { + "$ref": "#/definitions/NukeBuild" } - } + ] } diff --git a/build/Build.cs b/build/Build.cs index 98bdb3599..67e76ce76 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -10,7 +10,6 @@ using Nuke.Common.Tools.OctoVersion; using Nuke.Common.Utilities; using Nuke.Common.Utilities.Collections; -using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.Tools.DotMemoryUnit.DotMemoryUnitTasks; using static Nuke.Common.Tools.DotNet.DotNetTasks; @@ -81,7 +80,7 @@ class Build : NukeBuild Target CompileNet48 => _ => CompileDefinition(_, "net48"); - Target CompileNet80 => _ => CompileDefinition(_, "net8.0"); + Target CompileNet80 => _ => CompileDefinition(_, "net10.0"); ITargetDefinition CompileDefinition(ITargetDefinition targetDefinition, [CanBeNull] string framework) { @@ -109,7 +108,7 @@ ITargetDefinition CompileDefinition(ITargetDefinition targetDefinition, [CanBeNu Target TestWindowsNet48 => _ => TestDefinition(_, CompileNet48, "net48", runDotMemoryTests: true); [PublicAPI] - Target TestWindowsNet80 => _ => TestDefinition(_, CompileNet80, "net8.0", runDotMemoryTests: false); + Target TestWindowsNet80 => _ => TestDefinition(_, CompileNet80, "net10.0", runDotMemoryTests: false); ITargetDefinition TestDefinition(ITargetDefinition targetDefinition, Target dependsOn, [CanBeNull] string framework, bool runDotMemoryTests) { @@ -166,7 +165,7 @@ ITargetDefinition TestDefinition(ITargetDefinition targetDefinition, Target depe { LocalPackagesDirectory.CreateDirectory(); ArtifactsDirectory.GlobFiles("*.nupkg") - .ForEach(package => CopyFileToDirectory(package, LocalPackagesDirectory, FileExistsPolicy.Overwrite)); + .ForEach(package => package.CopyToDirectory(LocalPackagesDirectory, ExistsPolicy.FileOverwrite)); }); [PublicAPI] diff --git a/build/_build.csproj b/build/_build.csproj index 7679e4a44..f1850c939 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 CS0649;CS0169 .. @@ -11,7 +11,7 @@ - + diff --git a/global.json b/global.json index 6a14d5d34..45f723296 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.303", + "version": "10.0.100", "rollForward": "latestFeature" } } diff --git a/source/Halibut.TestProxy/Halibut.TestProxy.csproj b/source/Halibut.TestProxy/Halibut.TestProxy.csproj index 1440b763c..d3ec080a1 100644 --- a/source/Halibut.TestProxy/Halibut.TestProxy.csproj +++ b/source/Halibut.TestProxy/Halibut.TestProxy.csproj @@ -8,16 +8,16 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 - + diff --git a/source/Halibut.TestUtils.CompatBinary.Base/Halibut.TestUtils.CompatBinary.Base.csproj b/source/Halibut.TestUtils.CompatBinary.Base/Halibut.TestUtils.CompatBinary.Base.csproj index bc01e10da..f9e4221aa 100644 --- a/source/Halibut.TestUtils.CompatBinary.Base/Halibut.TestUtils.CompatBinary.Base.csproj +++ b/source/Halibut.TestUtils.CompatBinary.Base/Halibut.TestUtils.CompatBinary.Base.csproj @@ -8,10 +8,10 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 diff --git a/source/Halibut.TestUtils.CompatBinary.Base/SettingsHelper.cs b/source/Halibut.TestUtils.CompatBinary.Base/SettingsHelper.cs index eb453ddb1..5deec8ffb 100644 --- a/source/Halibut.TestUtils.CompatBinary.Base/SettingsHelper.cs +++ b/source/Halibut.TestUtils.CompatBinary.Base/SettingsHelper.cs @@ -76,7 +76,9 @@ public static X509Certificate2 GetClientCertificate() { var octopusCertPath = GetSetting("octopuscertpath"); //Console.WriteLine($"Using octopus cert path: {octopusCertPath}"); +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var clientCert = new X509Certificate2(octopusCertPath); +#pragma warning restore SYSLIB0057 //Console.WriteLine("Octopus/Client cert details " + clientCert); return clientCert; @@ -94,7 +96,9 @@ public static X509Certificate2 GetServiceCertificate() { var tentacleCertPath = GetSetting("tentaclecertpath"); //Console.WriteLine($"Using tentacle cert path: {tentacleCertPath}"); +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var serviceCert = new X509Certificate2(tentacleCertPath); +#pragma warning restore SYSLIB0057 //Console.WriteLine("Tentacle/service cert details " + serviceCert); return serviceCert; diff --git a/source/Halibut.TestUtils.CompatBinary.v4_4_8/Halibut.TestUtils.CompatBinary.v4_4_8.csproj b/source/Halibut.TestUtils.CompatBinary.v4_4_8/Halibut.TestUtils.CompatBinary.v4_4_8.csproj index c6dedf19e..fb8020cb2 100644 --- a/source/Halibut.TestUtils.CompatBinary.v4_4_8/Halibut.TestUtils.CompatBinary.v4_4_8.csproj +++ b/source/Halibut.TestUtils.CompatBinary.v4_4_8/Halibut.TestUtils.CompatBinary.v4_4_8.csproj @@ -9,10 +9,10 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 diff --git a/source/Halibut.TestUtils.CompatBinary.v5_0_236/Halibut.TestUtils.CompatBinary.v5_0_236.csproj b/source/Halibut.TestUtils.CompatBinary.v5_0_236/Halibut.TestUtils.CompatBinary.v5_0_236.csproj index ab4610de5..f56052e66 100644 --- a/source/Halibut.TestUtils.CompatBinary.v5_0_236/Halibut.TestUtils.CompatBinary.v5_0_236.csproj +++ b/source/Halibut.TestUtils.CompatBinary.v5_0_236/Halibut.TestUtils.CompatBinary.v5_0_236.csproj @@ -9,10 +9,10 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 diff --git a/source/Halibut.TestUtils.CompatBinary.v6_0_658/Halibut.TestUtils.CompatBinary.v6_0_658.csproj b/source/Halibut.TestUtils.CompatBinary.v6_0_658/Halibut.TestUtils.CompatBinary.v6_0_658.csproj index 347d8068a..d8027b54f 100644 --- a/source/Halibut.TestUtils.CompatBinary.v6_0_658/Halibut.TestUtils.CompatBinary.v6_0_658.csproj +++ b/source/Halibut.TestUtils.CompatBinary.v6_0_658/Halibut.TestUtils.CompatBinary.v6_0_658.csproj @@ -9,14 +9,15 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 + diff --git a/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj b/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj index e42348846..61eba0ece 100644 --- a/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj +++ b/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj @@ -8,10 +8,10 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 diff --git a/source/Halibut.Tests.DotMemory/Certificates.cs b/source/Halibut.Tests.DotMemory/Certificates.cs index bc22c4439..7db89fb20 100644 --- a/source/Halibut.Tests.DotMemory/Certificates.cs +++ b/source/Halibut.Tests.DotMemory/Certificates.cs @@ -26,17 +26,25 @@ static Certificates() //jump through hoops to find certs because the nunit test runner is messing with directories var directory = Path.Combine(Path.GetDirectoryName(new Uri(typeof(Certificates).Assembly.Location).LocalPath)!, "Certificates"); TentacleListeningPfxPath = Path.Combine(directory, "TentacleListening.pfx"); +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 TentacleListening = new X509Certificate2(TentacleListeningPfxPath); +#pragma warning restore SYSLIB0057 TentacleListeningPublicThumbprint = TentacleListening.Thumbprint; OctopusPfxPath = Path.Combine(directory, "Octopus.pfx"); +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 Octopus = new X509Certificate2(OctopusPfxPath); +#pragma warning restore SYSLIB0057 OctopusPublicThumbprint = Octopus.Thumbprint; TentaclePollingPfxPath = Path.Combine(directory, "TentaclePolling.pfx"); +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 TentaclePolling = new X509Certificate2(TentaclePollingPfxPath); +#pragma warning restore SYSLIB0057 TentaclePollingPublicThumbprint = TentaclePolling.Thumbprint; +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 Ssl = new X509Certificate2(Path.Combine(directory, "Ssl.pfx"), "password"); +#pragma warning restore SYSLIB0057 SslThumbprint = Ssl.Thumbprint; } } diff --git a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj index 3b556a710..aea96d6d7 100644 --- a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj +++ b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj @@ -10,10 +10,10 @@ enable - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 diff --git a/source/Halibut.Tests/FriendlyHtmlPageTests.cs b/source/Halibut.Tests/FriendlyHtmlPageTests.cs index 9bb4ffadc..7ede856a9 100644 --- a/source/Halibut.Tests/FriendlyHtmlPageTests.cs +++ b/source/Halibut.Tests/FriendlyHtmlPageTests.cs @@ -121,11 +121,15 @@ static async Task>> GetHeadersIgnoringCertific using (var client = new HttpClient(httpClientHandler)) { var headers = new List>(); +#pragma warning disable SYSLIB0014 var existingServerCertificateValidationCallback = ServicePointManager.ServerCertificateValidationCallback; +#pragma warning restore SYSLIB0014 try { // We need to ignore server certificate validation errors - the server certificate is self-signed +#pragma warning disable SYSLIB0014 ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; +#pragma warning restore SYSLIB0014 var response = await client.GetAsync(uri); foreach (var key in response.Headers) { @@ -135,7 +139,9 @@ static async Task>> GetHeadersIgnoringCertific finally { // And restore it back to default behaviour +#pragma warning disable SYSLIB0014 ServicePointManager.ServerCertificateValidationCallback = existingServerCertificateValidationCallback; +#pragma warning restore SYSLIB0014 } return headers; diff --git a/source/Halibut.Tests/Halibut.Tests.csproj b/source/Halibut.Tests/Halibut.Tests.csproj index 602280ad8..61c984f8e 100644 --- a/source/Halibut.Tests/Halibut.Tests.csproj +++ b/source/Halibut.Tests/Halibut.Tests.csproj @@ -7,15 +7,15 @@ true false 9.0 - VSTHRD002,VSTHRD003;VSTHRD103 + VSTHRD002,VSTHRD003;VSTHRD103;CA2022 enable true - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 @@ -46,18 +46,19 @@ - + + $(DefineConstants);SUPPORTS_WEB_SOCKET_CLIENT;DOES_NOT_SUPPORT_CANCELLATION_ON_SOCKETS - + $(DefineConstants);HAS_TCP_KEEP_ALIVE_SOCKET_OPTIONS diff --git a/source/Halibut.Tests/Support/AsyncEnumerableCompat.cs b/source/Halibut.Tests/Support/AsyncEnumerableCompat.cs new file mode 100644 index 000000000..9b5ed6f46 --- /dev/null +++ b/source/Halibut.Tests/Support/AsyncEnumerableCompat.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Halibut.Tests.Support +{ + // On net10.0 the framework's System.Linq.AsyncEnumerable and the System.Linq.Async package + // (pulled in by System.Interactive.Async on net48) both define ToAsyncEnumerable and SelectAwait-style + // operators, which makes calls ambiguous or unavailable. These helpers give both targets one implementation. + public static class AsyncEnumerableCompat + { + public static async IAsyncEnumerable ToAsyncEnumerableCompat(this IEnumerable source) + { + foreach (var item in source) + { + yield return item; + } + } + + public static async IAsyncEnumerable SelectAwaitCompat(this IAsyncEnumerable source, Func> selector) + { + await foreach (var item in source) + { + yield return await selector(item); + } + } + } +} diff --git a/source/Halibut.Tests/Support/Certificates.cs b/source/Halibut.Tests/Support/Certificates.cs index bd0a31f1a..d1c13d164 100644 --- a/source/Halibut.Tests/Support/Certificates.cs +++ b/source/Halibut.Tests/Support/Certificates.cs @@ -31,23 +31,33 @@ static Certificates() //jump through hoops to find certs because the nunit test runner is messing with directories var directory = Path.Combine(Path.GetDirectoryName(new Uri(typeof(Certificates).Assembly.Location).LocalPath)!, "Certificates"); TentacleListeningPfxPath = Path.Combine(directory, "TentacleListening.pfx"); +#pragma warning disable SYSLIB0057 TentacleListening = new X509Certificate2(TentacleListeningPfxPath); +#pragma warning restore SYSLIB0057 TentacleListeningPublicThumbprint = TentacleListening.Thumbprint; OctopusPfxPath = Path.Combine(directory, "Octopus.pfx"); +#pragma warning disable SYSLIB0057 Octopus = new X509Certificate2(OctopusPfxPath); +#pragma warning restore SYSLIB0057 OctopusPublicThumbprint = Octopus.Thumbprint; TentaclePollingPfxPath = Path.Combine(directory, "TentaclePolling.pfx"); +#pragma warning disable SYSLIB0057 TentaclePolling = new X509Certificate2(TentaclePollingPfxPath); +#pragma warning restore SYSLIB0057 TentaclePollingPublicThumbprint = TentaclePolling.Thumbprint; WrongPfxPath = Path.Combine(directory, "WrongCert.pfx"); +#pragma warning disable SYSLIB0057 Wrong = new X509Certificate2(WrongPfxPath); +#pragma warning restore SYSLIB0057 WrongPublicThumbprint = Wrong.Thumbprint; sslPfxPath = Path.Combine(directory, "Ssl.pfx"); +#pragma warning disable SYSLIB0057 Ssl = new X509Certificate2(sslPfxPath, "password"); +#pragma warning restore SYSLIB0057 SslThumbprint = Ssl.Thumbprint; } } diff --git a/source/Halibut.Tests/Support/Streams/SynIoRecording/SyncIoRecordingWebSocketStream.cs b/source/Halibut.Tests/Support/Streams/SynIoRecording/SyncIoRecordingWebSocketStream.cs index 4bb1c57f5..e0ad329d9 100644 --- a/source/Halibut.Tests/Support/Streams/SynIoRecording/SyncIoRecordingWebSocketStream.cs +++ b/source/Halibut.Tests/Support/Streams/SynIoRecording/SyncIoRecordingWebSocketStream.cs @@ -5,7 +5,7 @@ namespace Halibut.Tests.Support.Streams.SynIoRecording { - public class SyncIoRecordingWebSocketStream : WebSocketStream, IRecordSyncIo + public class SyncIoRecordingWebSocketStream : Halibut.Transport.Protocol.WebSocketStream, IRecordSyncIo { readonly List syncCalls = new(); diff --git a/source/Halibut.Tests/Support/TempDisposableCertAndThumbprint.cs b/source/Halibut.Tests/Support/TempDisposableCertAndThumbprint.cs index 2c952fec0..cf2469482 100644 --- a/source/Halibut.Tests/Support/TempDisposableCertAndThumbprint.cs +++ b/source/Halibut.Tests/Support/TempDisposableCertAndThumbprint.cs @@ -49,7 +49,9 @@ public static ICertAndThumbprint CreateSelfSigned(DisposableCollection disposedB var bytes = certificate.Export(X509ContentType.Pfx); var filePath = Path.Combine(tempDir.DirectoryPath, $"{name}.pfx"); File.WriteAllBytes(filePath, bytes); +#pragma warning disable SYSLIB0057 var disposableCert = new TempDisposableCertAndThumbprint(tempDir, filePath, new X509Certificate2(bytes)); +#pragma warning restore SYSLIB0057 disposedBy.Add(disposableCert); return disposableCert; } diff --git a/source/Halibut.Tests/TestServices/AsyncComplexObjectService.cs b/source/Halibut.Tests/TestServices/AsyncComplexObjectService.cs index c37262a37..b50faa4b0 100644 --- a/source/Halibut.Tests/TestServices/AsyncComplexObjectService.cs +++ b/source/Halibut.Tests/TestServices/AsyncComplexObjectService.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Halibut.Tests.Support; using Halibut.Tests.Util; using Halibut.TestUtils.Contracts; @@ -28,13 +29,13 @@ public async Task ProcessAsync(ComplexObjectMulti { ChildPayload1 = await ReadIntoNewDataStream(request.Child1!.ChildPayload1, cancellationToken), ChildPayload2 = await ReadIntoNewDataStream(request.Child1!.ChildPayload2, cancellationToken), - ListOfStreams = await request.Child1.ListOfStreams!.ToAsyncEnumerable().SelectAwait(async ds => await ReadIntoNewDataStream(ds, cancellationToken)).ToListAsync(cancellationToken), + ListOfStreams = await request.Child1.ListOfStreams!.ToAsyncEnumerableCompat().SelectAwaitCompat(async ds => await ReadIntoNewDataStream(ds, cancellationToken)).ToListAsync(cancellationToken), DictionaryPayload = request.Child1.DictionaryPayload!.ToDictionary(pair => pair.Key, pair => pair.Value), }, Child2 = new ComplexChild2 { EnumPayload = request.Child2!.EnumPayload, - ComplexPayloadSet = await request.Child2.ComplexPayloadSet!.ToAsyncEnumerable().SelectAwait(async x => new ComplexPair(x.EnumValue, await ReadIntoNewDataStream(x.Payload, cancellationToken))).ToHashSetAsync(cancellationToken) + ComplexPayloadSet = await request.Child2.ComplexPayloadSet!.ToAsyncEnumerableCompat().SelectAwaitCompat(async x => new ComplexPair(x.EnumValue, await ReadIntoNewDataStream(x.Payload, cancellationToken))).ToHashSetAsync(cancellationToken: cancellationToken) } }; } diff --git a/source/Halibut.Tests/Transport/Protocol/MessageSerializerFixture.cs b/source/Halibut.Tests/Transport/Protocol/MessageSerializerFixture.cs index c36acdd85..3ac48bedb 100644 --- a/source/Halibut.Tests/Transport/Protocol/MessageSerializerFixture.cs +++ b/source/Halibut.Tests/Transport/Protocol/MessageSerializerFixture.cs @@ -16,6 +16,13 @@ namespace Halibut.Tests.Transport.Protocol { public class MessageSerializerFixture : BaseTest { +#if NETFRAMEWORK + const long ExpectedCompressedBytes = 55; +#else + // .NET 9+ uses zlib-ng for DeflateStream, which produces slightly different output. + const long ExpectedCompressedBytes = 57; +#endif + [Test] [TestCaseSource(typeof(MessageSerializerTestCaseSource))] public async Task SendReceiveMessageShouldRoundTrip(MessageSerializerTestCase testCase) @@ -52,8 +59,8 @@ public async Task WriteMessage_ObservesThatMessageIsWritten(MessageSerializerTes } var writtenMessage = messageSerializerObserver.MessagesWritten.Should().ContainSingle().Subject; - writtenMessage.CompressedBytesWritten.Should().Be(55); - var expectedCompressedBytesWrittenIntoMemory = testCase.AsyncMemoryLimit > 55 ? 55 : 0; + writtenMessage.CompressedBytesWritten.Should().Be(ExpectedCompressedBytes); + var expectedCompressedBytesWrittenIntoMemory = testCase.AsyncMemoryLimit > ExpectedCompressedBytes ? ExpectedCompressedBytes : 0; writtenMessage.CompressedBytesWrittenIntoMemory.Should().Be(expectedCompressedBytesWrittenIntoMemory); messageSerializerObserver.MessagesRead.Should().BeEmpty(); } @@ -83,7 +90,7 @@ public async Task ReadMessage_ObservesThatMessageIsRead(MessageSerializerTestCas } var readMessage = messageSerializerObserver.MessagesRead.Should().ContainSingle().Subject; - readMessage.CompressedBytesRead.Should().Be(55); + readMessage.CompressedBytesRead.Should().Be(ExpectedCompressedBytes); readMessage.DecompressedBytesRead.Should().Be(120); var expectedDecompressedBytesReadIntoMemory = Math.Min(testCase.AsyncMemoryLimit, 120); readMessage.DecompressedBytesReadIntoMemory.Should().Be(expectedDecompressedBytesReadIntoMemory); @@ -210,7 +217,7 @@ public async Task ReadMessage_Rewindable_ObservesThatMessageIsRead(MessageSerial } var readMessage = messageSerializerObserver.MessagesRead.Should().ContainSingle().Subject; - readMessage.CompressedBytesRead.Should().Be(55); + readMessage.CompressedBytesRead.Should().Be(ExpectedCompressedBytes); readMessage.DecompressedBytesRead.Should().Be(120); var expectedDecompressedBytesReadIntoMemory = Math.Min(testCase.AsyncMemoryLimit, 120); readMessage.DecompressedBytesReadIntoMemory.Should().Be(expectedDecompressedBytesReadIntoMemory); @@ -272,7 +279,7 @@ public async Task ReadMessage_Rewindable_ShouldNotObserveTrailingDataWhenReading } var readMessage = messageSerializerObserver.MessagesRead.Should().ContainSingle().Subject; - readMessage.CompressedBytesRead.Should().Be(55); + readMessage.CompressedBytesRead.Should().Be(ExpectedCompressedBytes); readMessage.DecompressedBytesRead.Should().Be(120); var expectedDecompressedBytesReadIntoMemory = Math.Min(testCase.AsyncMemoryLimit, 120); readMessage.DecompressedBytesReadIntoMemory.Should().Be(expectedDecompressedBytesReadIntoMemory); diff --git a/source/Halibut.Tests/UsageFixture.cs b/source/Halibut.Tests/UsageFixture.cs index 4de3035a9..0be41209d 100644 --- a/source/Halibut.Tests/UsageFixture.cs +++ b/source/Halibut.Tests/UsageFixture.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using FluentAssertions; using Halibut.Exceptions; +using Halibut.Tests.Support; using Halibut.Tests.Support.TestAttributes; using Halibut.Tests.Support.TestCases; using Halibut.Tests.TestServices.Async; @@ -256,8 +257,8 @@ public async Task OctopusCanSendAndReceiveComplexObjects_WithMultipleComplexChil response.Child1.ChildPayload2.Should().NotBeSameAs(request.Child1.ChildPayload2); (await response.Child1.ChildPayload2!.ReadAsString(CancellationToken)).Should().Be(childPayload2); response.Child1.ListOfStreams.Should().NotBeSameAs(request.Child1.ListOfStreams); - (await response.Child1.ListOfStreams!.ToAsyncEnumerable() - .SelectAwait(async x => await x.ReadAsString(CancellationToken)) + (await response.Child1.ListOfStreams!.ToAsyncEnumerableCompat() + .SelectAwaitCompat(async x => await x.ReadAsString(CancellationToken)) .ToListAsync(CancellationToken)) .Should().BeEquivalentTo(list); response.Child1.DictionaryPayload.Should().NotBeSameAs(request.Child1.DictionaryPayload); @@ -266,8 +267,8 @@ public async Task OctopusCanSendAndReceiveComplexObjects_WithMultipleComplexChil response.Child2.Should().NotBeSameAs(request.Child2); response.Child2!.EnumPayload.Should().Be(enumValue); response.Child2.ComplexPayloadSet.Should().NotBeSameAs(request.Child2.ComplexPayloadSet); - (await response.Child2.ComplexPayloadSet!.ToAsyncEnumerable() - .SelectAwait(async x => new ComplexPair(x.EnumValue, await x.Payload.ReadAsString(CancellationToken))) + (await response.Child2.ComplexPayloadSet!.ToAsyncEnumerableCompat() + .SelectAwaitCompat(async x => new ComplexPair(x.EnumValue, await x.Payload.ReadAsString(CancellationToken))) .ToArrayAsync()) .ToHashSet() .Should() diff --git a/source/Halibut/Halibut.csproj b/source/Halibut/Halibut.csproj index 383684887..46b608079 100644 --- a/source/Halibut/Halibut.csproj +++ b/source/Halibut/Halibut.csproj @@ -19,10 +19,10 @@ enable - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 True @@ -32,18 +32,17 @@ - + - + - + - @@ -51,7 +50,7 @@ - + $(DefineConstants);LIBLOG_PORTABLE;HAS_TCP_KEEP_ALIVE_SOCKET_OPTIONS diff --git a/source/Halibut/Transport/ClientCertificateValidator.cs b/source/Halibut/Transport/ClientCertificateValidator.cs index ea37d453a..b5929268f 100644 --- a/source/Halibut/Transport/ClientCertificateValidator.cs +++ b/source/Halibut/Transport/ClientCertificateValidator.cs @@ -15,7 +15,9 @@ public ClientCertificateValidator(ServiceEndPoint endPoint) public bool Validate(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslpolicyerrors) { +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var providedCert = new X509Certificate2(certificate!.Export(X509ContentType.Cert), (string)null!); // Copy the cert so that we can reference it later +#pragma warning restore SYSLIB0057 var providedThumbprint = providedCert.Thumbprint; if (providedThumbprint == endPoint.RemoteThumbprint) diff --git a/source/Halibut/Transport/DiscoveryClient.cs b/source/Halibut/Transport/DiscoveryClient.cs index c92280702..cedaa5edb 100644 --- a/source/Halibut/Transport/DiscoveryClient.cs +++ b/source/Halibut/Transport/DiscoveryClient.cs @@ -61,7 +61,9 @@ await ssl.AuthenticateAsClientEnforcingTimeout( throw new Exception("The server did not provide an SSL certificate"); #pragma warning disable PC001 // API not supported on all platforms - X509Certificate2 not supported on macOS +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 return new ServiceEndPoint(serviceEndpoint.BaseUri, new X509Certificate2(ssl.RemoteCertificate.Export(X509ContentType.Cert), (string)null!).Thumbprint, halibutTimeoutsAndLimits); +#pragma warning restore SYSLIB0057 #pragma warning restore PC001 // API not supported on all platforms - X509Certificate2 not supported on macOS } } diff --git a/source/Halibut/Transport/SecureListener.cs b/source/Halibut/Transport/SecureListener.cs index a32c0ad64..40db01b3d 100644 --- a/source/Halibut/Transport/SecureListener.cs +++ b/source/Halibut/Transport/SecureListener.cs @@ -457,7 +457,9 @@ async Task SendFriendlyHtmlPage(Stream stream) return null; } +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var thumbprint = new X509Certificate2(stream.RemoteCertificate.Export(X509ContentType.Cert), (string)null!).Thumbprint; +#pragma warning restore SYSLIB0057 return thumbprint; } diff --git a/source/Halibut/Transport/SecureWebSocketListener.cs b/source/Halibut/Transport/SecureWebSocketListener.cs index 1807a469f..ec562fb26 100644 --- a/source/Halibut/Transport/SecureWebSocketListener.cs +++ b/source/Halibut/Transport/SecureWebSocketListener.cs @@ -233,7 +233,9 @@ async Task Authorize(HttpListenerContext context, string clientName) return false; } +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var thumbprint = new X509Certificate2(certificate.Export(X509ContentType.Cert), (string)null!).Thumbprint; +#pragma warning restore SYSLIB0057 var isAuthorized = verifyClientThumbprint(thumbprint); if (!isAuthorized) diff --git a/source/Halibut/Transport/ServerCertificateInterceptor.cs b/source/Halibut/Transport/ServerCertificateInterceptor.cs index 33b6b55b8..30b169a22 100644 --- a/source/Halibut/Transport/ServerCertificateInterceptor.cs +++ b/source/Halibut/Transport/ServerCertificateInterceptor.cs @@ -38,7 +38,9 @@ static void Initialize() { if (certificates.ContainsKey(clientId)) { +#pragma warning disable SYSLIB0057 // obsolete ctor; kept for identical behaviour on net48 and net10 var providedCert = new X509Certificate2(certificate.Export(X509ContentType.Cert), (string)null!); // Copy the cert so that we can reference it later +#pragma warning restore SYSLIB0057 certificates[clientId] = providedCert; return true; } diff --git a/source/Halibut/Transport/Streams/StreamFactory.cs b/source/Halibut/Transport/Streams/StreamFactory.cs index 1f941bc48..87f7719e4 100644 --- a/source/Halibut/Transport/Streams/StreamFactory.cs +++ b/source/Halibut/Transport/Streams/StreamFactory.cs @@ -15,7 +15,7 @@ public Stream CreateStream(TcpClient client) public Stream CreateStream(WebSocket webSocket) { - var webSocketStream = new WebSocketStream(webSocket); + var webSocketStream = new Halibut.Transport.Protocol.WebSocketStream(webSocket); var networkStream = new NetworkTimeoutStream(webSocketStream); // When synchronous serialization is performed, it will call the synchronous versions of Read/Write. diff --git a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj index 1dff29309..5f449ec16 100644 --- a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj +++ b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj @@ -8,10 +8,10 @@ - net48;net8.0 + net48;net10.0 - net8.0 + net10.0 From 096339c740af53c82129461cc10c9edefe80de37 Mon Sep 17 00:00:00 2001 From: Orion Edwards Date: Fri, 9 Oct 2026 14:37:20 +1300 Subject: [PATCH 2/5] Update test and build dependencies - Assent 1.8.2 -> 3.0.1 - CliWrap 3.8.2 -> 3.10.5 - FluentAssertions 7.0.0 -> 7.2.2 - Microsoft.Extensions.Configuration.EnvironmentVariables 7.0.0 -> 10.0.12 (Halibut.Tests), 6.0.1 -> 10.0.12 (Halibut.Tests.DotMemory) - Microsoft.Extensions.Hosting 7.0.1 -> 10.0.12 (Halibut.TestProxy) - Microsoft.Extensions.Hosting.Abstractions 7.0.0 -> 10.0.12 (Halibut.TestProxy) - Microsoft.NET.Test.Sdk 17.13.0 -> 18.10.1 - Microsoft.VisualStudio.Threading 17.13.61 -> 18.7.23 - NSubstitute 5.3.0 -> 6.2.0 - NUnit 3.13.3 -> 3.14.0 (5.0.0 backed off, breaks Assert.ThrowsAsync usage) - NUnit3TestAdapter 5.0.0 -> 5.2.0 (kept on 5.x to match NUnit 3) - Serilog 4.2.0 -> 4.4.0 - Serilog.Extensions.Logging 9.0.1 -> 10.0.0 - System.Diagnostics.PerformanceCounter 6.0.1 -> 10.0.12 - System.ValueTuple 4.6.1 -> 4.6.2 (Halibut.TestUtils.Contracts) - Testcontainers 4.0.0 -> 4.16.0 - Octopus.Shellfish 0.2.2426 -> 0.2.3062 (Halibut.Tests.DotMemory) Co-Authored-By: Claude Opus 5.5 --- .../Halibut.TestProxy.csproj | 4 +-- .../Halibut.TestUtils.Contracts.csproj | 2 +- .../Halibut.Tests.DotMemory.csproj | 20 +++++++------- source/Halibut.Tests/Halibut.Tests.csproj | 26 +++++++++---------- .../Redis/Utils/RedisContainerBuilder.cs | 5 ++-- .../Octopus.TestPortForwarder.csproj | 2 +- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/source/Halibut.TestProxy/Halibut.TestProxy.csproj b/source/Halibut.TestProxy/Halibut.TestProxy.csproj index d3ec080a1..bbeb24d81 100644 --- a/source/Halibut.TestProxy/Halibut.TestProxy.csproj +++ b/source/Halibut.TestProxy/Halibut.TestProxy.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj b/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj index 61eba0ece..e2cb6ba10 100644 --- a/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj +++ b/source/Halibut.TestUtils.Contracts/Halibut.TestUtils.Contracts.csproj @@ -18,7 +18,7 @@ all - + diff --git a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj index aea96d6d7..d23810e33 100644 --- a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj +++ b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj @@ -29,19 +29,19 @@ - - - - - - - + + + + + + + - + - + - + diff --git a/source/Halibut.Tests/Halibut.Tests.csproj b/source/Halibut.Tests/Halibut.Tests.csproj index 61c984f8e..4243e0dcc 100644 --- a/source/Halibut.Tests/Halibut.Tests.csproj +++ b/source/Halibut.Tests/Halibut.Tests.csproj @@ -34,23 +34,23 @@ - - - - - - - - - - + + + + + + + + + + - + - + - + diff --git a/source/Halibut.Tests/Queue/Redis/Utils/RedisContainerBuilder.cs b/source/Halibut.Tests/Queue/Redis/Utils/RedisContainerBuilder.cs index 510a64df7..07b6f0155 100644 --- a/source/Halibut.Tests/Queue/Redis/Utils/RedisContainerBuilder.cs +++ b/source/Halibut.Tests/Queue/Redis/Utils/RedisContainerBuilder.cs @@ -86,8 +86,7 @@ public RedisContainer Build() // permissions, so Redis (running as 1001) would fail to start if the checkout is not readable by other users. var redisConfigArguments = RedisConfigFileToArguments(Path.Combine(redisConfigPath, "redis.conf")); - var container = new ContainerBuilder() - .WithImage(_image) + var container = new ContainerBuilder(_image) .WithPortBinding(hostPort, 6379) // Start redis-server directly, the official image's entrypoint loads the Redis 8 modules (JSON, search etc.) which Octopus Cloud's image does not. .WithEntrypoint("redis-server") @@ -98,7 +97,7 @@ public RedisContainer Build() .WithCreateParameterModifier(parameters => { parameters.User = "1001:1001"; - parameters.HostConfig.ReadonlyRootfs = true; + parameters.HostConfig!.ReadonlyRootfs = true; parameters.HostConfig.CapDrop = new List { "ALL" }; parameters.HostConfig.SecurityOpt = new List { "no-new-privileges" }; }) diff --git a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj index 5f449ec16..f302e3471 100644 --- a/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj +++ b/source/Octopus.TestPortForwarder/Octopus.TestPortForwarder.csproj @@ -14,7 +14,7 @@ net10.0 - + From bbcf21acbeedeb831813e97dbf964ba128e753e7 Mon Sep 17 00:00:00 2001 From: Orion Edwards Date: Fri, 9 Oct 2026 14:48:43 +1300 Subject: [PATCH 3/5] Fix net48 restore failures and .NET 10-only CI issues - Assent 3.x only supports net8.0+, which broke net48 restore (NU1202). Pin to 1.9.3, the newest version with a net48-compatible build. - System.IO.Pipelines 6.0.3 is a downgrade on net48 now that Microsoft.Extensions.Hosting 10 / Testcontainers pull in newer versions (NU1605 as error). Bump to 10.0.12. - Remove the explicit SSH.NET reference; Testcontainers 4.16 already depends on SSH.NET 2026.0.0. - Upgrade Octopus.OctoVersion.Tool to 1.1.79 and run its net10.0 build. 0.3.400 only ships net8.0 with no roll-forward, so it fails on CI agents that only have the .NET 10 runtime. - ExceptionContractFixture: accept the modern .NET SslStream EOF message, which has no leading space (only .NET Framework's does). Co-Authored-By: Claude Opus 5.5 --- build/Build.cs | 2 +- build/_build.csproj | 2 +- source/Halibut.TestProxy/Halibut.TestProxy.csproj | 2 +- source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj | 2 +- source/Halibut.Tests/ExceptionContractFixture.cs | 2 ++ source/Halibut.Tests/Halibut.Tests.csproj | 3 +-- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index 67e76ce76..f2f5368db 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -34,7 +34,7 @@ class Build : NukeBuild [Parameter("Branch name for OctoVersion to use to calculate the version number. Can be set via the environment variable OCTOVERSION_CurrentBranch.", Name = "OCTOVERSION_CurrentBranch")] readonly string BranchName; - [OctoVersion(UpdateBuildNumber = true, BranchMember = nameof(BranchName), AutoDetectBranchMember = nameof(AutoDetectBranch), Framework = "net8.0")] + [OctoVersion(UpdateBuildNumber = true, BranchMember = nameof(BranchName), AutoDetectBranchMember = nameof(AutoDetectBranch), Framework = "net10.0")] readonly OctoVersionInfo OctoVersionInfo; [Parameter("The test Filter passed to dotnet test e.g. TestCategory=Async")] diff --git a/build/_build.csproj b/build/_build.csproj index f1850c939..1f3e86208 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -12,7 +12,7 @@ - + diff --git a/source/Halibut.TestProxy/Halibut.TestProxy.csproj b/source/Halibut.TestProxy/Halibut.TestProxy.csproj index bbeb24d81..442a2a8e6 100644 --- a/source/Halibut.TestProxy/Halibut.TestProxy.csproj +++ b/source/Halibut.TestProxy/Halibut.TestProxy.csproj @@ -17,7 +17,7 @@ - + diff --git a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj index d23810e33..f50f0a78c 100644 --- a/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj +++ b/source/Halibut.Tests.DotMemory/Halibut.Tests.DotMemory.csproj @@ -30,7 +30,7 @@ - + diff --git a/source/Halibut.Tests/ExceptionContractFixture.cs b/source/Halibut.Tests/ExceptionContractFixture.cs index eb1ae5bc0..a59f8d9c4 100644 --- a/source/Halibut.Tests/ExceptionContractFixture.cs +++ b/source/Halibut.Tests/ExceptionContractFixture.cs @@ -151,7 +151,9 @@ public async Task WhenTheListeningRequestFailsToBeSent_AsTheServiceRejectsTheCon .And.Message.Should().ContainAny( $"An error occurred when sending a request to '{clientAndService.ServiceUri}', before the request could begin: Unable to read data from the transport connection", $"An error occurred when sending a request to '{clientAndService.ServiceUri}', before the request could begin: Unable to write data to the transport connection", + // .NET Framework's SslStream message has a leading space; modern .NET's does not $"An error occurred when sending a request to '{clientAndService.ServiceUri}', before the request could begin: Received an unexpected EOF or 0 bytes from the transport stream", + $"An error occurred when sending a request to '{clientAndService.ServiceUri}', before the request could begin: Received an unexpected EOF or 0 bytes from the transport stream", $"An error occurred when sending a request to '{clientAndService.ServiceUri}', before the request could begin: Transport endpoint is not connected"); } diff --git a/source/Halibut.Tests/Halibut.Tests.csproj b/source/Halibut.Tests/Halibut.Tests.csproj index 4243e0dcc..526854c7d 100644 --- a/source/Halibut.Tests/Halibut.Tests.csproj +++ b/source/Halibut.Tests/Halibut.Tests.csproj @@ -36,7 +36,7 @@ - + @@ -51,7 +51,6 @@ - From 14b28c98305354070c5f4d811dfcdd5423bb3d73 Mon Sep 17 00:00:00 2001 From: Orion Edwards Date: Fri, 9 Oct 2026 15:05:17 +1300 Subject: [PATCH 4/5] Pin SDK 10.0.401 and patch vulnerable Nuke transitive dependencies - global.json SDK 10.0.100 -> 10.0.401 - NuGet.Packaging 6.12.1 -> 6.14.3 (GHSA-g4vj-cjjj-v7hg) - System.Security.Cryptography.Xml 9.0.0 -> 10.0.12 (GHSA-23rf-6693-g89p) Co-Authored-By: Claude Opus 5.5 --- build/_build.csproj | 2 ++ global.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build/_build.csproj b/build/_build.csproj index 1f3e86208..5af72320d 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -12,6 +12,8 @@ + + diff --git a/global.json b/global.json index 45f723296..99bfe4cad 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.100", + "version": "10.0.401", "rollForward": "latestFeature" } } From a0dc4a8ea26fccf449b53de1e23f8c4380a613d0 Mon Sep 17 00:00:00 2001 From: Luke Butters Date: Fri, 9 Oct 2026 13:17:16 +1100 Subject: [PATCH 5/5] Rename Nuke targets to drop framework versions (DotNet / NetFramework) --- .nuke/build.schema.json | 8 ++++---- build/Build.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index d716ee559..90081562c 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -26,8 +26,8 @@ "enum": [ "Clean", "Compile", - "CompileNet48", - "CompileNet80", + "CompileDotNet", + "CompileNetFramework", "CopyToLocalPackages", "Default", "Pack", @@ -35,8 +35,8 @@ "Restore", "TestLinux", "TestWindows", - "TestWindowsNet48", - "TestWindowsNet80" + "TestWindowsDotNet", + "TestWindowsNetFramework" ] }, "Verbosity": { diff --git a/build/Build.cs b/build/Build.cs index f2f5368db..dd0c3464f 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -78,9 +78,9 @@ class Build : NukeBuild Target Compile => _ => CompileDefinition(_, null); - Target CompileNet48 => _ => CompileDefinition(_, "net48"); + Target CompileNetFramework => _ => CompileDefinition(_, "net48"); - Target CompileNet80 => _ => CompileDefinition(_, "net10.0"); + Target CompileDotNet => _ => CompileDefinition(_, "net10.0"); ITargetDefinition CompileDefinition(ITargetDefinition targetDefinition, [CanBeNull] string framework) { @@ -105,10 +105,10 @@ ITargetDefinition CompileDefinition(ITargetDefinition targetDefinition, [CanBeNu Target TestLinux => _ => TestDefinition(_, Compile, null, runDotMemoryTests: false); [PublicAPI] - Target TestWindowsNet48 => _ => TestDefinition(_, CompileNet48, "net48", runDotMemoryTests: true); + Target TestWindowsNetFramework => _ => TestDefinition(_, CompileNetFramework, "net48", runDotMemoryTests: true); [PublicAPI] - Target TestWindowsNet80 => _ => TestDefinition(_, CompileNet80, "net10.0", runDotMemoryTests: false); + Target TestWindowsDotNet => _ => TestDefinition(_, CompileDotNet, "net10.0", runDotMemoryTests: false); ITargetDefinition TestDefinition(ITargetDefinition targetDefinition, Target dependsOn, [CanBeNull] string framework, bool runDotMemoryTests) {