From cb26e47f9b4cd4ac46531827cd917de8d3db0cbe Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:39:32 +0100 Subject: [PATCH 01/17] add tests on pr --- .github/workflows/run-tests-on-pr.yml | 44 +++++++++++++++++++++++++++ CleanArchitecture.sln | 1 + 2 files changed, 45 insertions(+) create mode 100644 .github/workflows/run-tests-on-pr.yml diff --git a/.github/workflows/run-tests-on-pr.yml b/.github/workflows/run-tests-on-pr.yml new file mode 100644 index 0000000..a371989 --- /dev/null +++ b/.github/workflows/run-tests-on-pr.yml @@ -0,0 +1,44 @@ +name: Run tests and publish results on PRs 🧪 + +on: + pull_request: + branches: + - main + +permissions: + contents: read + checks: write + pull-requests: write + +env: + DOTNET_VERSION: "9.x" + +jobs: + + run-tests: + name: Run tests + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup .NET 📦 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Restore dependencies 📂 + run: dotnet restore + + - name: Run All Tests 🧪 + run: | + mkdir -p tests-results + dotnet test --logger "trx;LogFileName=test-results.trx" --results-directory ./tests-results + continue-on-error: true + + - name: Publish test results 📜 + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: tests-results/test-results.trx \ No newline at end of file diff --git a/CleanArchitecture.sln b/CleanArchitecture.sln index d4afea9..5b0a23e 100644 --- a/CleanArchitecture.sln +++ b/CleanArchitecture.sln @@ -10,6 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .github\dependabot.yml = .github\dependabot.yml Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props + .github\workflows\run-tests-on-pr.yml = .github\workflows\run-tests-on-pr.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{64A28C1B-09AF-426E-8721-D002BE554B48}" From 15bfb381b17cfda71f42be2f2df34a2e2c02b0c5 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:43:44 +0100 Subject: [PATCH 02/17] adding solution name --- .github/workflows/run-tests-on-pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests-on-pr.yml b/.github/workflows/run-tests-on-pr.yml index a371989..b933628 100644 --- a/.github/workflows/run-tests-on-pr.yml +++ b/.github/workflows/run-tests-on-pr.yml @@ -29,12 +29,12 @@ jobs: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Restore dependencies 📂 - run: dotnet restore + run: dotnet restore CleanArchitecture.sln - name: Run All Tests 🧪 run: | mkdir -p tests-results - dotnet test --logger "trx;LogFileName=test-results.trx" --results-directory ./tests-results + dotnet test CleanArchitecture.sln --logger "trx;LogFileName=test-results.trx" --results-directory ./tests-results continue-on-error: true - name: Publish test results 📜 From 5c7da45264e0ae89a069f799b0cff2a382abbf3d Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:46:04 +0100 Subject: [PATCH 03/17] some stuff --- .../Api.FunctionalTests/Users/RegisterUserTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs index 8da030f..3100dff 100644 --- a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs +++ b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs @@ -98,6 +98,6 @@ public async Task Should_ReturnConflict_WhenUserExists() // Act HttpResponseMessage response = await HttpClient.PostAsJsonAsync("/users/register", request); // Assert - response.StatusCode.Should().Be(HttpStatusCode.Conflict); + response.StatusCode.Should().Be(HttpStatusCode.OK); } } From 56ca4e4be23c141c9ee506cbbb8c81f3d0cad372 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:06:10 +0100 Subject: [PATCH 04/17] fix unit test --- src/Web.Api/Endpoints/Users/CreateUserRequest.cs | 2 +- .../Api.FunctionalTests/Users/RegisterUserTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Web.Api/Endpoints/Users/CreateUserRequest.cs b/src/Web.Api/Endpoints/Users/CreateUserRequest.cs index bd1f4f3..28e21a8 100644 --- a/src/Web.Api/Endpoints/Users/CreateUserRequest.cs +++ b/src/Web.Api/Endpoints/Users/CreateUserRequest.cs @@ -1,3 +1,3 @@ namespace Web.Api.Endpoints.Users; -public sealed record CreateUserRequest(string Email, string FirstName, string LastName, string Password); +public sealed record CreateUserRequest(string Email, string FirstName, string LastName, string Password) diff --git a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs index 3100dff..8da030f 100644 --- a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs +++ b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs @@ -98,6 +98,6 @@ public async Task Should_ReturnConflict_WhenUserExists() // Act HttpResponseMessage response = await HttpClient.PostAsJsonAsync("/users/register", request); // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); + response.StatusCode.Should().Be(HttpStatusCode.Conflict); } } From 1d4404248ab92d5844bdddc2ab7f28d3e5ed63d1 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:09:01 +0100 Subject: [PATCH 05/17] fix build --- .github/workflows/build.yml | 138 +++++++++--------- .../workflows/{run-tests-on-pr.yml => ci.yml} | 3 + .../Endpoints/Users/CreateUserRequest.cs | 2 +- 3 files changed, 73 insertions(+), 70 deletions(-) rename .github/workflows/{run-tests-on-pr.yml => ci.yml} (88%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 161ca68..e1fb1d3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,69 +1,69 @@ -name: Build & Test 🧪 - -on: - push: - branches: [ main ] - pull_request: - workflow_dispatch: - -env: - DOTNET_VERSION: "9.x" - -jobs: - - build_and_test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Cache NuGet 🗂️ - uses: actions/cache@v4 - with: - path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} - restore-keys: | - ${{ runner.os }}-nuget- - - - name: Setup .NET 📦 - uses: actions/setup-dotnet@v4 - with: - dotnet-version: ${{ env.DOTNET_VERSION }} - - - name: Restore dependencies 📂 - run: dotnet restore CleanArchitecture.sln - - - name: Build 🧱 - run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror - - - name: Run All Tests 🧪 - run: dotnet test CleanArchitecture.sln --configuration Release --no-build --logger trx --results-directory TestResults - - - name: Convert TRX to JUnit XML 📜 - uses: dorny/test-reporter@v2 - with: - name: All Tests - path: TestResults/*.trx - reporter: dotnet-trx - - publish: - runs-on: ubuntu-latest - needs: build_and_test - if: github.event_name == 'workflow_dispatch' - - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET 📦 - uses: actions/setup-dotnet@v4 - with: - dotnet-version: ${{ env.DOTNET_VERSION }} - - - name: Publish 🚀 - run: dotnet publish CleanArchitecture.sln --configuration Release --output ./published --no-build - - - name: Upload published artifacts - uses: actions/upload-artifact@v4 - with: - name: published-app - path: published +# name: Build & Test 🧪 + +# on: +# push: +# branches: [ main ] +# pull_request: +# workflow_dispatch: + +# env: +# DOTNET_VERSION: "9.x" + +# jobs: + +# build_and_test: +# runs-on: ubuntu-latest + +# steps: +# - uses: actions/checkout@v4 + +# - name: Cache NuGet 🗂️ +# uses: actions/cache@v4 +# with: +# path: ~/.nuget/packages +# key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} +# restore-keys: | +# ${{ runner.os }}-nuget- + +# - name: Setup .NET 📦 +# uses: actions/setup-dotnet@v4 +# with: +# dotnet-version: ${{ env.DOTNET_VERSION }} + +# - name: Restore dependencies 📂 +# run: dotnet restore CleanArchitecture.sln + +# - name: Build 🧱 +# run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror + +# - name: Run All Tests 🧪 +# run: dotnet test CleanArchitecture.sln --configuration Release --no-build --logger trx --results-directory TestResults + +# - name: Convert TRX to JUnit XML 📜 +# uses: dorny/test-reporter@v2 +# with: +# name: All Tests +# path: TestResults/*.trx +# reporter: dotnet-trx + +# publish: +# runs-on: ubuntu-latest +# needs: build_and_test +# if: github.event_name == 'workflow_dispatch' + +# steps: +# - uses: actions/checkout@v4 + +# - name: Setup .NET 📦 +# uses: actions/setup-dotnet@v4 +# with: +# dotnet-version: ${{ env.DOTNET_VERSION }} + +# - name: Publish 🚀 +# run: dotnet publish CleanArchitecture.sln --configuration Release --output ./published --no-build + +# - name: Upload published artifacts +# uses: actions/upload-artifact@v4 +# with: +# name: published-app +# path: published diff --git a/.github/workflows/run-tests-on-pr.yml b/.github/workflows/ci.yml similarity index 88% rename from .github/workflows/run-tests-on-pr.yml rename to .github/workflows/ci.yml index b933628..3e7bf4e 100644 --- a/.github/workflows/run-tests-on-pr.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,9 @@ jobs: - name: Restore dependencies 📂 run: dotnet restore CleanArchitecture.sln + - name: Build 🧱 + run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror + - name: Run All Tests 🧪 run: | mkdir -p tests-results diff --git a/src/Web.Api/Endpoints/Users/CreateUserRequest.cs b/src/Web.Api/Endpoints/Users/CreateUserRequest.cs index 28e21a8..bd1f4f3 100644 --- a/src/Web.Api/Endpoints/Users/CreateUserRequest.cs +++ b/src/Web.Api/Endpoints/Users/CreateUserRequest.cs @@ -1,3 +1,3 @@ namespace Web.Api.Endpoints.Users; -public sealed record CreateUserRequest(string Email, string FirstName, string LastName, string Password) +public sealed record CreateUserRequest(string Email, string FirstName, string LastName, string Password); From 866817caee16aabb76edfe266dbb4f25db423cb0 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:23:52 +0100 Subject: [PATCH 06/17] rajout de la couverture de code --- .github/workflows/ci.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e7bf4e..f05e5e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,11 +37,28 @@ jobs: - name: Run All Tests 🧪 run: | mkdir -p tests-results - dotnet test CleanArchitecture.sln --logger "trx;LogFileName=test-results.trx" --results-directory ./tests-results + dotnet test CleanArchitecture.sln --logger "trx;LogFileName=test-results.trx" --collect:"XPlat Code Coverage" --results-directory ./tests-results continue-on-error: true - name: Publish test results 📜 uses: EnricoMi/publish-unit-test-result-action@v2 if: always() with: - files: tests-results/test-results.trx \ No newline at end of file + files: tests-results/test-results.trx + - name: Show Code Coverage % + if: always() + run: | + coverage_file=$(find tests-results -name 'coverage.cobertura.xml' | head -n 1) + + if [ -z "$coverage_file" ]; then + echo "❌ Aucun fichier de couverture trouvé." + exit 0 + fi + + echo "📄 Fichier de couverture : $coverage_file" + + # Extraire l'attribut 'line-rate' du XML Cobertura + coverage=$(xmllint --xpath "string(/coverage/@line-rate)" "$coverage_file") + percentage=$(awk "BEGIN { printf \"%.2f\", $coverage * 100 }") + + echo "📊 **Couverture du code : $percentage%**" \ No newline at end of file From 5aad474dec74b0a39c63d9c7b9992ce4ca9221cf Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:27:33 +0100 Subject: [PATCH 07/17] fix --- CleanArchitecture.sln | 2 +- .../Api.FunctionalTests/Api.FunctionalTests.csproj | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CleanArchitecture.sln b/CleanArchitecture.sln index 5b0a23e..c061b3a 100644 --- a/CleanArchitecture.sln +++ b/CleanArchitecture.sln @@ -8,9 +8,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .github\workflows\build.yml = .github\workflows\build.yml .github\dependabot.yml = .github\dependabot.yml + .github\workflows\ci.yml = .github\workflows\ci.yml Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props - .github\workflows\run-tests-on-pr.yml = .github\workflows\run-tests-on-pr.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{64A28C1B-09AF-426E-8721-D002BE554B48}" diff --git a/tests/FunctionalTests/Api.FunctionalTests/Api.FunctionalTests.csproj b/tests/FunctionalTests/Api.FunctionalTests/Api.FunctionalTests.csproj index 2559528..40e1b36 100644 --- a/tests/FunctionalTests/Api.FunctionalTests/Api.FunctionalTests.csproj +++ b/tests/FunctionalTests/Api.FunctionalTests/Api.FunctionalTests.csproj @@ -7,6 +7,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 747a461ed26f487b3a5990579c1d45e78dfaabf7 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:30:26 +0100 Subject: [PATCH 08/17] fix coverage --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f05e5e4..93cc617 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,8 @@ jobs: if: always() with: files: tests-results/test-results.trx + - name: Install xmllint + run: sudo apt-get update && sudo apt-get install -y libxml2-utils - name: Show Code Coverage % if: always() run: | From f98f5c8232b4f313cccd9deaa097751501ae3d3e Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:48:20 +0100 Subject: [PATCH 09/17] =?UTF-8?q?mise=20=C3=A0=20jour=20avec=20affichage?= =?UTF-8?q?=20couverture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93cc617..9b2df93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ permissions: env: DOTNET_VERSION: "9.x" + COVERAGE_PERCENTAGE: ${{ steps.coverage_output.outputs.percentage }} jobs: @@ -63,4 +64,24 @@ jobs: coverage=$(xmllint --xpath "string(/coverage/@line-rate)" "$coverage_file") percentage=$(awk "BEGIN { printf \"%.2f\", $coverage * 100 }") - echo "📊 **Couverture du code : $percentage%**" \ No newline at end of file + echo "📊 **Couverture du code : $percentage%**" + - name: Post coverage as GitHub Check + uses: actions/github-script@v7 + if: always() + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const percentage = process.env.COVERAGE_PERCENTAGE; + + await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: "Code Coverage", + head_sha: context.sha, + status: "completed", + conclusion: "neutral", + output: { + title: "Code Coverage Result", + summary: `**${percentage}%**` + } + }); \ No newline at end of file From 5805dc50835909d48ab3d5a39c424e300fb4e707 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:50:48 +0100 Subject: [PATCH 10/17] fix --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b2df93..5b03f21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,6 @@ permissions: env: DOTNET_VERSION: "9.x" - COVERAGE_PERCENTAGE: ${{ steps.coverage_output.outputs.percentage }} jobs: @@ -84,4 +83,6 @@ jobs: title: "Code Coverage Result", summary: `**${percentage}%**` } - }); \ No newline at end of file + }); + env: + COVERAGE_PERCENTAGE: ${{ steps.coverage_output.outputs.percentage }} \ No newline at end of file From 99a3ede7ead4536b50e7ad88097bf15b3a0ff8a8 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:55:54 +0100 Subject: [PATCH 11/17] couverture --- .github/workflows/ci.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b03f21..efa2746 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,6 @@ env: DOTNET_VERSION: "9.x" jobs: - run-tests: name: Run tests runs-on: ubuntu-latest @@ -45,38 +44,48 @@ jobs: if: always() with: files: tests-results/test-results.trx + - name: Install xmllint run: sudo apt-get update && sudo apt-get install -y libxml2-utils + - name: Show Code Coverage % + id: coverage_output # ← IMPORTANT if: always() run: | coverage_file=$(find tests-results -name 'coverage.cobertura.xml' | head -n 1) if [ -z "$coverage_file" ]; then + echo "percentage=0" >> $GITHUB_OUTPUT echo "❌ Aucun fichier de couverture trouvé." exit 0 fi echo "📄 Fichier de couverture : $coverage_file" - # Extraire l'attribut 'line-rate' du XML Cobertura coverage=$(xmllint --xpath "string(/coverage/@line-rate)" "$coverage_file") percentage=$(awk "BEGIN { printf \"%.2f\", $coverage * 100 }") echo "📊 **Couverture du code : $percentage%**" + + # ⬅️ OUTPUT pour les autres étapes + echo "percentage=$percentage" >> $GITHUB_OUTPUT + - name: Post coverage as GitHub Check uses: actions/github-script@v7 if: always() with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const percentage = process.env.COVERAGE_PERCENTAGE; - + const percentage = "${{ steps.coverage_output.outputs.percentage }}"; + const sha = context.payload.pull_request + ? context.payload.pull_request.head.sha + : context.sha; + await github.rest.checks.create({ owner: context.repo.owner, repo: context.repo.repo, name: "Code Coverage", - head_sha: context.sha, + head_sha: sha, status: "completed", conclusion: "neutral", output: { @@ -84,5 +93,3 @@ jobs: summary: `**${percentage}%**` } }); - env: - COVERAGE_PERCENTAGE: ${{ steps.coverage_output.outputs.percentage }} \ No newline at end of file From b94d6597da5ed7acbb91ca36532c77b5b25dfb2a Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:00:58 +0100 Subject: [PATCH 12/17] comment couverture dans la pr --- .github/workflows/ci.yml | 92 +++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efa2746..d8790e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: # ⬅️ OUTPUT pour les autres étapes echo "percentage=$percentage" >> $GITHUB_OUTPUT - - name: Post coverage as GitHub Check + - name: Publish Coverage as Check uses: actions/github-script@v7 if: always() with: @@ -81,15 +81,87 @@ jobs: ? context.payload.pull_request.head.sha : context.sha; - await github.rest.checks.create({ + const checkName = "Code Coverage"; + + // Vérifier si un check existe déjà + const existing = await github.rest.checks.listForRef({ owner: context.repo.owner, repo: context.repo.repo, - name: "Code Coverage", - head_sha: sha, - status: "completed", - conclusion: "neutral", - output: { - title: "Code Coverage Result", - summary: `**${percentage}%**` - } + ref: sha }); + + const prev = existing.data.check_runs.find(c => c.name === checkName); + + if (prev) { + // Mise à jour du check + await github.rest.checks.update({ + owner: context.repo.owner, + repo: context.repo.repo, + check_run_id: prev.id, + conclusion: "neutral", + output: { + title: "Code Coverage Result", + summary: `Coverage: **${percentage}%**` + } + }); + } else { + // Création du check + await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: checkName, + head_sha: sha, + status: "completed", + conclusion: "neutral", + output: { + title: "Code Coverage Result", + summary: `Coverage: **${percentage}%**` + } + }); + } + - name: Comment coverage on PR + if: always() + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const percentage = "${{ steps.coverage_output.outputs.percentage }}"; + const pr = context.payload.pull_request?.number; + + if (!pr) { + console.log("No pull_request context, skipping."); + return; + } + + const body = `📊 **Code Coverage:** ${percentage}%`; + + // Chercher un commentaire existant + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr, + }); + + const botComment = comments.data.find(c => + c.body?.includes("📊 **Code Coverage:**") + ); + + if (botComment) { + // Mise à jour du commentaire + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body, + }); + } else { + // Nouveau commentaire + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr, + body, + }); + } + + From 9124fb90b562c3db11f4e44f6d255d15cf01fb83 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:06:16 +0100 Subject: [PATCH 13/17] 2 job : 1 pour build et un autre pour les tests --- .github/workflows/ci.yml | 112 ++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8790e1..ef8faae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ -name: Run tests and publish results on PRs 🧪 +name: build and tests 🧱 🧪 on: pull_request: branches: - - main + - main permissions: contents: read @@ -14,10 +14,39 @@ env: DOTNET_VERSION: "9.x" jobs: - run-tests: - name: Run tests + # ---------------------- + # 🔹 JOB BUILD + # ---------------------- + build: + name: Build 🧱 runs-on: ubuntu-latest + outputs: + build-artifact: ${{ steps.build_sln.outputs.artifact-path }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup .NET 📦 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Restore dependencies 📂 + run: dotnet restore CleanArchitecture.sln + + - name: Build solution 🧱 + id: build_sln + run: | + dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror + echo "artifact-path=./CleanArchitecture.sln" >> $GITHUB_OUTPUT + + # ---------------------- + # 🔹 JOB TEST + # ---------------------- + test: + name: Run Tests & Coverage 🧪 + runs-on: ubuntu-latest + needs: build steps: - name: Checkout code uses: actions/checkout@v4 @@ -30,13 +59,16 @@ jobs: - name: Restore dependencies 📂 run: dotnet restore CleanArchitecture.sln - - name: Build 🧱 - run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror + - name: Build solution (reuse build) + run: dotnet build CleanArchitecture.sln --configuration Release --no-restore - - name: Run All Tests 🧪 + - name: Run All Tests 🧪 📊 run: | - mkdir -p tests-results - dotnet test CleanArchitecture.sln --logger "trx;LogFileName=test-results.trx" --collect:"XPlat Code Coverage" --results-directory ./tests-results + mkdir -p tests-results + dotnet test CleanArchitecture.sln \ + --logger "trx;LogFileName=test-results.trx" \ + --collect:"XPlat Code Coverage" \ + --results-directory ./tests-results continue-on-error: true - name: Publish test results 📜 @@ -48,8 +80,8 @@ jobs: - name: Install xmllint run: sudo apt-get update && sudo apt-get install -y libxml2-utils - - name: Show Code Coverage % - id: coverage_output # ← IMPORTANT + - name: Extract Code Coverage % + id: coverage_output if: always() run: | coverage_file=$(find tests-results -name 'coverage.cobertura.xml' | head -n 1) @@ -60,14 +92,9 @@ jobs: exit 0 fi - echo "📄 Fichier de couverture : $coverage_file" - coverage=$(xmllint --xpath "string(/coverage/@line-rate)" "$coverage_file") percentage=$(awk "BEGIN { printf \"%.2f\", $coverage * 100 }") - echo "📊 **Couverture du code : $percentage%**" - - # ⬅️ OUTPUT pour les autres étapes echo "percentage=$percentage" >> $GITHUB_OUTPUT - name: Publish Coverage as Check @@ -81,44 +108,19 @@ jobs: ? context.payload.pull_request.head.sha : context.sha; - const checkName = "Code Coverage"; - - // Vérifier si un check existe déjà - const existing = await github.rest.checks.listForRef({ + await github.rest.checks.create({ owner: context.repo.owner, repo: context.repo.repo, - ref: sha + name: "Code Coverage", + head_sha: sha, + status: "completed", + conclusion: "neutral", + output: { + title: "Code Coverage Result", + summary: `Coverage: **${percentage}%**` + } }); - const prev = existing.data.check_runs.find(c => c.name === checkName); - - if (prev) { - // Mise à jour du check - await github.rest.checks.update({ - owner: context.repo.owner, - repo: context.repo.repo, - check_run_id: prev.id, - conclusion: "neutral", - output: { - title: "Code Coverage Result", - summary: `Coverage: **${percentage}%**` - } - }); - } else { - // Création du check - await github.rest.checks.create({ - owner: context.repo.owner, - repo: context.repo.repo, - name: checkName, - head_sha: sha, - status: "completed", - conclusion: "neutral", - output: { - title: "Code Coverage Result", - summary: `Coverage: **${percentage}%**` - } - }); - } - name: Comment coverage on PR if: always() uses: actions/github-script@v7 @@ -128,14 +130,10 @@ jobs: const percentage = "${{ steps.coverage_output.outputs.percentage }}"; const pr = context.payload.pull_request?.number; - if (!pr) { - console.log("No pull_request context, skipping."); - return; - } + if (!pr) return; const body = `📊 **Code Coverage:** ${percentage}%`; - // Chercher un commentaire existant const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, @@ -147,7 +145,6 @@ jobs: ); if (botComment) { - // Mise à jour du commentaire await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, @@ -155,7 +152,6 @@ jobs: body, }); } else { - // Nouveau commentaire await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, @@ -163,5 +159,3 @@ jobs: body, }); } - - From f3c297f5bb7019cc5103db5b28d45528f33912c4 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:11:19 +0100 Subject: [PATCH 14/17] =?UTF-8?q?plus=20de=20d=C3=A9tails=20dans=20le=20bu?= =?UTF-8?q?ild=20et=20les=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef8faae..98bb12e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,14 +37,13 @@ jobs: - name: Build solution 🧱 id: build_sln run: | - dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror - echo "artifact-path=./CleanArchitecture.sln" >> $GITHUB_OUTPUT + dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror -v:detailed # ---------------------- # 🔹 JOB TEST # ---------------------- test: - name: Run Tests & Coverage 🧪 + name: Run Tests & Coverage 🧪 📊 runs-on: ubuntu-latest needs: build steps: @@ -62,13 +61,14 @@ jobs: - name: Build solution (reuse build) run: dotnet build CleanArchitecture.sln --configuration Release --no-restore - - name: Run All Tests 🧪 📊 + - name: Run All Tests 🧪 run: | mkdir -p tests-results dotnet test CleanArchitecture.sln \ --logger "trx;LogFileName=test-results.trx" \ --collect:"XPlat Code Coverage" \ - --results-directory ./tests-results + --results-directory ./tests-results \ + -v:detailed continue-on-error: true - name: Publish test results 📜 From da09127927fe39e5b8d626cab796b09f513b2910 Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:19:53 +0100 Subject: [PATCH 15/17] corriger la couverture --- .github/workflows/ci.yml | 35 +++++++++++++++-------------------- CleanArchitecture.sln | 1 - 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98bb12e..05e48ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: build and tests 🧱 🧪 +name: Build and Test with Coverage 🧱🧪 on: pull_request: @@ -18,50 +18,46 @@ jobs: # 🔹 JOB BUILD # ---------------------- build: - name: Build 🧱 + name: Build Solution 🧱 runs-on: ubuntu-latest - outputs: - build-artifact: ${{ steps.build_sln.outputs.artifact-path }} steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup .NET 📦 + - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_VERSION }} - - name: Restore dependencies 📂 + - name: Restore dependencies run: dotnet restore CleanArchitecture.sln - - name: Build solution 🧱 - id: build_sln - run: | - dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror -v:detailed + - name: Build solution + run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -v:detailed # ---------------------- # 🔹 JOB TEST # ---------------------- test: - name: Run Tests & Coverage 🧪 📊 + name: Run Tests & Coverage 🧪📊 runs-on: ubuntu-latest - needs: build + needs: build # dépend du build pour la séquence, mais reste dans un job séparé steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup .NET 📦 + - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_VERSION }} - - name: Restore dependencies 📂 + - name: Restore dependencies run: dotnet restore CleanArchitecture.sln - - name: Build solution (reuse build) + - name: Build solution for tests run: dotnet build CleanArchitecture.sln --configuration Release --no-restore - - name: Run All Tests 🧪 + - name: Run all tests with coverage run: | mkdir -p tests-results dotnet test CleanArchitecture.sln \ @@ -71,7 +67,7 @@ jobs: -v:detailed continue-on-error: true - - name: Publish test results 📜 + - name: Publish test results uses: EnricoMi/publish-unit-test-result-action@v2 if: always() with: @@ -80,7 +76,7 @@ jobs: - name: Install xmllint run: sudo apt-get update && sudo apt-get install -y libxml2-utils - - name: Extract Code Coverage % + - name: Extract code coverage % id: coverage_output if: always() run: | @@ -97,7 +93,7 @@ jobs: echo "📊 **Couverture du code : $percentage%**" echo "percentage=$percentage" >> $GITHUB_OUTPUT - - name: Publish Coverage as Check + - name: Publish coverage as check uses: actions/github-script@v7 if: always() with: @@ -129,7 +125,6 @@ jobs: script: | const percentage = "${{ steps.coverage_output.outputs.percentage }}"; const pr = context.payload.pull_request?.number; - if (!pr) return; const body = `📊 **Code Coverage:** ${percentage}%`; diff --git a/CleanArchitecture.sln b/CleanArchitecture.sln index c061b3a..7ac797f 100644 --- a/CleanArchitecture.sln +++ b/CleanArchitecture.sln @@ -6,7 +6,6 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8FC526EA-218B-4615-8410-4E1850611F38}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - .github\workflows\build.yml = .github\workflows\build.yml .github\dependabot.yml = .github\dependabot.yml .github\workflows\ci.yml = .github\workflows\ci.yml Directory.Build.props = Directory.Build.props From 3ad15a77912493bc3f34761eb124e769063f3f0c Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:23:28 +0100 Subject: [PATCH 16/17] unit test ko --- .github/workflows/build.yml | 69 ------------------- .../Users/RegisterUserTests.cs | 2 +- 2 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index e1fb1d3..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,69 +0,0 @@ -# name: Build & Test 🧪 - -# on: -# push: -# branches: [ main ] -# pull_request: -# workflow_dispatch: - -# env: -# DOTNET_VERSION: "9.x" - -# jobs: - -# build_and_test: -# runs-on: ubuntu-latest - -# steps: -# - uses: actions/checkout@v4 - -# - name: Cache NuGet 🗂️ -# uses: actions/cache@v4 -# with: -# path: ~/.nuget/packages -# key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} -# restore-keys: | -# ${{ runner.os }}-nuget- - -# - name: Setup .NET 📦 -# uses: actions/setup-dotnet@v4 -# with: -# dotnet-version: ${{ env.DOTNET_VERSION }} - -# - name: Restore dependencies 📂 -# run: dotnet restore CleanArchitecture.sln - -# - name: Build 🧱 -# run: dotnet build CleanArchitecture.sln --configuration Release --no-restore -warnaserror - -# - name: Run All Tests 🧪 -# run: dotnet test CleanArchitecture.sln --configuration Release --no-build --logger trx --results-directory TestResults - -# - name: Convert TRX to JUnit XML 📜 -# uses: dorny/test-reporter@v2 -# with: -# name: All Tests -# path: TestResults/*.trx -# reporter: dotnet-trx - -# publish: -# runs-on: ubuntu-latest -# needs: build_and_test -# if: github.event_name == 'workflow_dispatch' - -# steps: -# - uses: actions/checkout@v4 - -# - name: Setup .NET 📦 -# uses: actions/setup-dotnet@v4 -# with: -# dotnet-version: ${{ env.DOTNET_VERSION }} - -# - name: Publish 🚀 -# run: dotnet publish CleanArchitecture.sln --configuration Release --output ./published --no-build - -# - name: Upload published artifacts -# uses: actions/upload-artifact@v4 -# with: -# name: published-app -# path: published diff --git a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs index 8da030f..3100dff 100644 --- a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs +++ b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs @@ -98,6 +98,6 @@ public async Task Should_ReturnConflict_WhenUserExists() // Act HttpResponseMessage response = await HttpClient.PostAsJsonAsync("/users/register", request); // Assert - response.StatusCode.Should().Be(HttpStatusCode.Conflict); + response.StatusCode.Should().Be(HttpStatusCode.OK); } } From 9fc93bbbf34e4050392b6e4fca52ff6a96d4f97c Mon Sep 17 00:00:00 2001 From: hichem-hamdi <39518696+hichem-hamdi@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:26:57 +0100 Subject: [PATCH 17/17] fix unit test --- .../Api.FunctionalTests/Users/RegisterUserTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs index 3100dff..8da030f 100644 --- a/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs +++ b/tests/FunctionalTests/Api.FunctionalTests/Users/RegisterUserTests.cs @@ -98,6 +98,6 @@ public async Task Should_ReturnConflict_WhenUserExists() // Act HttpResponseMessage response = await HttpClient.PostAsJsonAsync("/users/register", request); // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); + response.StatusCode.Should().Be(HttpStatusCode.Conflict); } }