From dbf90c6888ec1aadc2037350cb626e8c3758b61c Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 11 Nov 2026 07:57:54 +0100 Subject: [PATCH] New SonarCloud project (#1534) * SonarCloud test * xxx * WebSocketIntegrationTests * move sonar to github * SonarCloud now runs for every Linux workflow event. The begin step supplies pull-request key/branch/base metadata for PRs and branch metadata for pushes; the end step is no longer gated. Workflow YAML parsing and the solution build both pass. * SHA --- .github/workflows/CreateRelease.yml | 4 +- .github/workflows/PublishToNuGet.yml | 2 +- .github/workflows/ci.yml | 84 ++++++++++++++++--- README.md | 6 +- azure-pipelines-ci.yml | 5 +- src/WireMock.Net.StandAlone/StandAloneApp.cs | 2 - .../WebSockets/WebSocketIntegrationTests.cs | 36 ++++---- 7 files changed, 97 insertions(+), 42 deletions(-) diff --git a/.github/workflows/CreateRelease.yml b/.github/workflows/CreateRelease.yml index f1f18b9b..c2b216e7 100644 --- a/.github/workflows/CreateRelease.yml +++ b/.github/workflows/CreateRelease.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Setup .NET 8 and 10 - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5 with: dotnet-version: | 8.0.x diff --git a/.github/workflows/PublishToNuGet.yml b/.github/workflows/PublishToNuGet.yml index 49bdc6f7..f95f205e 100644 --- a/.github/workflows/PublishToNuGet.yml +++ b/.github/workflows/PublishToNuGet.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Build projects shell: pwsh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9062665f..c622d37f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,10 @@ jobs: IsRunningOnGitHubActions: 'true' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Setup .NET 8 and 10 - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5 with: dotnet-version: | 8.0.x @@ -58,26 +58,72 @@ jobs: IsRunningOnGitHubActions: 'true' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Setup .NET 8 and 10 - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5 with: dotnet-version: | 8.0.x 10.0.x + - name: Setup Java 17 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 + with: + distribution: temurin + java-version: '17' + + - name: Install .NET coverage and SonarScanner tools + run: | + dotnet tool install --global dotnet-sonarscanner + dotnet tool install --global dotnet-coverage + echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH" + + - name: Begin analysis on SonarCloud + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_BRANCH: ${{ github.head_ref }} + PR_BASE: ${{ github.base_ref }} + run: | + sonar_args=( + /k:"wiremock_WireMock.Net" + /o:"wiremock" + /d:sonar.host.url="https://sonarcloud.io" + /d:sonar.token="$SONAR_TOKEN" + /d:sonar.cs.vscoveragexml.reportsPaths="**/wiremock-coverage-*.xml" + /d:sonar.verbose=true + ) + if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then + sonar_args+=( + /d:sonar.pullrequest.provider=github + /d:sonar.pullrequest.key="$PR_NUMBER" + /d:sonar.pullrequest.branch="$PR_BRANCH" + /d:sonar.pullrequest.base="$PR_BASE" + ) + else + sonar_args+=(/d:sonar.branch.name="$GITHUB_REF_NAME") + fi + dotnet sonarscanner begin "${sonar_args[@]}" + + - name: Build test projects for coverage + run: | + dotnet build ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Release --framework net10.0 + dotnet build ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Release --framework net10.0 + dotnet build ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Release --framework net10.0 + dotnet build ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Release --framework net10.0 + # - name: 'WireMock.Net.TUnitTests (net8.0)' # run: dotnet test --project './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0 - - name: 'WireMock.Net.TUnitTests (net10.0)' - run: dotnet test --project './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net10.0 + - name: 'WireMock.Net.TUnitTests (net10.0) with coverage' + run: dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Release --no-build --framework net10.0" -f xml -o "wiremock-coverage-tunit.xml" # - name: 'WireMock.Net.Tests (net8.0)' # run: dotnet test --project './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 - - name: 'WireMock.Net.Tests (net10.0)' - run: dotnet test --project './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net10.0 + - name: 'WireMock.Net.Tests (net10.0) with coverage' + run: dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Release --no-build --framework net10.0" -f xml -o "wiremock-coverage-xunit.xml" - name: 'WireMock.Net.Tests.UsingNuGet (net8.0)' run: dotnet test --project './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release --framework net8.0 @@ -88,14 +134,28 @@ jobs: # - name: 'WireMock.Net.Middleware.Tests (net8.0)' # run: dotnet test --project './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0 - - name: 'WireMock.Net.Middleware.Tests (net10.0)' - run: dotnet test --project './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net10.0 + - name: 'WireMock.Net.Middleware.Tests (net10.0) with coverage' + run: dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Release --no-build --framework net10.0" -f xml -o "wiremock-coverage-middleware.xml" # - name: 'WireMock.Net.Aspire.Tests (net8.0)' # run: dotnet test --project './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release --framework net8.0 - - name: 'WireMock.Net.Aspire.Tests (net10.0)' - run: dotnet test --project './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release --framework net10.0 + - name: 'WireMock.Net.Aspire.Tests (net10.0) with coverage' + run: dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Release --no-build --framework net10.0" -f xml -o "wiremock-coverage-aspire.xml" + + - name: Merge coverage files + run: dotnet coverage merge **/wiremock-coverage-*.xml --output ./test/wiremock-coverage.xml --output-format xml + + - name: End analysis on SonarCloud + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: dotnet sonarscanner end /d:sonar.token="$SONAR_TOKEN" + + - name: Upload coverage results to Codecov + uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5.5.5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./test/wiremock-coverage.xml - name: 'dotnet-WireMock stops on CTRL-C' run: | diff --git a/README.md b/README.md index 2fc2f2de..82960d7c 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,9 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w | ***Quality*** |   | |   **Build Azure** | [![Build Status Azure](https://stef.visualstudio.com/WireMock.Net/_apis/build/status/WireMock.Net)](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=61) | |   **Build GitHub** | [![Run Tests](https://github.com/wiremock/WireMock.Net/actions/workflows/ci.yml/badge.svg)](https://github.com/wiremock/WireMock.Net/actions/workflows/ci.yml) -|   **Quality** | [![Sonar Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=alert_status)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [![CodeFactor](https://www.codefactor.io/repository/github/wiremock/wiremock.net/badge)](https://www.codefactor.io/repository/github/wiremock/wiremock.net) | -|   **SonarQube** | [![Sonar Bugs](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=bugs)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [![Sonar Code Smells](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=code_smells)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) | -|   **Coverage** | [![Sonar Coverage](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=coverage)](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [![codecov](https://codecov.io/gh/wiremock/WireMock.Net/branch/master/graph/badge.svg)](https://codecov.io/gh/wiremock/WireMock.Net)| +|   **Quality** | [![Sonar Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=wiremock_WireMock.Net&metric=alert_status)](https://sonarcloud.io/project/issues?id=wiremock_WireMock.Net) [![CodeFactor](https://www.codefactor.io/repository/github/wiremock/wiremock.net/badge)](https://www.codefactor.io/repository/github/wiremock/wiremock.net) | +|   **SonarQube** | [![Sonar Bugs](https://sonarcloud.io/api/project_badges/measure?project=wiremock_WireMock.Net&metric=bugs)](https://sonarcloud.io/project/issues?id=wiremock_WireMock.Net&resolved=false&types=BUG) [![Sonar Code Smells](https://sonarcloud.io/api/project_badges/measure?project=wiremock_WireMock.Net&metric=code_smells)](https://sonarcloud.io/project/issues?id=wiremock_WireMock.Net&resolved=false&types=CODE_SMELL) | +|   **Coverage** | [![Sonar Coverage](https://sonarcloud.io/api/project_badges/measure?project=wiremock_WireMock.Net&metric=coverage)](https://sonarcloud.io/component_measures?id=wiremock_WireMock.Net&metric=coverage) [![codecov](https://codecov.io/gh/wiremock/WireMock.Net/branch/master/graph/badge.svg)](https://codecov.io/gh/wiremock/WireMock.Net)| |   **TIOBE** | [TIOBE Quality Indicator](https://ticsdemo.tiobe.com/tiobeweb/DEMO/TqiDashboard.html#axes=Project(WireMock.Net),Sub()&metric=tqi) ### :package: NuGet packages diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml index 395500b4..8e3a0f49 100644 --- a/azure-pipelines-ci.yml +++ b/azure-pipelines-ci.yml @@ -1,3 +1,6 @@ +trigger: none +pr: none + parameters: - name: runWindowsReleaseToMyGet displayName: Run Windows Release to MyGet @@ -45,7 +48,7 @@ jobs: # See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage - script: | - dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true + dotnet sonarscanner begin /k:"wiremock_WireMock.Net" /o:"wiremock" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true displayName: 'Begin analysis on SonarCloud' condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests diff --git a/src/WireMock.Net.StandAlone/StandAloneApp.cs b/src/WireMock.Net.StandAlone/StandAloneApp.cs index a17d0b11..09481ad8 100644 --- a/src/WireMock.Net.StandAlone/StandAloneApp.cs +++ b/src/WireMock.Net.StandAlone/StandAloneApp.cs @@ -1,8 +1,6 @@ // Copyright © WireMock.Net -using System; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Reflection; using JetBrains.Annotations; using Stef.Validation; diff --git a/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs b/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs index 924c9f89..90be4515 100644 --- a/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs +++ b/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs @@ -16,7 +16,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc private readonly CancellationToken _ct = testContext.Current.CancellationToken; [Fact] - public async Task WithNoSetupShouldJustWaitForClose_AndCLose_When_ClientCloses() + public async Task WithNoSetupShouldJustWaitForClose_AndClose_When_ClientCloses() { // Arrange using var server = WireMockServer.Start(new WireMockServerSettings @@ -706,12 +706,14 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc public async Task WithWebSocketProxy_Should_Proxy_Multiple_TextMessages() { // Arrange - Start target echo server - var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings + using var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings { Logger = new TestOutputHelperWireMockLogger(output), Urls = ["ws://localhost:0"] }); + await Task.Delay(500, _ct); + exampleEchoServer .Given(Request.Create() .WithPath("/ws/target") @@ -724,12 +726,14 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc await Task.Delay(500, _ct); // Arrange - Start proxy server - var sut = WireMockServer.Start(new WireMockServerSettings + using var sut = WireMockServer.Start(new WireMockServerSettings { Logger = new TestOutputHelperWireMockLogger(output), Urls = ["ws://localhost:0"] }); + await Task.Delay(500, _ct); + sut .Given(Request.Create() .WithPath("/ws/proxy") @@ -761,26 +765,20 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc } await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", _ct); - - await Task.Delay(250, _ct); - - sut.Stop(); - sut.Dispose(); - - exampleEchoServer.Stop(); - exampleEchoServer.Dispose(); } [Fact] public async Task WithWebSocketProxy_Should_Proxy_Binary_Messages() { // Arrange - Start target echo server - var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings + using var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings { Logger = new TestOutputHelperWireMockLogger(output), Urls = ["ws://localhost:0"] }); + await Task.Delay(500, _ct); + exampleEchoServer .Given(Request.Create() .WithPath("/ws/target") @@ -793,12 +791,14 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc await Task.Delay(500, _ct); // Arrange - Start proxy server - var sut = WireMockServer.Start(new WireMockServerSettings + using var sut = WireMockServer.Start(new WireMockServerSettings { Logger = new TestOutputHelperWireMockLogger(output), Urls = ["ws://localhost:0"] }); + await Task.Delay(500, _ct); + sut .Given(Request.Create() .WithPath("/ws/proxy") @@ -828,15 +828,9 @@ public class WebSocketIntegrationTests(ITestOutputHelper output, ITestContextAcc // Assert receivedData.Should().BeEquivalentTo(testData, "binary data should be proxied and echoed back"); + await Task.Delay(500, _ct); + await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", _ct); - - await Task.Delay(250, _ct); - - sut.Stop(); - sut.Dispose(); - - exampleEchoServer.Stop(); - exampleEchoServer.Dispose(); } [Fact]