Browse Source

CI: add Windows Integration Tests for .NET (#1704)

* CI: add Windows Integration Tests for .NET

see https://github.com/sshnet/SSH.NET/pull/1702#issuecomment-3342506642

* fix podman setup with Windows and .NET

* debug

* x

* x

* x

* revert

* Run Windows .NET tests in separate job

so they run in parallel and we avoid the Common_CreateMoreChannelsThanMaxSessions test failure.

* fix coverlet artifacts

* fix missing PermitTTY in RemoteSshdConfig Reset

this fixes a test failure in Common_CreateMoreChannelsThanMaxSessions
when running the tests multiple times against the same SSH server
instance.

see https://github.com/sshnet/SSH.NET/pull/1704#issuecomment-3343210311

* speed up Windows tests

turns out this is caused by DNS resolution taking about
2 seconds on every new connection...

* add windows integration tests to Publish needs:

---------

Co-authored-by: Rob Hague <rob.hague00@gmail.com>
Co-authored-by: Robert Hague <rh@johnstreetcapital.com>
mus65 3 weeks ago
parent
commit
ebdcb3ea7d

+ 50 - 6
.github/workflows/build.yml

@@ -15,7 +15,7 @@ jobs:
         fetch-depth: 0 # needed for Nerdbank.GitVersioning
 
     - name: Setup .NET
-      uses: actions/setup-dotnet@v4
+      uses: actions/setup-dotnet@v5
 
     - name: Build Unit Tests .NET
       run: dotnet build -f net9.0 test/Renci.SshNet.Tests/
@@ -62,7 +62,7 @@ jobs:
         fetch-depth: 0 # needed for Nerdbank.GitVersioning
 
     - name: Setup .NET
-      uses: actions/setup-dotnet@v4
+      uses: actions/setup-dotnet@v5
 
     - name: Build Solution
       run: dotnet build Renci.SshNet.sln
@@ -103,8 +103,8 @@ jobs:
           -p:CoverletOutput=../../coverlet/windows_unit_test_net_4_6_2_coverage.xml `
           test/Renci.SshNet.Tests/
 
-  Windows-Integration-Tests:
-    name: Windows Integration Tests
+  Windows-Integration-Tests-NetFramework:
+    name: Windows Integration Tests .NET Framework
     runs-on: windows-2025
     steps:
     - name: Checkout
@@ -113,7 +113,7 @@ jobs:
         fetch-depth: 0 # needed for Nerdbank.GitVersioning
 
     - name: Setup .NET
-      uses: actions/setup-dotnet@v4
+      uses: actions/setup-dotnet@v5
 
     - name: Setup WSL2
       uses: Vampire/setup-wsl@6a8db447be7ed35f2f499c02c6e60ff77ef11278 # v6.0.0
@@ -142,7 +142,49 @@ jobs:
     - name: Archive Coverlet Results
       uses: actions/upload-artifact@v4
       with:
-        name: Coverlet Results Windows
+        name: Coverlet Results Windows .NET Framework
+        path: coverlet
+
+  Windows-Integration-Tests-Net:
+    name: Windows Integration Tests .NET
+    runs-on: windows-2025
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v5
+      with:
+        fetch-depth: 0 # needed for Nerdbank.GitVersioning
+
+    - name: Setup .NET
+      uses: actions/setup-dotnet@v5
+
+    - name: Setup WSL2
+      uses: Vampire/setup-wsl@6a8db447be7ed35f2f499c02c6e60ff77ef11278 # v6.0.0
+      with:
+        distribution: Ubuntu-24.04
+
+    - name: Setup SSH Server
+      shell: wsl-bash {0}
+      run: |
+        apt-get update && apt-get upgrade -y
+        apt-get install -y podman
+        podman build -t renci-ssh-tests-server-image -f test/Renci.SshNet.IntegrationTests/Dockerfile test/Renci.SshNet.IntegrationTests/
+        podman run --rm -h renci-ssh-tests-server -d -p 2222:22 renci-ssh-tests-server-image
+
+    - name: Run Integration Tests .NET
+      run:
+        dotnet test `
+          -f net9.0 `
+          --logger "console;verbosity=normal" `
+          --logger GitHubActions `
+          -p:CollectCoverage=true `
+          -p:CoverletOutputFormat=cobertura `
+          -p:CoverletOutput=..\..\coverlet\windows_integration_test_net_9_coverage.xml `
+          test\Renci.SshNet.IntegrationTests\
+
+    - name: Archive Coverlet Results
+      uses: actions/upload-artifact@v4
+      with:
+        name: Coverlet Results Windows .NET
         path: coverlet
 
   Publish:
@@ -153,6 +195,8 @@ jobs:
     needs:
       - Windows
       - Linux
+      - Windows-Integration-Tests-NetFramework
+      - Windows-Integration-Tests-Net
     steps:
       - name: Download NuGet Package
         uses: actions/download-artifact@v5

+ 1 - 1
.github/workflows/docs.yml

@@ -28,7 +28,7 @@ jobs:
         uses: actions/configure-pages@v5
 
       - name: Setup .NET
-        uses: actions/setup-dotnet@v4
+        uses: actions/setup-dotnet@v5
 
       - name: Setup docfx
         run: dotnet tool update -g docfx

+ 1 - 0
test/Renci.SshNet.IntegrationTests/Common/RemoteSshdConfigExtensions.cs

@@ -23,6 +23,7 @@ namespace Renci.SshNet.IntegrationTests.Common
                             .ClearHostKeyAlgorithms()
                             .ClearPublicKeyAcceptedAlgorithms()
                             .ClearMessageAuthenticationCodeAlgorithms()
+                            .PermitTTY(true)
                             .WithUsePAM(true)
                             .Update()
                             .Restart();

+ 13 - 10
test/Renci.SshNet.IntegrationTests/TestsFixtures/InfrastructureFixture.cs

@@ -1,4 +1,6 @@
-using DotNet.Testcontainers.Builders;
+using System.Runtime.InteropServices;
+
+using DotNet.Testcontainers.Builders;
 using DotNet.Testcontainers.Containers;
 using DotNet.Testcontainers.Images;
 
@@ -28,26 +30,27 @@ namespace Renci.SshNet.IntegrationTests.TestsFixtures
 
         private IFutureDockerImage _sshServerImage;
 
-        public string SshServerHostName { get; set; }
+        public string SshServerHostName { get; private set; }
 
-        public ushort SshServerPort { get; set; }
+        public ushort SshServerPort { get; private set; }
 
-        public SshUser AdminUser = new SshUser("sshnetadm", "ssh4ever");
+        public SshUser AdminUser { get; } = new SshUser("sshnetadm", "ssh4ever");
 
-        public SshUser User = new SshUser("sshnet", "ssh4ever");
+        public SshUser User { get; } = new SshUser("sshnet", "ssh4ever");
 
         public async Task InitializeAsync()
         {
-            // for the .NET Framework Tests in CI, the Container is set up in WSL2 with Podman
-#if NETFRAMEWORK
-            if (Environment.GetEnvironmentVariable("CI") == "true")
+#pragma warning disable MA0144 // use System.OperatingSystem to check the current OS
+            // for the Windows Tests in CI, the Container is set up in WSL2 with Podman
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
+                Environment.GetEnvironmentVariable("CI") == "true")
+#pragma warning restore MA0144 // use System.OperatingSystem to check the current OS
             {
                 SshServerPort = 2222;
-                SshServerHostName = "localhost";
+                SshServerHostName = "127.0.0.1";
                 await Task.Delay(1_000);
                 return;
             }
-#endif
 
             var containerLogger = _loggerFactory.CreateLogger("testcontainers");