From fe4d74189ada5ad96da42201c21187d233577ad8 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 7 Oct 2025 19:59:53 +0200 Subject: [PATCH 1/2] Add coverage enforcement for test projects (#6950) * Add coverage enforcement for test projects * Expand GitHub Actions triggers to include additional branch patterns * Update `coverlet.msbuild` configuration and centralize dependency version management - Removed inline version specification for `coverlet.msbuild` in `test/Directory.Build.props`. - Centralized `coverlet.msbuild` version definition in `Directory.Packages.props` for consistency and maintainability. * Remove `Elsa.Common.Core` unit test project and related test files * Add Directory.Build.props for test project organization and update property configurations - Introduced `Directory.Build.props` files for `test/unit` and `test/integration` to define project-specific properties. - Updated `test/Directory.Build.props` to include new coverage formats and an exclusion for `Elsa.Testing.Shared`. - Adjusted solution file to link new `Directory.Build.props` files. - Configured threshold properties for `unit`, `integration`, and `component` test directories. * Disable coverage collection for performance tests in project file * Expand GitHub Actions workflow triggers and add PR-specific condition for test job --- .github/workflows/packages.yml | 107 ++++++++++++++---- Directory.Packages.props | 1 + Elsa.sln | 6 + test/Directory.Build.props | 13 ++- test/component/Directory.Build.props | 6 +- test/integration/Directory.Build.props | 9 ++ .../Elsa.Workflows.PerformanceTests.csproj | 1 + test/unit/Directory.Build.props | 9 ++ .../Elsa.Common.Core/Elsa.Common.Core.csproj | 5 - .../EnumerableExtensionsTests.cs | 29 ----- 10 files changed, 125 insertions(+), 61 deletions(-) create mode 100644 test/integration/Directory.Build.props create mode 100644 test/unit/Directory.Build.props delete mode 100644 test/unit/Elsa.Common.Core/Elsa.Common.Core.csproj delete mode 100644 test/unit/Elsa.Common.Core/EnumerableExtensionsTests.cs diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 10bb34007..37f97aa5b 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -1,4 +1,5 @@ name: Packages + on: workflow_dispatch: push: @@ -12,18 +13,87 @@ on: - 'rc/*' - 'develop/*' - 'codex/*' + pull_request: + branches: + - 'main' + - 'bug/*' + - 'perf/*' + - 'patch/*' + - 'feat/*' + - 'enh/*' + - 'rc/*' + - 'develop/*' + - 'codex/*' release: - types: [ prereleased, published ] + types: [prereleased, published] + env: base_version: '3.6.0' feedz_feed_source: 'https://f.feedz.io/elsa-workflows/elsa-3/nuget/index.json' nuget_feed_source: 'https://api.nuget.org/v3/index.json' jobs: - build: - name: Build packages + test: + name: Test with coverage runs-on: ubuntu-latest timeout-minutes: 30 + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up .NET SDKs + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.x + 9.0.x + + - name: Cache NuGet packages + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/Directory.Packages.props', '**/*.csproj') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Restore solution + run: dotnet restore Elsa.sln + + - name: Build solution + run: dotnet build Elsa.sln --no-restore --configuration Release + + - name: Prepare coverage directory + run: | + rm -rf artifacts/coverage + mkdir -p artifacts/coverage + + - name: Run tests with coverage + run: | + set -euo pipefail + mapfile -t projects < <(find test -type f -name '*.csproj' | sort) + if [ ${#projects[@]} -eq 0 ]; then + echo "No test projects were found in the test directory." >&2 + exit 1 + fi + for project in "${projects[@]}"; do + echo "Running tests with coverage for ${project}" + dotnet test "$project" --configuration Release --no-build --logger "GitHubActions;report-warnings=false" /p:CollectCoverage=true + done + + - name: Upload coverage reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-reports + path: artifacts/coverage + + build: + name: Build packages + needs: test + runs-on: ubuntu-latest + timeout-minutes: 30 + if: ${{ github.event_name != 'pull_request' }} steps: - name: Extract branch name run: | @@ -31,28 +101,31 @@ jobs: BRANCH_NAME=${BRANCH_NAME#refs/heads/} # remove the refs/heads/ prefix # Extract the last part after the last slash of the branch name, if any, e.g., feature/issue-123 -> issue-123 and use it as the version prefix. PACKAGE_PREFIX=$(echo $BRANCH_NAME | rev | cut -d/ -f1 | rev | tr '_' '-') - + # If the branch name is main, use the preview version. Otherwise, use the branch name as the version prefix. if [[ "${BRANCH_NAME}" == "main" || "${BRANCH_NAME}" =~ ^develop/ ]]; then PACKAGE_PREFIX="preview" fi - + echo "Ref: ${{ github.ref }}" echo "Branch name: ${BRANCH_NAME}" echo "Package prefix: ${PACKAGE_PREFIX}" echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV echo "PACKAGE_PREFIX=${PACKAGE_PREFIX}" >> $GITHUB_ENV + - name: Checkout uses: actions/checkout@v4 + - name: Verify commit exists in branch run: | - if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && ("${{ github.event.action }}" == "published" || "${{ github.event.action }}" == "prereleased")]]; then + if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && ("${{ github.event.action }}" == "published" || "${{ github.event.action }}" == "prereleased") ]]; then git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* git branch --remote --contains | grep origin/develop/3.6.0 else git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* git branch --remote --contains | grep origin/${BRANCH_NAME} fi + - name: Set VERSION variable run: | if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && ("${{ github.event.action }}" == "published" || "${{ github.event.action }}" == "prereleased") ]]; then @@ -62,35 +135,21 @@ jobs: else echo "VERSION=${{env.base_version}}-preview.${{github.run_number}}" >> $GITHUB_ENV fi - # - name: Set up JDK 17 - # uses: actions/setup-java@v2 - # with: - # java-version: '17' - # distribution: 'adopt' + - uses: actions/setup-dotnet@v4 with: dotnet-version: 9.x - # - name: Install SonarScanner for .NET - # run: dotnet tool install --global dotnet-sonarscanner - # - name: Install Coverlet for code coverage - # run: dotnet tool install --global coverlet.console - # - name: Begin SonarCloud analysis - # env: - # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - # run: dotnet sonarscanner begin /k:"elsa-workflows_elsa-core" /o:"elsa-workflows" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.exclusions=**/obj/**,**/*.dll,build/**,samples/**,src/apps/** /d:"sonar.verbose=true" /d:sonar.cs.opencover.reportsPaths=**/testresults/**/coverage.opencover.xml + - name: Compile+Test+Pack run: ./build.sh Compile+Test+Pack --version ${VERSION} --analyseCode true - # - name: End SonarCloud analysis - # env: - # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - # run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" + - name: Upload artifact uses: actions/upload-artifact@v4 with: name: elsa-nuget-packages path: packages/*nupkg if: ${{ github.event_name == 'release' || github.event_name == 'push'}} - + publish_preview_feedz: name: Publish to feedz.io needs: build diff --git a/Directory.Packages.props b/Directory.Packages.props index 4768c5cc5..a411ccbda 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,6 +29,7 @@ + diff --git a/Elsa.sln b/Elsa.sln index 1a2bd9126..f0e4169fb 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -62,8 +62,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit", "unit", "{18453B51-25EB-4317-A4B3-B10518252E92}" + ProjectSection(SolutionItems) = preProject + test\unit\Directory.Build.props = test\unit\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{1B8D5897-902E-4632-8698-E89CAF3DDF54}" + ProjectSection(SolutionItems) = preProject + test\integration\Directory.Build.props = test\integration\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "component", "component", "{08B41FFA-CEE3-46A7-B5C0-3EB65D37A16C}" ProjectSection(SolutionItems) = preProject diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 03f0023c2..108bef4c9 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -9,6 +9,15 @@ false true false + true + cobertura,lcov,opencover + $(MSBuildThisFileDirectory)../artifacts/coverage/$(MSBuildProjectName)/coverage + 10 + line + total + + [*Elsa.Testing.Shared*]* + @@ -17,7 +26,7 @@ - + @@ -26,4 +35,4 @@ - \ No newline at end of file + diff --git a/test/component/Directory.Build.props b/test/component/Directory.Build.props index 94e6bc5b1..e6ff014e4 100644 --- a/test/component/Directory.Build.props +++ b/test/component/Directory.Build.props @@ -1,7 +1,11 @@ - + + + 40 + + diff --git a/test/integration/Directory.Build.props b/test/integration/Directory.Build.props new file mode 100644 index 000000000..d4fc658e9 --- /dev/null +++ b/test/integration/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + 10 + + + diff --git a/test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj b/test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj index ee58b4574..244833891 100644 --- a/test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj +++ b/test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj @@ -7,6 +7,7 @@ false Exe + false diff --git a/test/unit/Directory.Build.props b/test/unit/Directory.Build.props new file mode 100644 index 000000000..7e5383630 --- /dev/null +++ b/test/unit/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + 0 + + + diff --git a/test/unit/Elsa.Common.Core/Elsa.Common.Core.csproj b/test/unit/Elsa.Common.Core/Elsa.Common.Core.csproj deleted file mode 100644 index 0d2efc651..000000000 --- a/test/unit/Elsa.Common.Core/Elsa.Common.Core.csproj +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/test/unit/Elsa.Common.Core/EnumerableExtensionsTests.cs b/test/unit/Elsa.Common.Core/EnumerableExtensionsTests.cs deleted file mode 100644 index 3c1598fe8..000000000 --- a/test/unit/Elsa.Common.Core/EnumerableExtensionsTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Elsa.Extensions; -using Xunit; - -namespace Elsa.Common.Core; - -public class EnumerableExtensionsTests -{ - [Fact] - public void ToBatches_ReturnsItemsInListOfPages() - { - var items = new List - { - 1, - 2, - 3, - 4, - 5 - }; - var batchSize = 2; - var batches = items.ToBatches(batchSize).ToList(); - - Assert.Equal(3, batches.Count); - Assert.Equal(2, batches.ElementAt(0).Count()); - Assert.Equal(2, batches.ElementAt(1).Count()); - Assert.Equal(1, batches.ElementAt(2).Count()); - Assert.Equal(3, batches.ElementAt(1).ElementAt(0)); - Assert.Equal(4, batches.ElementAt(1).ElementAt(1)); - } -} \ No newline at end of file From bbbf13c58ce849b7fcbd5f81635876e23d7b46a2 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 7 Oct 2025 20:10:38 +0200 Subject: [PATCH 2/2] Allow tests to run on all events Remove condition to run tests only on pull requests. --- .github/workflows/packages.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 37f97aa5b..7e23ef7d4 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -37,7 +37,6 @@ jobs: name: Test with coverage runs-on: ubuntu-latest timeout-minutes: 30 - if: ${{ github.event_name == 'pull_request' }} steps: - name: Checkout uses: actions/checkout@v4