From c5e155cdc52310a5d71a12f205bd245bbc9ffe13 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 18:43:56 +0200 Subject: [PATCH 01/38] chore: add global.json to specify .NET SDK version and test runner --- global.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 global.json diff --git a/global.json b/global.json new file mode 100644 index 0000000..31c6981 --- /dev/null +++ b/global.json @@ -0,0 +1,9 @@ +{ + "sdk": { + "version": "10.0.201", + "rollForward": "latestPatch" + }, + "test": { + "runner": "Microsoft.Testing.Platform" + } +} From c2f87edb854b1513033461f635ce6bb02d56faae Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 18:44:23 +0200 Subject: [PATCH 02/38] build(ci): add first iteration of CI workflow for building and testing with coverage --- .github/workflows/build.yml | 205 ++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..1bbc233 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,205 @@ +name: Build + +on: + push: + branches: [ master, 'develop/*' ] + pull_request: + +env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_NOLOGO: true + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + - name: Restore dependencies + run: dotnet restore + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build + run: dotnet build --no-restore --configuration Release + + test: + name: Test + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build + run: dotnet build --configuration Release --no-restore + + - name: Run unit tests with coverage + run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" + + - name: Upload TRX artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: trx-unit + path: ./TestResults/*.trx + + - name: Upload coverage artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: coverage-unit + path: ./TestResults/**/*.cobertura.xml + + component-test: + name: Component test + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build + run: dotnet build --configuration Release --no-restore + + - name: Run Blazor component tests with coverage + run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + --report-trx --treenode-filter "/*/*/*/*[Category=Components]" + + - name: Upload TRX artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: trx-component + path: ./TestResults/*.trx + + - name: Upload coverage artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: coverage-component + path: ./TestResults/**/*.cobertura.xml + + integration-test: + name: Integration Test + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build + run: dotnet build --configuration Release + + - name: Run Blazor component tests with coverage + run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + --report-trx --treenode-filter "/*/*/*/*[Category=Components]" + + - name: Upload TRX artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: trx-integration + path: ./TestResults/*.trx + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + if: always() + with: + name: coverage-integration + path: ./TestResults/**/*.cobertura.xml + + report: + name: Report + runs-on: ubuntu-latest + needs: [test, component-test, integration-test] + if: always() + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Download all TRX artifacts + uses: actions/download-artifact@v6 + with: + pattern: trx-* + path: TestResults + merge-multiple: true + + - name: Download all coverage artifacts + uses: actions/download-artifact@v6 + with: + pattern: coverage-* + path: TestResults + merge-multiple: true + + - name: Publish test results + uses: dorny/test-reporter@v1 + if: always() + with: + name: Test Results + path: TestResults/*.trx + reporter: dotnet-trx + fail-on-error: true + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + directory: TestResults + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Qodana code inspection + uses: JetBrains/qodana-action@v2025.3 + env: + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} + QODANA_ENDPOINT: 'https://qodana.cloud' + with: + cache-default-branch-only: true \ No newline at end of file From db34b4b16af0b1d11d4188da9dd1a771bdef4074 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 18:47:45 +0200 Subject: [PATCH 03/38] build(ci): fix typo and missing restore steps --- .github/workflows/build.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1bbc233..c7fa23b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,9 @@ jobs: with: dotnet-version: '10.0.x' + - name: Restore dependencies + run: dotnet restore + - name: Cache NuGet packages uses: actions/cache@v5 with: @@ -89,6 +92,9 @@ jobs: with: dotnet-version: '10.0.x' + - name: Restore dependencies + run: dotnet restore + - name: Cache NuGet packages uses: actions/cache@v5 with: @@ -129,6 +135,9 @@ jobs: uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore - name: Cache NuGet packages uses: actions/cache@v5 @@ -140,9 +149,9 @@ jobs: - name: Build run: dotnet build --configuration Release - - name: Run Blazor component tests with coverage + - name: Run integration tests with coverage run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ - --report-trx --treenode-filter "/*/*/*/*[Category=Components]" + --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" - name: Upload TRX artifact uses: actions/upload-artifact@v6 @@ -161,7 +170,7 @@ jobs: report: name: Report runs-on: ubuntu-latest - needs: [test, component-test, integration-test] + needs: [ test, component-test, integration-test ] if: always() steps: - name: Checkout From 02db56229ce7d3311b6d33e4fbe62ce1e3f0583c Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 18:51:00 +0200 Subject: [PATCH 04/38] build(ci): fix argument typo --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7fa23b..decdd6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run unit tests with coverage - run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" - name: Upload TRX artifact @@ -106,7 +106,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run Blazor component tests with coverage - run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ --report-trx --treenode-filter "/*/*/*/*[Category=Components]" - name: Upload TRX artifact @@ -150,7 +150,7 @@ jobs: run: dotnet build --configuration Release - name: Run integration tests with coverage - run: dotnet test --configuration Release --no-build --results-directors ./TestResults -- --coverage --coverage-output-format cobertura \ + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" - name: Upload TRX artifact From 3f8b627dec79ec346334dcf8e7cc9ca53e1528b0 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:07:06 +0200 Subject: [PATCH 05/38] build(ci): fix argument definition and add extra flags --- .github/workflows/build.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index decdd6a..5ea8934 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,8 +62,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run unit tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ - --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura - name: Upload TRX artifact uses: actions/upload-artifact@v6 @@ -106,8 +105,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run Blazor component tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ - --report-trx --treenode-filter "/*/*/*/*[Category=Components]" + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura - name: Upload TRX artifact uses: actions/upload-artifact@v6 @@ -147,11 +145,10 @@ jobs: restore-keys: ${{ runner.os }}-nuget- - name: Build - run: dotnet build --configuration Release + run: dotnet build --configuration Release --no-restore - name: Run integration tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output-format cobertura \ - --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura - name: Upload TRX artifact uses: actions/upload-artifact@v6 From 2f52c8e376759da379b06fb4d9b571718cfc5318 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:13:48 +0200 Subject: [PATCH 06/38] build(ci): add flag to ignore when test project ran no tests --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ea8934..b9c9186 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run unit tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v6 @@ -105,7 +105,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run Blazor component tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v6 @@ -148,7 +148,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Run integration tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v6 From 65cbe65063ba7e90edfcab4dbd6a503b71eae125 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:18:04 +0200 Subject: [PATCH 07/38] build(ci): remove test result publishing --- .github/workflows/build.yml | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b9c9186..390e0b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,6 +61,13 @@ jobs: - name: Build run: dotnet build --configuration Release --no-restore + - name: Expose GitHub Actions Runtime + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); + core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); + - name: Run unit tests with coverage run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 @@ -104,6 +111,13 @@ jobs: - name: Build run: dotnet build --configuration Release --no-restore + - name: Expose GitHub Actions Runtime + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); + core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); + - name: Run Blazor component tests with coverage run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 @@ -133,7 +147,7 @@ jobs: uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' - + - name: Restore dependencies run: dotnet restore @@ -147,6 +161,13 @@ jobs: - name: Build run: dotnet build --configuration Release --no-restore + - name: Expose GitHub Actions Runtime + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); + core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); + - name: Run integration tests with coverage run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 @@ -187,15 +208,6 @@ jobs: path: TestResults merge-multiple: true - - name: Publish test results - uses: dorny/test-reporter@v1 - if: always() - with: - name: Test Results - path: TestResults/*.trx - reporter: dotnet-trx - fail-on-error: true - - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: From e1a73430468c47c02da6f790c83cff30872c2d9d Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:25:40 +0200 Subject: [PATCH 08/38] build(ci): fix qodana action step --- .github/workflows/build.yml | 1 + qodana.yaml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 390e0b9..fdb30f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,4 +220,5 @@ jobs: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} QODANA_ENDPOINT: 'https://qodana.cloud' with: + args: --image jetbrains/qodana-cdnet:2025.1 cache-default-branch-only: true \ No newline at end of file diff --git a/qodana.yaml b/qodana.yaml index b0a303c..e57f465 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -3,7 +3,6 @@ #################################################################################################################### version: "1.0" -linter: jetbrains/qodana-cdnet:2025.3 profile: name: qodana.recommended include: From 6dd13e11d2f4b2ba57fa8012c4704dffdaff0175 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:31:04 +0200 Subject: [PATCH 09/38] test(aspire): extend the resource timeout to 3 minutes for integration tests --- test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs index 91ca51f..07fa643 100644 --- a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs +++ b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs @@ -5,6 +5,7 @@ namespace TUnit.Sample.AppHost.IntegrationTests; public class AppFixture : AspireFixture { + protected override TimeSpan ResourceTimeout => TimeSpan.FromMinutes(3); protected override ResourceWaitBehavior WaitBehavior => ResourceWaitBehavior.Named; protected override IEnumerable ResourcesToWaitFor() => [ResourceConstants.WebApi, ResourceConstants.WebFrontend]; From 53d785a818585ea329eea5bac1264daefd502409 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:35:37 +0200 Subject: [PATCH 10/38] test: update CoreIntegrationTestBase to use CreateTablesAsync for database setup --- .../Utility/CoreIntegrationTestBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/TUnit.Sample.ApiService.IntegrationTests/Utility/CoreIntegrationTestBase.cs b/test/TUnit.Sample.ApiService.IntegrationTests/Utility/CoreIntegrationTestBase.cs index ebd6ad7..6b81863 100644 --- a/test/TUnit.Sample.ApiService.IntegrationTests/Utility/CoreIntegrationTestBase.cs +++ b/test/TUnit.Sample.ApiService.IntegrationTests/Utility/CoreIntegrationTestBase.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Npgsql; @@ -40,7 +41,8 @@ CREATE SCHEMA IF NOT EXISTS "{SchemaName}" .Options; await using var dbContext = new CoreDbContext(options) { SchemaName = SchemaName }; - await dbContext.Database.EnsureCreatedAsync(); + var dbCreator = (RelationalDatabaseCreator)dbContext.Database.GetService(); + await dbCreator.CreateTablesAsync(); } protected override void ConfigureTestConfiguration(IConfigurationBuilder config) From bb0bbcde3d1d06eeb675b8635b87d5c229abed22 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:35:47 +0200 Subject: [PATCH 11/38] build(ci): update Qodana image to version 2025.3 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fdb30f5..fe74a59 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,5 +220,5 @@ jobs: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} QODANA_ENDPOINT: 'https://qodana.cloud' with: - args: --image jetbrains/qodana-cdnet:2025.1 + args: --image jetbrains/qodana-cdnet:2025.3 cache-default-branch-only: true \ No newline at end of file From de32fafd91782e3162bd5e36ef450034c41808b3 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:40:41 +0200 Subject: [PATCH 12/38] build(ci): add codecov test publishing and update qodana action step --- .github/workflows/build.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe74a59..43bd620 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -211,14 +211,18 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: - directory: TestResults + directory: ./TestResults token: ${{ secrets.CODECOV_TOKEN }} + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/codecov-action@v5 + with: + directory: ./TestResults + token: ${{ secrets.CODECOV_TOKEN }} + report_type: test_results + - name: Qodana code inspection uses: JetBrains/qodana-action@v2025.3 env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} - QODANA_ENDPOINT: 'https://qodana.cloud' - with: - args: --image jetbrains/qodana-cdnet:2025.3 - cache-default-branch-only: true \ No newline at end of file + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} \ No newline at end of file From 778d8d53d40dbc92117a2f8fd189c31f746fe2e8 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:47:44 +0200 Subject: [PATCH 13/38] test(aspire): wait for only resources under test to spin up --- test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs index 07fa643..57d99ca 100644 --- a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs +++ b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs @@ -7,7 +7,7 @@ public class AppFixture : AspireFixture { protected override TimeSpan ResourceTimeout => TimeSpan.FromMinutes(3); protected override ResourceWaitBehavior WaitBehavior => ResourceWaitBehavior.Named; - protected override IEnumerable ResourcesToWaitFor() => [ResourceConstants.WebApi, ResourceConstants.WebFrontend]; + protected override IEnumerable ResourcesToWaitFor() => [ResourceConstants.WebApi]; protected override void ConfigureBuilder(IDistributedApplicationTestingBuilder builder) { From 3735028fdb3333e1a01218426b78a3f4c40d516a Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:02:49 +0200 Subject: [PATCH 14/38] build(ci): isolate apphost tests to a separate job --- .github/workflows/build.yml | 52 +++++++++++++++++++ .../AppFixture.cs | 2 +- .../GlobalSetup.cs | 2 +- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 43bd620..7976346 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -185,6 +185,58 @@ jobs: name: coverage-integration path: ./TestResults/**/*.cobertura.xml + aspire-test: + name: Aspire Test + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build + run: dotnet build --configuration Release --no-restore + + - name: Expose GitHub Actions Runtime + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); + core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); + + - name: Run Aspire tests with coverage + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 + env: + ASPIRE_ALLOW_UNSECURED_TRANSPORT: true + + - name: Upload TRX artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: trx-aspire + path: ./TestResults/*.trx + + - name: Upload coverage artifact + uses: actions/upload-artifact@v6 + if: always() + with: + name: coverage-aspire + path: ./TestResults/**/*.cobertura.xml + report: name: Report runs-on: ubuntu-latest diff --git a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs index 57d99ca..85899e6 100644 --- a/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs +++ b/test/TUnit.Sample.AppHost.IntegrationTests/AppFixture.cs @@ -5,7 +5,7 @@ namespace TUnit.Sample.AppHost.IntegrationTests; public class AppFixture : AspireFixture { - protected override TimeSpan ResourceTimeout => TimeSpan.FromMinutes(3); + protected override TimeSpan ResourceTimeout => TimeSpan.FromMinutes(4); protected override ResourceWaitBehavior WaitBehavior => ResourceWaitBehavior.Named; protected override IEnumerable ResourcesToWaitFor() => [ResourceConstants.WebApi]; diff --git a/test/TUnit.Sample.AppHost.IntegrationTests/GlobalSetup.cs b/test/TUnit.Sample.AppHost.IntegrationTests/GlobalSetup.cs index 2c94b0c..e7c1615 100644 --- a/test/TUnit.Sample.AppHost.IntegrationTests/GlobalSetup.cs +++ b/test/TUnit.Sample.AppHost.IntegrationTests/GlobalSetup.cs @@ -1 +1 @@ -[assembly: Category("Integration")] \ No newline at end of file +[assembly: Category("AppHost")] \ No newline at end of file From 3bf553dcdf7e7927f9534bec9cce8db54acf59b2 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:09:06 +0200 Subject: [PATCH 15/38] build: specify Qodana linter --- qodana.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/qodana.yaml b/qodana.yaml index e57f465..b0a303c 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -3,6 +3,7 @@ #################################################################################################################### version: "1.0" +linter: jetbrains/qodana-cdnet:2025.3 profile: name: qodana.recommended include: From 80b5872fdab6134cb400be129aa00742d759c94c Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:12:29 +0200 Subject: [PATCH 16/38] build(ci): move qodana to a separate operation --- .github/workflows/build.yml | 7 +------ .github/workflows/code-inspection.yml | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/code-inspection.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7976346..565cbb4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -272,9 +272,4 @@ jobs: with: directory: ./TestResults token: ${{ secrets.CODECOV_TOKEN }} - report_type: test_results - - - name: Qodana code inspection - uses: JetBrains/qodana-action@v2025.3 - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} \ No newline at end of file + report_type: test_results \ No newline at end of file diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml new file mode 100644 index 0000000..eec471c --- /dev/null +++ b/.github/workflows/code-inspection.yml @@ -0,0 +1,25 @@ +name: Code inspection +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + - main + - 'releases/*' # The release branches +jobs: + qodana: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + checks: write + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit + fetch-depth: 0 # a full history is required for pull request analysis + - name: 'Qodana Scan' + uses: JetBrains/qodana-action@v2025.3 + env: + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} \ No newline at end of file From b5879a488d8f2b41d8b0e479e032fb9e228e2997 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:15:45 +0200 Subject: [PATCH 17/38] build(ci): add requirement on the aspire-test job for report generation --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 565cbb4..04fd2d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -240,7 +240,7 @@ jobs: report: name: Report runs-on: ubuntu-latest - needs: [ test, component-test, integration-test ] + needs: [ test, component-test, integration-test, aspire-test ] if: always() steps: - name: Checkout From 9cdd267063a47b8b32408cc504e386f6107bc10d Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:18:24 +0200 Subject: [PATCH 18/38] build(ci): update ASPIRE_ALLOW_UNSECURED_TRANSPORT --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04fd2d9..388107e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -221,7 +221,7 @@ jobs: - name: Run Aspire tests with coverage run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 env: - ASPIRE_ALLOW_UNSECURED_TRANSPORT: true + ASPIRE_ALLOW_UNSECURED_TRANSPORT: "true" - name: Upload TRX artifact uses: actions/upload-artifact@v6 From bc5d697226a5ddd03eeaa6bffacd969bc15dc7be Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:30:45 +0200 Subject: [PATCH 19/38] build(ci): trust ASP.NET Core dev certificate in workflow --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 388107e..26b8703 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -218,6 +218,12 @@ jobs: core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); + - name: Trust ASP.NET Core dev certificate + run: | + dotnet dev-certs https -ep "$HOME/.aspnet/https/devcert.crt" --format PEM --no-password + sudo cp "$HOME/.aspnet/https/devcert.crt" /usr/local/share/ca-certificates/dotnet-devcert.crt + sudo update-ca-certificates + - name: Run Aspire tests with coverage run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 env: From fdb1ad19412955e6955218aa343d0d4452cb20c5 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:34:04 +0200 Subject: [PATCH 20/38] build(ci): add Codecov configuration file with coverage thresholds --- codecov.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..3b8d4af --- /dev/null +++ b/codecov.yml @@ -0,0 +1,14 @@ +coverage: + status: + project: + default: + target: 80% + threshold: 3% + patch: + default: + target: 80% + threshold: 3% + +comment: + layout: "condensed_header, diff, flags, components" + require_changes: true \ No newline at end of file From 95c682880ff57386c39d7f8d49a64f6743a3d230 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:34:24 +0200 Subject: [PATCH 21/38] build(ci): update script to create directory before copying certificate --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26b8703..71d5ff1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,6 +220,7 @@ jobs: - name: Trust ASP.NET Core dev certificate run: | + mkdir -p "$HOME/.aspnet/https" dotnet dev-certs https -ep "$HOME/.aspnet/https/devcert.crt" --format PEM --no-password sudo cp "$HOME/.aspnet/https/devcert.crt" /usr/local/share/ca-certificates/dotnet-devcert.crt sudo update-ca-certificates From 4b0905d39f3f25b96d196ffe80c5ec89ce31eaba Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:44:53 +0200 Subject: [PATCH 22/38] build(ci): update action versions to latest --- .github/workflows/build.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71d5ff1..8e12577 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Expose GitHub Actions Runtime - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); @@ -72,14 +72,14 @@ jobs: run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: trx-unit path: ./TestResults/*.trx - name: Upload coverage artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: coverage-unit @@ -112,7 +112,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Expose GitHub Actions Runtime - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); @@ -122,14 +122,14 @@ jobs: run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: trx-component path: ./TestResults/*.trx - name: Upload coverage artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: coverage-component @@ -162,7 +162,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Expose GitHub Actions Runtime - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); @@ -172,14 +172,14 @@ jobs: run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: trx-integration path: ./TestResults/*.trx - name: Upload coverage artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() with: name: coverage-integration @@ -212,7 +212,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Expose GitHub Actions Runtime - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']); @@ -231,14 +231,14 @@ jobs: ASPIRE_ALLOW_UNSECURED_TRANSPORT: "true" - name: Upload TRX artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: trx-aspire path: ./TestResults/*.trx - name: Upload coverage artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: always() with: name: coverage-aspire @@ -254,14 +254,14 @@ jobs: uses: actions/checkout@v6 - name: Download all TRX artifacts - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v8 with: pattern: trx-* path: TestResults merge-multiple: true - name: Download all coverage artifacts - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v8 with: pattern: coverage-* path: TestResults From 18d3d33042dbf598994ee4d629ed248165b481fb Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:55:23 +0200 Subject: [PATCH 23/38] build(ci): update coverage output path for consistency across workflows --- .github/workflows/build.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e12577..0e15566 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,7 +69,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run unit tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -83,7 +83,7 @@ jobs: if: always() with: name: coverage-unit - path: ./TestResults/**/*.cobertura.xml + path: ./TestResults/coverage.cobertura.xml component-test: name: Component test @@ -119,7 +119,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run Blazor component tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -133,7 +133,7 @@ jobs: if: always() with: name: coverage-component - path: ./TestResults/**/*.cobertura.xml + path: ./TestResults/coverage.cobertura.xml integration-test: name: Integration Test @@ -169,7 +169,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run integration tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -183,7 +183,7 @@ jobs: if: always() with: name: coverage-integration - path: ./TestResults/**/*.cobertura.xml + path: ./TestResults/coverage.cobertura.xml aspire-test: name: Aspire Test @@ -226,7 +226,7 @@ jobs: sudo update-ca-certificates - name: Run Aspire tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 env: ASPIRE_ALLOW_UNSECURED_TRANSPORT: "true" @@ -242,7 +242,7 @@ jobs: if: always() with: name: coverage-aspire - path: ./TestResults/**/*.cobertura.xml + path: ./TestResults/coverage.cobertura.xml report: name: Report @@ -265,7 +265,6 @@ jobs: with: pattern: coverage-* path: TestResults - merge-multiple: true - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 From 9ee2a88e159ca74b8cb7976fbb7cb1053283f5a5 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:56:07 +0200 Subject: [PATCH 24/38] build(ci): add concurrency control to cancel in-progress workflows --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e15566..92ec2ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,10 @@ env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: true DOTNET_NOLOGO: true + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: build: From e9bcc4c7f891d95fde87ff8809e9e185e4f76680 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:05:04 +0200 Subject: [PATCH 25/38] build(ci): expand test result artifact paths and log retrieved artifacts --- .github/workflows/build.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 92ec2ab..e8d2e30 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,7 +80,7 @@ jobs: if: always() with: name: trx-unit - path: ./TestResults/*.trx + path: ./TestResults/**/*.trx - name: Upload coverage artifact uses: actions/upload-artifact@v7 @@ -130,7 +130,7 @@ jobs: if: always() with: name: trx-component - path: ./TestResults/*.trx + path: ./TestResults/**/*.trx - name: Upload coverage artifact uses: actions/upload-artifact@v7 @@ -180,7 +180,7 @@ jobs: if: always() with: name: trx-integration - path: ./TestResults/*.trx + path: ./TestResults/**/*.trx - name: Upload coverage artifact uses: actions/upload-artifact@v7 @@ -239,7 +239,7 @@ jobs: if: always() with: name: trx-aspire - path: ./TestResults/*.trx + path: ./TestResults/**/*.trx - name: Upload coverage artifact uses: actions/upload-artifact@v7 @@ -270,6 +270,10 @@ jobs: pattern: coverage-* path: TestResults + - name: List downloaded artifacts + if: always() + run: find TestResults -type f | sort 2>/dev/null || echo "No files found in TestResults" + - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: From b6706ed4e6b835658c1d8fdad343c5ad253fb316 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:11:42 +0200 Subject: [PATCH 26/38] build(ci): update coverage and test result file paths for consistency across workflows --- .github/workflows/build.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e8d2e30..e324167 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -73,7 +73,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run unit tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=UnitTest]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -87,7 +87,7 @@ jobs: if: always() with: name: coverage-unit - path: ./TestResults/coverage.cobertura.xml + path: ./TestResults/**/*.cobertura.xml component-test: name: Component test @@ -123,7 +123,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run Blazor component tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Components]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -137,7 +137,7 @@ jobs: if: always() with: name: coverage-component - path: ./TestResults/coverage.cobertura.xml + path: ./TestResults/**/*.cobertura.xml integration-test: name: Integration Test @@ -173,7 +173,7 @@ jobs: core.exportVariable('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL']); - name: Run integration tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=Integration]" --coverage-output-format cobertura --ignore-exit-code 8 - name: Upload TRX artifact uses: actions/upload-artifact@v7 @@ -187,7 +187,7 @@ jobs: if: always() with: name: coverage-integration - path: ./TestResults/coverage.cobertura.xml + path: ./TestResults/**/*.cobertura.xml aspire-test: name: Aspire Test @@ -230,7 +230,7 @@ jobs: sudo update-ca-certificates - name: Run Aspire tests with coverage - run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --coverage-output ./TestResults/coverage.cobertura.xml --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 + run: dotnet test --configuration Release --no-build --results-directory ./TestResults -- --coverage --report-trx --treenode-filter "/*/*/*/*[Category=AppHost]" --coverage-output-format cobertura --ignore-exit-code 8 env: ASPIRE_ALLOW_UNSECURED_TRANSPORT: "true" @@ -246,7 +246,7 @@ jobs: if: always() with: name: coverage-aspire - path: ./TestResults/coverage.cobertura.xml + path: ./TestResults/**/*.cobertura.xml report: name: Report @@ -277,13 +277,13 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: - directory: ./TestResults + files: ./TestResults/**/*.cobertura.xml token: ${{ secrets.CODECOV_TOKEN }} - name: Upload test results to Codecov if: ${{ !cancelled() }} uses: codecov/codecov-action@v5 with: - directory: ./TestResults + files: ./TestResults/**/*.trx token: ${{ secrets.CODECOV_TOKEN }} report_type: test_results \ No newline at end of file From fc688092b2c993eccb318d2d6e743a0a822eeb76 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:19:38 +0200 Subject: [PATCH 27/38] build(ci): remove Qodana code quality workflow --- .github/workflows/qodana_code_quality.yml | 28 ----------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/qodana_code_quality.yml diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml deleted file mode 100644 index 647aa9f..0000000 --- a/.github/workflows/qodana_code_quality.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Qodana -on: - workflow_dispatch: - pull_request: - push: - branches: # Specify your branches here - - main # The 'main' branch - - 'releases/*' # The release branches - -jobs: - qodana: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - checks: write - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit - fetch-depth: 0 # a full history is required for pull request analysis - - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2025.3 - with: - pr-mode: false - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1507766807 }} - QODANA_ENDPOINT: 'https://qodana.cloud' \ No newline at end of file From dffe94c8e60607a404ed0c44533de540bf1ee992 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:28:17 +0200 Subject: [PATCH 28/38] build(ci): update Qodana linter to latest version --- qodana.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qodana.yaml b/qodana.yaml index b0a303c..d1ba9fe 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -3,7 +3,7 @@ #################################################################################################################### version: "1.0" -linter: jetbrains/qodana-cdnet:2025.3 +linter: jetbrains/qodana-cdnet:latest profile: name: qodana.recommended include: From 8ee7afcfae80b56ec9aadee081296c7ade65373e Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:33:03 +0200 Subject: [PATCH 29/38] build(ci): specify solution file for Qodana dotnet linter --- qodana.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qodana.yaml b/qodana.yaml index d1ba9fe..0ea47b3 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -4,6 +4,8 @@ version: "1.0" linter: jetbrains/qodana-cdnet:latest +dotnet: + solution: TUnit.Sample.slnx profile: name: qodana.recommended include: From ee887b007c49bba155ccf8959b73c7187349e43c Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:42:58 +0200 Subject: [PATCH 30/38] build(ci): unify .NET version variable and add build step to code-inspection workflow --- .github/workflows/build.yml | 2 +- .github/workflows/code-inspection.yml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e324167..f789f5d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -200,7 +200,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v5 with: - dotnet-version: '10.0.x' + dotnet-version: ${{ vars.DOTNET_VERSION }} - name: Restore dependencies run: dotnet restore diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index eec471c..5d5ab84 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -19,6 +19,15 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ vars.DOTNET_VERSION }} + + - name: Build + run: dotnet build --configuration Release + - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2025.3 env: From f303cffc752e11d44fe2cf483eb4eddd134e8a4f Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:57:26 +0200 Subject: [PATCH 31/38] build(ci): restrict workflow to master branch only --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f789f5d..6ef6dc0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build on: push: - branches: [ master, 'develop/*' ] + branches: [ master ] pull_request: env: From 4ae7c6b5fa9abf2e665aca57cece4bb05bec3179 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:05:39 +0200 Subject: [PATCH 32/38] build(ci): add NuGet caching and remove unused Qodana linter configuration --- .github/workflows/code-inspection.yml | 14 ++++++++++---- qodana.yaml | 3 --- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index 5ee2436..14e9f32 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -25,13 +25,19 @@ jobs: with: dotnet-version: ${{ vars.DOTNET_VERSION }} - - name: Build - run: dotnet build --configuration Release + - name: Restore dependencies + run: dotnet restore + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} + restore-keys: ${{ runner.os }}-nuget- - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2025.3 with: pr-mode: false env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} - QODANA_ENDPOINT: 'https://qodana.cloud' \ No newline at end of file + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} \ No newline at end of file diff --git a/qodana.yaml b/qodana.yaml index 0ea47b3..e57f465 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -3,9 +3,6 @@ #################################################################################################################### version: "1.0" -linter: jetbrains/qodana-cdnet:latest -dotnet: - solution: TUnit.Sample.slnx profile: name: qodana.recommended include: From 6fa0d6ec61d4ff712e5c1ac36f85dbc3bfb7a36f Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:12:03 +0200 Subject: [PATCH 33/38] build(ci): specify solution file for Qodana action configuration --- .github/workflows/code-inspection.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index 14e9f32..a7989ed 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -39,5 +39,6 @@ jobs: uses: JetBrains/qodana-action@v2025.3 with: pr-mode: false + args: --solution TUnit.Sample.slnx env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} \ No newline at end of file From a23e775c52c65620a8ea88c99b790b4d174dcd07 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:17:06 +0200 Subject: [PATCH 34/38] build(ci): reorder steps in code-inspection workflow and pass --no-build to Qodana --- .github/workflows/code-inspection.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index a7989ed..c305d13 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -25,9 +25,6 @@ jobs: with: dotnet-version: ${{ vars.DOTNET_VERSION }} - - name: Restore dependencies - run: dotnet restore - - name: Cache NuGet packages uses: actions/cache@v5 with: @@ -35,10 +32,16 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/global.json') }} restore-keys: ${{ runner.os }}-nuget- + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --configuration Debug --no-restore + - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2025.3 with: pr-mode: false - args: --solution TUnit.Sample.slnx + args: --solution TUnit.Sample.slnx --no-build env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} \ No newline at end of file From a70af8a95b717cd1408e699941bf39239db6d589 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:22:40 +0200 Subject: [PATCH 35/38] build(ci): unset DOTNET_ROOT before Qodana scan in code-inspection workflow --- .github/workflows/code-inspection.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index c305d13..633851f 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -38,6 +38,9 @@ jobs: - name: Build run: dotnet build --configuration Debug --no-restore + - name: Unset DOTNET_ROOT + run: echo "DOTNET_ROOT=" >> $GITHUB_ENV + - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2025.3 with: From 3753b82eac05a4c130205f53d9ed7cf02a715417 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:30:14 +0200 Subject: [PATCH 36/38] build(ci): adjust Qodana configuration and update dotnet-cli property in code-inspection workflow --- .github/workflows/code-inspection.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index 633851f..9357f52 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -38,13 +38,13 @@ jobs: - name: Build run: dotnet build --configuration Debug --no-restore - - name: Unset DOTNET_ROOT - run: echo "DOTNET_ROOT=" >> $GITHUB_ENV +# - name: Install .NET SDK for Qodana +# run: curl -sSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 10.0 --install-dir "$GITHUB_WORKSPACE/.dotnet" - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2025.3 with: pr-mode: false - args: --solution TUnit.Sample.slnx --no-build + args: --solution TUnit.Sample.slnx --property=dotnet.msbuild.dotnet-cli=/usr/share/dotnet/dotnet env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} \ No newline at end of file From 9122b82ef15f44a6351f11418de29a2d3f6ed5a8 Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:33:59 +0200 Subject: [PATCH 37/38] build(ci): comment out unused Qodana action arguments and profile configuration --- .github/workflows/code-inspection.yml | 2 +- qodana.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code-inspection.yml b/.github/workflows/code-inspection.yml index 9357f52..cf10d14 100644 --- a/.github/workflows/code-inspection.yml +++ b/.github/workflows/code-inspection.yml @@ -45,6 +45,6 @@ jobs: uses: JetBrains/qodana-action@v2025.3 with: pr-mode: false - args: --solution TUnit.Sample.slnx --property=dotnet.msbuild.dotnet-cli=/usr/share/dotnet/dotnet +# args: --solution TUnit.Sample.slnx --property=dotnet.msbuild.dotnet-cli=/usr/share/dotnet/dotnet env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1311845410 }} \ No newline at end of file diff --git a/qodana.yaml b/qodana.yaml index e57f465..bc2de96 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -2,8 +2,8 @@ # WARNING: Do not store sensitive information in this file, as its contents will be included in the Qodana report. # #################################################################################################################### -version: "1.0" -profile: - name: qodana.recommended -include: - - name: CheckDependencyLicenses \ No newline at end of file +#version: "1.0" +#profile: +# name: qodana.recommended +#include: +# - name: CheckDependencyLicenses \ No newline at end of file From c808334ec907b07e299c66853fdc7455d878287c Mon Sep 17 00:00:00 2001 From: Mark Novak <67005577+tavanuka@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:36:57 +0200 Subject: [PATCH 38/38] build(ci): enable Qodana configuration with solution file and recommended profile --- qodana.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/qodana.yaml b/qodana.yaml index bc2de96..24d3c5c 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -2,8 +2,10 @@ # WARNING: Do not store sensitive information in this file, as its contents will be included in the Qodana report. # #################################################################################################################### -#version: "1.0" -#profile: -# name: qodana.recommended -#include: -# - name: CheckDependencyLicenses \ No newline at end of file +version: "1.0" +dotnet: + solution: TUnit.Sample.slnx +profile: + name: qodana.recommended +include: + - name: CheckDependencyLicenses \ No newline at end of file