Skip to content

Commit f65ca44

Browse files
authored
Migrate from AppVeyor to GitHub Actions (#1539)
* Migrate from AppVeyor to GitHub Actions * also run on pull_request * small formatting improvements * add on: workflow_dispatch this is needed to re-run jobs manually from the web UI * Publish NuGet package to GitHub Registry only on develop branch. * re-add empty appveyor.yml so it doesn't fail CI until AppVeyor integration is disabled * fix appveyor * typo
1 parent 3ec45e1 commit f65ca44

File tree

10 files changed

+208
-75
lines changed

10 files changed

+208
-75
lines changed

.github/workflows/build.yml

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
name: Build
2+
3+
on:
4+
- push
5+
- pull_request
6+
- workflow_dispatch
7+
8+
jobs:
9+
Linux:
10+
runs-on: ubuntu-24.04
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
with:
15+
fetch-depth: 0 # needed for Nerdbank.GitVersioning
16+
17+
- name: Setup .NET
18+
uses: actions/setup-dotnet@v4
19+
with:
20+
dotnet-version: 8.0.x
21+
22+
- name: Build Unit Tests .NET
23+
run: dotnet build -f net8.0 test/Renci.SshNet.Tests/
24+
25+
- name: Build IntegrationTests .NET
26+
run: dotnet build -f net8.0 test/Renci.SshNet.IntegrationTests/
27+
28+
- name: Build IntegrationTests .NET Framework
29+
run: dotnet build -f net48 test/Renci.SshNet.IntegrationTests/
30+
31+
- name: Run Unit Tests .NET
32+
run: |
33+
dotnet test \
34+
-f net8.0 \
35+
--no-build \
36+
--logger "console;verbosity=normal" \
37+
--logger GitHubActions \
38+
-p:CollectCoverage=true \
39+
-p:CoverletOutputFormat=cobertura \
40+
-p:CoverletOutput=../../coverlet/linux_unit_test_net_8_coverage.xml \
41+
test/Renci.SshNet.Tests/
42+
43+
- name: Run Integration Tests .NET
44+
run: |
45+
dotnet test \
46+
-f net8.0 \
47+
--no-build \
48+
--logger "console;verbosity=normal" \
49+
--logger GitHubActions \
50+
-p:CollectCoverage=true \
51+
-p:CoverletOutputFormat=cobertura \
52+
-p:CoverletOutput=../../coverlet/linux_integration_test_net_8_coverage.xml \
53+
test/Renci.SshNet.IntegrationTests/
54+
55+
# Also run a subset of the integration tests targeting netfx using mono. This is a temporary measure to get
56+
# some coverage until a proper solution for running the .NET Framework integration tests in CI is found.
57+
# Running all the tests causes problems which are not worth solving in this rare configuration.
58+
# See https://github.com/sshnet/SSH.NET/pull/1462 and related links
59+
- name: Run Integration Tests Mono
60+
run: |
61+
sudo apt-get install ca-certificates gnupg
62+
sudo gpg --homedir /tmp --no-default-keyring --keyring /usr/share/keyrings/mono-official-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
63+
echo "deb [signed-by=/usr/share/keyrings/mono-official-archive-keyring.gpg] https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
64+
sudo apt-get update
65+
sudo apt-get install mono-devel
66+
dotnet test \
67+
-f net48 \
68+
--no-build \
69+
--logger "console;verbosity=normal" \
70+
--logger GitHubActions \
71+
-p:CollectCoverage=true \
72+
-p:CoverletOutputFormat=cobertura \
73+
-p:CoverletOutput=../../coverlet/linux_integration_test_net_48_coverage.xml \
74+
--filter "Name~Ecdh|Name~ECDsa|Name~Zlib|Name~Gcm" \
75+
test/Renci.SshNet.IntegrationTests/
76+
77+
- name: Archive Coverlet Results
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: Coverlet Results Linux
81+
path: coverlet
82+
83+
Windows:
84+
runs-on: windows-2022
85+
steps:
86+
- name: Checkout
87+
uses: actions/checkout@v4
88+
with:
89+
fetch-depth: 0 # needed for Nerdbank.GitVersioning
90+
91+
- name: Setup .NET
92+
uses: actions/setup-dotnet@v4
93+
with:
94+
dotnet-version: 9.0.x
95+
96+
- name: Build Solution
97+
run: dotnet build Renci.SshNet.sln
98+
99+
- name: Publish AOT Compatibility Test App
100+
run: dotnet publish -r win-x64 /warnaserror test/Renci.SshNet.AotCompatibilityTestApp/
101+
102+
- name: Create NuGet Package
103+
run: dotnet pack
104+
105+
- name: Archive NuGet Package
106+
uses: actions/upload-artifact@v4
107+
with:
108+
name: NuGet Package
109+
path: src/Renci.SshNet/bin/Release/*.*nupkg
110+
111+
- name: Run Unit Tests .NET
112+
run: |
113+
dotnet test `
114+
-f net8.0 `
115+
--no-build `
116+
--logger "console;verbosity=normal" `
117+
--logger GitHubActions `
118+
-p:CollectCoverage=true `
119+
-p:CoverletOutputFormat=cobertura `
120+
-p:CoverletOutput=../../coverlet/windows_unit_test_net_8_coverage.xml `
121+
test/Renci.SshNet.Tests/
122+
123+
- name: Run Unit Tests .NET Framework
124+
run: |
125+
dotnet test `
126+
-f net462 `
127+
--no-build `
128+
--logger "console;verbosity=normal" `
129+
--logger GitHubActions `
130+
-p:CollectCoverage=true `
131+
-p:CoverletOutputFormat=cobertura `
132+
-p:CoverletOutput=../../coverlet/windows_unit_test_net_4_6_2_coverage.xml `
133+
test/Renci.SshNet.Tests/
134+
135+
- name: Archive Coverlet Results
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: Coverlet Results Windows
139+
path: coverlet
140+
141+
Publish:
142+
runs-on: ubuntu-24.04
143+
if: github.ref == 'refs/heads/develop'
144+
permissions:
145+
packages: write
146+
needs:
147+
- Windows
148+
- Linux
149+
steps:
150+
- name: Download NuGet Package
151+
uses: actions/download-artifact@v4
152+
with:
153+
name: NuGet Package
154+
155+
- name: Publish to GitHub NuGet Registry
156+
run: |
157+
dotnet nuget add source \
158+
--username $GITHUB_ACTOR \
159+
--password ${{ secrets.GITHUB_TOKEN }} \
160+
--store-password-in-clear-text \
161+
--name github \
162+
"https://nuget.pkg.github.com/$GITHUB_REPOSITORY_OWNER/index.json"
163+
dotnet nuget push "*.nupkg" \
164+
--source github \
165+
--api-key ${{ secrets.GITHUB_TOKEN }}

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Before subsequent coverage collections, delete the previous collections with `gi
3030

3131
## CI
3232

33-
The repository makes use of continuous integration (CI) on [AppVeyor](https://ci.appveyor.com/project/drieseng/ssh-net/history) to validate builds and tests on PR branches and non-PR branches. At the time of writing, some tests can occasionally fail in CI due to a dependency on timing or a dependency on networking/socket code. If you see an existing test which is unrelated to your changes occasionally failing in CI but passing locally, you probably don't need to worry about it. If you see one of your newly-added tests failing, it is probably worth investigating why and whether it can be made more stable.
33+
The repository makes use of continuous integration (CI) with GitHub Actions to validate builds and tests on PR branches and non-PR branches. At the time of writing, some tests can occasionally fail in CI due to a dependency on timing or a dependency on networking/socket code. If you see an existing test which is unrelated to your changes occasionally failing in CI but passing locally, you probably don't need to worry about it. If you see one of your newly-added tests failing, it is probably worth investigating why and whether it can be made more stable.
3434

3535
## Good to know
3636

Directory.Packages.props

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
55
</PropertyGroup>
66
<ItemGroup>
7-
<PackageVersion Include="Appveyor.TestLogger" Version="2.0.0" />
87
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
98
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.4.0" />
109
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
1110
<PackageVersion Include="coverlet.msbuild" Version="6.0.2" />
12-
<PackageVersion Include="LiquidTestReports.Markdown" Version="1.0.9" />
11+
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1">
12+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13+
<PrivateAssets>all</PrivateAssets>
14+
</PackageVersion>
1315
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.163" />
1416
<!-- Must be kept at version 1.0.0 or higher, see https://github.com/sshnet/SSH.NET/pull/1288 for details. -->
1517
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ SSH.NET is a Secure Shell (SSH-2) library for .NET, optimized for parallelism.
44

55
[![Version](https://img.shields.io/nuget/vpre/SSH.NET.svg)](https://www.nuget.org/packages/SSH.NET)
66
[![NuGet download count](https://img.shields.io/nuget/dt/SSH.NET.svg)](https://www.nuget.org/packages/SSH.NET)
7-
[![Build status](https://ci.appveyor.com/api/projects/status/ih77qu6tap3o92gu/branch/develop?svg=true)](https://ci.appveyor.com/api/projects/status/ih77qu6tap3o92gu/branch/develop)
7+
![Build status](https://github.com/sshnet/SSH.NET/actions/workflows/build.yml/badge.svg)
88

99
## Key Features
1010

@@ -177,6 +177,19 @@ Private keys in OpenSSH key format can be encrypted using one of the following c
177177

178178
The library has no special requirements to build, other than an up-to-date .NET SDK. See also [CONTRIBUTING.md](https://github.com/sshnet/SSH.NET/blob/develop/CONTRIBUTING.md).
179179

180+
## Using Pre-Release NuGet Package
181+
182+
If you need an unreleased bugfix or feature, you can use the Pre-Release NuGet packages from the `develop` branch which are published to the [GitHub NuGet Registry](https://github.com/sshnet/SSH.NET/pkgs/nuget/SSH.NET).
183+
In order to pull packages from the registry you first have to create a Personal Access Token with the `read:packages` permissions. Then add a NuGet Source for SSH.NET:
184+
185+
Note: you may have to add `--store-password-in-clear-text` on non-Windows platforms.
186+
187+
```
188+
dotnet nuget add source --name SSH.NET --username <username> --password <personalaccesstoken> https://nuget.pkg.github.com/sshnet/index.json
189+
```
190+
191+
Then you can add the the package as described [here](https://github.com/sshnet/SSH.NET/pkgs/nuget/SSH.NET).
192+
180193
## Supporting SSH.NET
181194

182195
Do you or your company rely on **SSH.NET** in your projects? If you want to encourage us to keep on going and show us that you appreciate our work, please consider becoming a [sponsor](https://github.com/sponsors/sshnet) through GitHub Sponsors.

Renci.SshNet.sln

+10-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1010
.editorconfig = .editorconfig
1111
.gitattributes = .gitattributes
1212
.gitignore = .gitignore
13-
appveyor.yml = appveyor.yml
1413
CODEOWNERS = CODEOWNERS
1514
CONTRIBUTING.md = CONTRIBUTING.md
1615
Directory.Build.props = Directory.Build.props
@@ -83,6 +82,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet.IntegrationBen
8382
EndProject
8483
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet.AotCompatibilityTestApp", "test\Renci.SshNet.AotCompatibilityTestApp\Renci.SshNet.AotCompatibilityTestApp.csproj", "{F2E3FC50-4EF4-488C-B3D2-C45E99898D8B}"
8584
EndProject
85+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{05229079-6738-42CE-8F73-F4E182929B03}"
86+
EndProject
87+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{95F25B1A-2B14-4745-9087-43C00CD90EE0}"
88+
ProjectSection(SolutionItems) = preProject
89+
.github\workflows\build.yml = .github\workflows\build.yml
90+
.github\workflows\docs.yml = .github\workflows\docs.yml
91+
EndProjectSection
92+
EndProject
8693
Global
8794
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8895
Debug|Any CPU = Debug|Any CPU
@@ -244,6 +251,8 @@ Global
244251
{19895BAF-F946-470D-8497-7034F9F2A8A7} = {1E46D4B6-EE87-4D29-8641-0AE8CD8ED0F0}
245252
{3572019A-3A57-4578-B5A2-6280576EB508} = {1E46D4B6-EE87-4D29-8641-0AE8CD8ED0F0}
246253
{92E7B1B8-4C70-4138-9970-433B2FC2E3EB} = {1E46D4B6-EE87-4D29-8641-0AE8CD8ED0F0}
254+
{05229079-6738-42CE-8F73-F4E182929B03} = {04E8CC26-116E-4116-9558-7ED542548E70}
255+
{95F25B1A-2B14-4745-9087-43C00CD90EE0} = {05229079-6738-42CE-8F73-F4E182929B03}
247256
EndGlobalSection
248257
GlobalSection(ExtensibilityGlobals) = postSolution
249258
SolutionGuid = {BAD6019D-4AF7-4E15-99A0-8036E16FC0E5}

appveyor.yml

+4-64
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,5 @@
1-
image:
2-
- Ubuntu2204
3-
- Visual Studio 2022
1+
# empty to avoid AppVeyor errors until it's disabled
2+
image: Ubuntu2204
43

5-
services:
6-
- docker
7-
8-
for:
9-
-
10-
matrix:
11-
only:
12-
- image: Ubuntu2204
13-
14-
init:
15-
- git config --global core.autocrlf input
16-
17-
before_build:
18-
- sh: mkdir artifacts -p
19-
20-
build_script:
21-
- echo build
22-
- dotnet build -f net8.0 -c Debug test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
23-
- dotnet build -f net8.0 -c Debug test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
24-
- dotnet build -f net48 -c Debug test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
25-
26-
test_script:
27-
- sh: echo "Run unit tests"
28-
- sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_unit_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_unit_test_net_8_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
29-
- sh: echo "Run integration tests"
30-
- sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_8_coverage.xml test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
31-
# Also run a subset of the integration tests targeting netfx using mono. This is a temporary measure to get
32-
# some coverage until a proper solution for running the .NET Framework integration tests in CI is found.
33-
# Running all the tests causes problems which are not worth solving in this rare configuration.
34-
# See https://github.com/sshnet/SSH.NET/pull/1462 and related links
35-
- sh: dotnet test -f net48 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_48_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_48_coverage.xml --filter "Name~Ecdh|Name~ECDsa|Name~Zlib|Name~Gcm" test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
36-
37-
-
38-
matrix:
39-
only:
40-
- image: Visual Studio 2022
41-
42-
init:
43-
- git config --global core.autocrlf true
44-
45-
before_build:
46-
- ps: mkdir artifacts -f
47-
48-
build_script:
49-
- echo build
50-
- dotnet build Renci.SshNet.sln -c Debug
51-
- dotnet publish -c Release -r win-x64 /warnaserror .\test\Renci.SshNet.AotCompatibilityTestApp\
52-
- dotnet pack -c Release
53-
54-
test_script:
55-
- ps: echo "Run unit tests for .NET 8.0"
56-
- ps: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=windows_unit_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/windows_unit_test_net_8_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
57-
- ps: echo "Run unit tests for .NET Framework 4.6.2"
58-
- ps: dotnet test -f net462 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=windows_unit_test_net_4_6_2_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/windows_unit_test_net_4_6_2_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
59-
60-
artifacts:
61-
- path: artifacts
62-
name: TestResults
63-
64-
- path: src/**/*.nupkg
65-
- path: src/**/*.snupkg
4+
build_script:
5+
- echo done

test/Renci.SshNet.AotCompatibilityTestApp/Renci.SshNet.AotCompatibilityTestApp.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0</TargetFramework>
5+
<TargetFramework>net9.0</TargetFramework>
66
<PublishAot>true</PublishAot>
77
<SelfContained>true</SelfContained>
88
<TrimmerSingleWarn>false</TrimmerSingleWarn>

test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414

1515
<ItemGroup>
1616
<PackageReference Include="BouncyCastle.Cryptography" />
17+
<PackageReference Include="GitHubActionsTestLogger">
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
<PrivateAssets>all</PrivateAssets>
20+
</PackageReference>
1721
<PackageReference Include="Microsoft.NET.Test.Sdk" />
1822
<PackageReference Include="MSTest.TestAdapter" />
1923
<PackageReference Include="MSTest.TestFramework" />
2024
<PackageReference Include="Testcontainers" />
21-
<PackageReference Include="Appveyor.TestLogger" />
22-
<PackageReference Include="LiquidTestReports.Markdown" />
2325
<PackageReference Include="coverlet.msbuild">
2426
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2527
<PrivateAssets>all</PrivateAssets>

test/Renci.SshNet.Tests/Common/AsyncSocketListener.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ void ConnectionDisconnected()
324324
}
325325
catch (ObjectDisposedException)
326326
{
327-
// TODO On .NET 7, sometimes we get ObjectDisposedException when _started but only on appveyor, locally it works
327+
// TODO On .NET 7, sometimes we get ObjectDisposedException when _started but only in CI, locally it works
328328
ConnectionDisconnected();
329329
}
330330
catch (SocketException ex)

test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
</ItemGroup>
1010

1111
<ItemGroup>
12+
<PackageReference Include="GitHubActionsTestLogger">
13+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
14+
<PrivateAssets>all</PrivateAssets>
15+
</PackageReference>
1216
<PackageReference Include="Microsoft.NET.Test.Sdk" />
1317
<PackageReference Include="MSTest.TestAdapter" />
1418
<PackageReference Include="MSTest.TestFramework" />
1519
<PackageReference Include="Moq" />
16-
<PackageReference Include="Appveyor.TestLogger" />
17-
<PackageReference Include="LiquidTestReports.Markdown" />
1820
<PackageReference Include="coverlet.msbuild">
1921
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2022
<PrivateAssets>all</PrivateAssets>

0 commit comments

Comments
 (0)