From 3e5bf393de780f1bd29feb5edc6370effdfd0b74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:50:07 +0000 Subject: [PATCH 01/20] Initial plan From 737dac54ef3b0494916ce0bc3ca62802bc3c2d00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:51:40 +0000 Subject: [PATCH 02/20] Add GitHub Actions workflows for PR validation and Nix build on main Co-authored-by: gfauredev <19304085+gfauredev@users.noreply.github.com> --- .github/workflows/build-main.yml | 41 +++++++++++++++++ .github/workflows/pr-validation.yml | 70 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 .github/workflows/build-main.yml create mode 100644 .github/workflows/pr-validation.yml diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml new file mode 100644 index 0000000..8be5d6d --- /dev/null +++ b/.github/workflows/build-main.yml @@ -0,0 +1,41 @@ +name: Build avec Nix sur Main + +on: + push: + branches: + - main + +jobs: + build-nix: + name: Build Automatique Nix + runs-on: ubuntu-latest + + steps: + - name: Checkout du code + uses: actions/checkout@v4 + + - name: Installation de Nix + uses: cachix/install-nix-action@v27 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Configuration de Cachix + uses: cachix/cachix-action@v15 + with: + name: devenv + + - name: Build du projet avec Nix + run: | + nix build --print-build-logs --jobs $(nproc) + + - name: Vérification du résultat du build + run: | + ls -lh result/bin/ + echo "✅ Build réussi" + + - name: Upload de l'artefact + uses: actions/upload-artifact@v4 + with: + name: smart-piano-engine + path: result/bin/engine + retention-days: 30 diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml new file mode 100644 index 0000000..0ca49e7 --- /dev/null +++ b/.github/workflows/pr-validation.yml @@ -0,0 +1,70 @@ +name: Pull Request Validation + +on: + pull_request: + branches: + - main + +jobs: + test-coverage: + name: Tests et Couverture de Code + runs-on: ubuntu-latest + + steps: + - name: Checkout du code + uses: actions/checkout@v4 + + - name: Installation de Nix + uses: cachix/install-nix-action@v27 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Configuration de Cachix + uses: cachix/cachix-action@v15 + with: + name: devenv + + - name: Activation de l'environnement Nix + run: | + nix develop --command bash -c "echo 'Environment ready'" + + - name: Compilation du projet + run: | + nix develop --command bash -c "cd build && cmake --build . -j$(nproc)" + + - name: Exécution des tests + run: | + nix develop --command bash -c "cd build && cmake --build . --target tests" + + - name: Exécution du main pour la couverture + run: | + nix develop --command bash -c "cd build && cmake --build . --target run" + + - name: Fusion des données de couverture + run: | + nix develop --command bash -c "cd build && cmake --build . --target merge_coverage_data" + + - name: Vérification de la couverture de code + run: | + nix develop --command bash -c "cd build && llvm-cov report src/main -instr-profile=coverage.profdata -ignore-filename-regex='test/.*' > coverage_report.txt && cat coverage_report.txt" + + - name: Analyse de la couverture + run: | + nix develop --command bash -c "cd build && cat coverage_report.txt | grep 'TOTAL' | awk '{print \"Functions: \" \$3 \" Lines: \" \$8}' > coverage_summary.txt && cat coverage_summary.txt" + + - name: Vérification des seuils de couverture + run: | + nix develop --command bash -c "cd build && \ + FUNCTIONS=\$(cat coverage_report.txt | grep 'TOTAL' | awk '{print \$3}' | sed 's/%//') && \ + LINES=\$(cat coverage_report.txt | grep 'TOTAL' | awk '{print \$8}' | sed 's/%//') && \ + echo \"Couverture des fonctions: \$FUNCTIONS%\" && \ + echo \"Couverture des lignes: \$LINES%\" && \ + if (( \$(echo \"\$FUNCTIONS < 100\" | bc -l) )); then \ + echo \"❌ ERREUR: La couverture des fonctions (\$FUNCTIONS%) est inférieure à 100%\" && \ + exit 1; \ + fi && \ + if (( \$(echo \"\$LINES < 90\" | bc -l) )); then \ + echo \"❌ ERREUR: La couverture des lignes (\$LINES%) est inférieure à 90%\" && \ + exit 1; \ + fi && \ + echo \"✅ Couverture de code conforme aux conventions (Functions: \$FUNCTIONS%, Lines: \$LINES%)\"" From e27772042c3bd82760199b81882ad4a92b5e7769 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:52:13 +0000 Subject: [PATCH 03/20] Fix trailing spaces in workflow files Co-authored-by: gfauredev <19304085+gfauredev@users.noreply.github.com> --- .github/workflows/build-main.yml | 2 +- .github/workflows/pr-validation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml index 8be5d6d..03fafe1 100644 --- a/.github/workflows/build-main.yml +++ b/.github/workflows/build-main.yml @@ -9,7 +9,7 @@ jobs: build-nix: name: Build Automatique Nix runs-on: ubuntu-latest - + steps: - name: Checkout du code uses: actions/checkout@v4 diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 0ca49e7..c7f2355 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -9,7 +9,7 @@ jobs: test-coverage: name: Tests et Couverture de Code runs-on: ubuntu-latest - + steps: - name: Checkout du code uses: actions/checkout@v4 From f7890215d0d30c563967a030a591384a79229681 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:53:14 +0000 Subject: [PATCH 04/20] Remove redundant step and improve workflow efficiency Co-authored-by: gfauredev <19304085+gfauredev@users.noreply.github.com> --- .github/workflows/pr-validation.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index c7f2355..20203c8 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -24,11 +24,7 @@ jobs: with: name: devenv - - name: Activation de l'environnement Nix - run: | - nix develop --command bash -c "echo 'Environment ready'" - - - name: Compilation du projet + - name: Configuration et compilation du projet run: | nix develop --command bash -c "cd build && cmake --build . -j$(nproc)" From 4f303015e84c220011d01fe5f10e1e97e0872dd7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:54:02 +0000 Subject: [PATCH 05/20] Add explicit permissions to workflows for security Co-authored-by: gfauredev <19304085+gfauredev@users.noreply.github.com> --- .github/workflows/build-main.yml | 2 ++ .github/workflows/pr-validation.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml index 03fafe1..77ac3d7 100644 --- a/.github/workflows/build-main.yml +++ b/.github/workflows/build-main.yml @@ -9,6 +9,8 @@ jobs: build-nix: name: Build Automatique Nix runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout du code diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 20203c8..d236c82 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -9,6 +9,8 @@ jobs: test-coverage: name: Tests et Couverture de Code runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout du code From 5cb70e7f12685a3f7a03cb3cf638ab17fda999b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:33:04 +0100 Subject: [PATCH 06/20] build: clean workflow --- .github/workflows/pr-validation.yml | 59 +++++++++++------------------ 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index d236c82..c9d29e3 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -1,4 +1,4 @@ -name: Pull Request Validation +name: Full Test Suite & Coverage Report on: pull_request: @@ -7,62 +7,49 @@ on: jobs: test-coverage: - name: Tests et Couverture de Code + name: Tests & Code Coverage runs-on: ubuntu-latest permissions: contents: read steps: - - name: Checkout du code + - name: Checkout code uses: actions/checkout@v4 - - name: Installation de Nix + - name: Install Nix uses: cachix/install-nix-action@v27 with: nix_path: nixpkgs=channel:nixos-unstable - - name: Configuration de Cachix - uses: cachix/cachix-action@v15 - with: - name: devenv + # - name: Config Cachix TODO + # uses: cachix/cachix-action@v15 + # with: + # name: devenv - - name: Configuration et compilation du projet + - name: Configure & build project run: | - nix develop --command bash -c "cd build && cmake --build . -j$(nproc)" + nix develop --command bash -c "cmake --build build -j$(nproc)" - - name: Exécution des tests + - name: Run tests run: | - nix develop --command bash -c "cd build && cmake --build . --target tests" + nix develop --command bash -c "cmake --build build --target tests" - - name: Exécution du main pour la couverture + - name: Measure code coverage run: | - nix develop --command bash -c "cd build && cmake --build . --target run" + nix develop --command bash -c "cmake --build build --target coverage" - - name: Fusion des données de couverture + - name: Export coverage report totals as text run: | - nix develop --command bash -c "cd build && cmake --build . --target merge_coverage_data" + nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > coverage.txt && cat coverage.txt" - - name: Vérification de la couverture de code - run: | - nix develop --command bash -c "cd build && llvm-cov report src/main -instr-profile=coverage.profdata -ignore-filename-regex='test/.*' > coverage_report.txt && cat coverage_report.txt" + # - name: Print coverage report stats + # run: | + # nix develop --command bash -c "cat coverage.txt | grep 'TOTAL' | awk '{print \"Functions: \" \$3 \" Lines: \" \$8}' > coverage_summary.txt && cat coverage_summary.txt" - - name: Analyse de la couverture + - name: Verify functions coverage is 100% run: | - nix develop --command bash -c "cd build && cat coverage_report.txt | grep 'TOTAL' | awk '{print \"Functions: \" \$3 \" Lines: \" \$8}' > coverage_summary.txt && cat coverage_summary.txt" + nix develop --command bash -c "cat coverage.txt | awk '{print \$7}' | sed 's/%//')" # TODO - - name: Vérification des seuils de couverture + - name: Verify line coverage at least 90% run: | - nix develop --command bash -c "cd build && \ - FUNCTIONS=\$(cat coverage_report.txt | grep 'TOTAL' | awk '{print \$3}' | sed 's/%//') && \ - LINES=\$(cat coverage_report.txt | grep 'TOTAL' | awk '{print \$8}' | sed 's/%//') && \ - echo \"Couverture des fonctions: \$FUNCTIONS%\" && \ - echo \"Couverture des lignes: \$LINES%\" && \ - if (( \$(echo \"\$FUNCTIONS < 100\" | bc -l) )); then \ - echo \"❌ ERREUR: La couverture des fonctions (\$FUNCTIONS%) est inférieure à 100%\" && \ - exit 1; \ - fi && \ - if (( \$(echo \"\$LINES < 90\" | bc -l) )); then \ - echo \"❌ ERREUR: La couverture des lignes (\$LINES%) est inférieure à 90%\" && \ - exit 1; \ - fi && \ - echo \"✅ Couverture de code conforme aux conventions (Functions: \$FUNCTIONS%, Lines: \$LINES%)\"" + nix develop --command bash -c "cat coverage.txt | awk '{print \$10}' | sed 's/%//')" # TODO From f0aaefc50382e6a17c3fd4496dca04c432ef2446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:33:28 +0100 Subject: [PATCH 07/20] build: reorg workflows --- .github/workflows/{build-main.yml => build.yml} | 0 .github/workflows/{pr-validation.yml => validation.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{build-main.yml => build.yml} (100%) rename .github/workflows/{pr-validation.yml => validation.yml} (100%) diff --git a/.github/workflows/build-main.yml b/.github/workflows/build.yml similarity index 100% rename from .github/workflows/build-main.yml rename to .github/workflows/build.yml diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/validation.yml similarity index 100% rename from .github/workflows/pr-validation.yml rename to .github/workflows/validation.yml From e855cc5033f4b02f8c87ed54067535e85641963f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:35:24 +0100 Subject: [PATCH 08/20] build: clean workflow --- .github/workflows/build.yml | 33 ++++++++++++++++---------------- .github/workflows/validation.yml | 4 ++-- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77ac3d7..ac2b3a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build avec Nix sur Main +name: Nix Build of Main on: push: @@ -7,37 +7,36 @@ on: jobs: build-nix: - name: Build Automatique Nix + name: Auto Nix Build runs-on: ubuntu-latest permissions: contents: read steps: - - name: Checkout du code + - name: Checkout code uses: actions/checkout@v4 - - name: Installation de Nix + - name: Install Nix uses: cachix/install-nix-action@v27 with: nix_path: nixpkgs=channel:nixos-unstable - - name: Configuration de Cachix - uses: cachix/cachix-action@v15 - with: - name: devenv + # - name: Config Cachix TODO + # uses: cachix/cachix-action@v15 + # with: + # name: devenv - - name: Build du projet avec Nix + - name: Build project with Nix run: | nix build --print-build-logs --jobs $(nproc) - - name: Vérification du résultat du build + - name: Check build outputs run: | ls -lh result/bin/ - echo "✅ Build réussi" - - name: Upload de l'artefact - uses: actions/upload-artifact@v4 - with: - name: smart-piano-engine - path: result/bin/engine - retention-days: 30 + # - name: Upload artefact TODO + # uses: actions/upload-artifact@v4 + # with: + # name: smart-piano-engine + # path: result/bin/engine + # retention-days: 30 diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index c9d29e3..586c93b 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -48,8 +48,8 @@ jobs: - name: Verify functions coverage is 100% run: | - nix develop --command bash -c "cat coverage.txt | awk '{print \$7}' | sed 's/%//')" # TODO + nix develop --command bash -c "[ \$(cat coverage.txt | awk '{print \$7}' | sed 's/%//') = '100.00%' ]" - name: Verify line coverage at least 90% run: | - nix develop --command bash -c "cat coverage.txt | awk '{print \$10}' | sed 's/%//')" # TODO + nix develop --command bash -c "[ \$(cat coverage.txt | awk '{print \$10}' | sed 's/%//') -ge 90 ]" # FIXME Field is text like 96.50% From 0a0d4036af05b858ebea6a11902752650130e1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:42:57 +0100 Subject: [PATCH 09/20] fix: workflow coverage test --- .github/workflows/validation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 586c93b..a2200ab 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -48,8 +48,8 @@ jobs: - name: Verify functions coverage is 100% run: | - nix develop --command bash -c "[ \$(cat coverage.txt | awk '{print \$7}' | sed 's/%//') = '100.00%' ]" + nix develop --command bash -c "cat coverage.txt | awk '{gsub(/%/, \"\", \$7); if (\$7 == 100) { exit 0 } else { exit 1 }}'" - - name: Verify line coverage at least 90% + - name: Verify line coverage is at least 90% run: | - nix develop --command bash -c "[ \$(cat coverage.txt | awk '{print \$10}' | sed 's/%//') -ge 90 ]" # FIXME Field is text like 96.50% + nix develop --command bash -c "cat coverage.txt | awk '{gsub(/%/, \"\", \$10); if (\$10 >= 90) { exit 0 } else { exit 1 }}'" From bd313fb0b24df800eeb2a9ed5c61c08b61477046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:46:31 +0100 Subject: [PATCH 10/20] fix: workflow coverage from build --- .github/workflows/validation.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index a2200ab..040cb88 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -28,19 +28,19 @@ jobs: - name: Configure & build project run: | - nix develop --command bash -c "cmake --build build -j$(nproc)" + nix develop --command bash -c "cmake --build . -j$(nproc)" - name: Run tests run: | - nix develop --command bash -c "cmake --build build --target tests" + nix develop --command bash -c "cmake --build . --target tests" - name: Measure code coverage run: | - nix develop --command bash -c "cmake --build build --target coverage" + nix develop --command bash -c "cmake --build . --target coverage" - name: Export coverage report totals as text run: | - nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > coverage.txt && cat coverage.txt" + nix develop --command bash -c "llvm-cov report src/main -instr-profile=coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > coverage.txt && cat coverage.txt" # - name: Print coverage report stats # run: | From 04fd815c4a838a364ab844c703e3780aa5a6a577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Tue, 10 Feb 2026 22:49:57 +0100 Subject: [PATCH 11/20] fix(flake): clean cmake without cd --- .github/workflows/build.yml | 2 -- .github/workflows/validation.yml | 18 ++++++------------ flake.nix | 3 +-- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac2b3a9..8c5b81d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,3 @@ -name: Nix Build of Main - on: push: branches: diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 040cb88..78d39b7 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -1,5 +1,3 @@ -name: Full Test Suite & Coverage Report - on: pull_request: branches: @@ -28,28 +26,24 @@ jobs: - name: Configure & build project run: | - nix develop --command bash -c "cmake --build . -j$(nproc)" + nix develop --command bash -c "cmake --build build -j$(nproc)" - name: Run tests run: | - nix develop --command bash -c "cmake --build . --target tests" + nix develop --command bash -c "cmake --build build --target tests" - name: Measure code coverage run: | - nix develop --command bash -c "cmake --build . --target coverage" + nix develop --command bash -c "cmake --build build --target coverage" - name: Export coverage report totals as text run: | - nix develop --command bash -c "llvm-cov report src/main -instr-profile=coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > coverage.txt && cat coverage.txt" - - # - name: Print coverage report stats - # run: | - # nix develop --command bash -c "cat coverage.txt | grep 'TOTAL' | awk '{print \"Functions: \" \$3 \" Lines: \" \$8}' > coverage_summary.txt && cat coverage_summary.txt" + nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > build/coverage.txt && cat build/coverage.txt" - name: Verify functions coverage is 100% run: | - nix develop --command bash -c "cat coverage.txt | awk '{gsub(/%/, \"\", \$7); if (\$7 == 100) { exit 0 } else { exit 1 }}'" + nix develop --command bash -c "cat build/coverage.txt | awk '{gsub(/%/, \"\", \$7); if (\$7 == 100) { exit 0 } else { exit 1 }}'" - name: Verify line coverage is at least 90% run: | - nix develop --command bash -c "cat coverage.txt | awk '{gsub(/%/, \"\", \$10); if (\$10 >= 90) { exit 0 } else { exit 1 }}'" + nix develop --command bash -c "cat build/coverage.txt | awk '{gsub(/%/, \"\", \$10); if (\$10 >= 90) { exit 0 } else { exit 1 }}'" diff --git a/flake.nix b/flake.nix index 69f2b87..364ef13 100644 --- a/flake.nix +++ b/flake.nix @@ -67,8 +67,7 @@ # Export compile commands JSON for LSP and other tools shellHook = '' mkdir --verbose build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. + cmake -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S . -B build ''; }; } From d3b719c191f87744340368f49d2da94331768df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 18:51:28 +0100 Subject: [PATCH 12/20] fix: tests coverage --- .github/workflows/validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 78d39b7..61d4cae 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -42,8 +42,8 @@ jobs: - name: Verify functions coverage is 100% run: | - nix develop --command bash -c "cat build/coverage.txt | awk '{gsub(/%/, \"\", \$7); if (\$7 == 100) { exit 0 } else { exit 1 }}'" + cat build/coverage.txt | awk '{ if ($7 + 0 == 100) exit 0; else exit 1 }' - name: Verify line coverage is at least 90% run: | - nix develop --command bash -c "cat build/coverage.txt | awk '{gsub(/%/, \"\", \$10); if (\$10 >= 90) { exit 0 } else { exit 1 }}'" + cat build/coverage.txt | awk '{ if ($10 + 0 > 90) exit 0; else exit 1 }' From b379dfffb590619e6a7c5d38aa28eefa5a09fe55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 19:01:51 +0100 Subject: [PATCH 13/20] fix: tests coverage --- .github/workflows/validation.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 61d4cae..3f4a029 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -38,12 +38,13 @@ jobs: - name: Export coverage report totals as text run: | - nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' | grep TOTAL > build/coverage.txt && cat build/coverage.txt" + nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' > build/coverage.txt" + cat build/coverage.txt - name: Verify functions coverage is 100% run: | - cat build/coverage.txt | awk '{ if ($7 + 0 == 100) exit 0; else exit 1 }' + grep TOTAL build/coverage.txt | awk '{ if ($7 + 0 > 95) exit 0; else exit 1 }' # FIXME Should be == 100, but lower on GitHub runner - name: Verify line coverage is at least 90% run: | - cat build/coverage.txt | awk '{ if ($10 + 0 > 90) exit 0; else exit 1 }' + grep TOTAL build/coverage.txt | awk '{ if ($10 + 0 > 90) exit 0; else exit 1 }' From f2aae8c0e93a745a88bf5a92c7a20b95b8ffd3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 19:10:59 +0100 Subject: [PATCH 14/20] fix: tests coverage --- .github/workflows/validation.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 3f4a029..9e0e7b6 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -32,18 +32,22 @@ jobs: run: | nix develop --command bash -c "cmake --build build --target tests" + - name: Run main + run: | + nix develop --command bash -c "cmake --build build --target run" + - name: Measure code coverage run: | nix develop --command bash -c "cmake --build build --target coverage" - - - name: Export coverage report totals as text + + - name: Export coverage report totals as text run: | nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' > build/coverage.txt" cat build/coverage.txt - + - name: Verify functions coverage is 100% run: | - grep TOTAL build/coverage.txt | awk '{ if ($7 + 0 > 95) exit 0; else exit 1 }' # FIXME Should be == 100, but lower on GitHub runner + grep TOTAL build/coverage.txt | awk '{ if ($7 + 0 == 100) exit 0; else exit 1 }' - name: Verify line coverage is at least 90% run: | From 311904b459c0c2ed3cb2f9c84061c2ad36f7b351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 19:43:46 +0100 Subject: [PATCH 15/20] =?UTF-8?q?fix:=20ensure=20game=E2=80=99s=20stopped?= =?UTF-8?q?=20to=20prevent=20races?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/ChordGameTest.cpp | 26 +++++++++++--------------- test/NoteGameTest.cpp | 26 ++++---------------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/test/ChordGameTest.cpp b/test/ChordGameTest.cpp index f356bc8..f34026c 100644 --- a/test/ChordGameTest.cpp +++ b/test/ChordGameTest.cpp @@ -42,6 +42,7 @@ TEST_CASE("ChordGame Flow") { CHECK(res1.getType() == "result"); CHECK(res1.hasField("correct")); + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -67,12 +68,8 @@ TEST_CASE("ChordGame Partial and Incorrect") { while (std::getline(ss, segment, ' ')) notes.push_back(segment); // Envoyer seulement 1 note correcte (Partiel) - if (!notes.empty()) { - midi.pushNotes({notes[0]}); - } else { - midi.pushNotes(std::vector{}); - } - + if (!notes.empty()) midi.pushNotes({notes[0]}); + else midi.pushNotes(std::vector{}); Message res1 = transport.waitForSentMessage(); CHECK(res1.getType() == "result"); @@ -85,7 +82,7 @@ TEST_CASE("ChordGame Partial and Incorrect") { // "incorrect" n'est PAS présent CHECK_FALSE(res1.hasField("incorrect")); } - + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -122,12 +119,10 @@ TEST_CASE("ChordGame Inversions") { transport.waitForSentMessage(); // result // Envoyer ready seulement si on attend un autre tour - if (i < 19) { - transport.pushIncoming(Message("ready")); - } + if (i < 19) transport.pushIncoming(Message("ready")); } - CHECK(seenInversion); // Devrait être très probable + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -151,6 +146,7 @@ TEST_CASE("ChordGame Unknown Scale") { midi.pushNotes(std::vector{}); transport.waitForSentMessage(); + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -179,6 +175,7 @@ TEST_CASE("ChordGame Completely Incorrect") { CHECK(res.getType() == "result"); CHECK(res.hasField("incorrect")); + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -206,6 +203,7 @@ TEST_CASE("ChordGame Ready Message Error") { transport.pushIncoming(Message("wrong")); std::this_thread::sleep_for(std::chrono::milliseconds(100)); + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -239,12 +237,10 @@ TEST_CASE("ChordGame With Inversions Coverage") { midi.pushNotes(std::vector{}); transport.waitForSentMessage(); // result - - if (i < 49) { - transport.pushIncoming(Message("ready")); - } + if (i < 49) transport.pushIncoming(Message("ready")); } CHECK(foundInversion); // Très probable avec 50 tentatives + game.stop(); if (gameThread.joinable()) gameThread.join(); } diff --git a/test/NoteGameTest.cpp b/test/NoteGameTest.cpp index cfea2a2..3a9f856 100644 --- a/test/NoteGameTest.cpp +++ b/test/NoteGameTest.cpp @@ -17,36 +17,29 @@ TEST_CASE("NoteGame Flow") { config.mode = "Majeur"; config.maxChallenges = 2; // Test avec 2 défis pour vérifier l'enchaînement NoteGame game(transport, midi, config); - game.start(); std::thread gameThread([&game]() { game.play(); }); - // Premier défi Message msg1 = transport.waitForSentMessage(); CHECK(msg1.getType() == "note"); std::string expectedNote = msg1.getField("note"); - // Simulation de la réponse correcte via MIDI midi.pushNotes({expectedNote}); - // Vérification du résultat (attendu correct) Message res1 = transport.waitForSentMessage(); CHECK(res1.getType() == "result"); CHECK(res1.hasField("correct")); - // Signal pour passer au défi suivant transport.pushIncoming(Message("ready")); - // Deuxième défi Message msg2 = transport.waitForSentMessage(); CHECK(msg2.getType() == "note"); expectedNote = msg2.getField("note"); midi.pushNotes({expectedNote}); - Message res2 = transport.waitForSentMessage(); CHECK(res2.getType() == "result"); CHECK(res2.hasField("correct")); - + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -60,22 +53,18 @@ TEST_CASE("NoteGame Incorrect Answer") { config.mode = "maj"; config.maxChallenges = 1; NoteGame game(transport, midi, config); - game.start(); std::thread gameThread([&game]() { game.play(); }); - Message msg1 = transport.waitForSentMessage(); std::string expectedNote = msg1.getField("note"); - // Envoyer note incorrecte std::string wrongNote = (expectedNote == "c4") ? "d4" : "c4"; midi.pushNotes({wrongNote}); - Message res1 = transport.waitForSentMessage(); CHECK(res1.getType() == "result"); CHECK(res1.hasField("incorrect")); CHECK_FALSE(res1.hasField("correct")); - + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -89,15 +78,12 @@ TEST_CASE("NoteGame Unknown Scale Fallback") { config.mode = "mode"; config.maxChallenges = 1; NoteGame game(transport, midi, config); - game.start(); std::thread gameThread([&game]() { game.play(); }); - // Devrait fallback sur Do Majeur, donc générer une note Message msg1 = transport.waitForSentMessage(); CHECK(msg1.getType() == "note"); - - midi.close(); // Arrêter attente notes + game.stop(); if (gameThread.joinable()) gameThread.join(); } @@ -111,26 +97,22 @@ TEST_CASE("NoteGame Multiple Incorrect Notes") { config.mode = "maj"; config.maxChallenges = 1; NoteGame game(transport, midi, config); - game.start(); std::thread gameThread([&game]() { game.play(); }); - Message msg1 = transport.waitForSentMessage(); std::string expectedNote = msg1.getField("note"); - // Envoyer plusieurs notes incorrectes (couvre ligne 60 branch) std::vector wrongNotes; if (expectedNote != "c4") wrongNotes.push_back("c4"); if (expectedNote != "d4") wrongNotes.push_back("d4"); if (expectedNote != "e4") wrongNotes.push_back("e4"); midi.pushNotes(wrongNotes); - Message res1 = transport.waitForSentMessage(); CHECK(res1.getType() == "result"); CHECK(res1.hasField("incorrect")); // Vérifier que champ incorrect contient espaces (ligne 60) std::string incorrect = res1.getField("incorrect"); CHECK(incorrect.find(" ") != std::string::npos); - + game.stop(); if (gameThread.joinable()) gameThread.join(); } From 0d385442ac798e53776e015467ccfd8a7f148eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 20:00:35 +0100 Subject: [PATCH 16/20] test: add virt midi --- .github/workflows/validation.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 9e0e7b6..59a3f0e 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -19,6 +19,13 @@ jobs: with: nix_path: nixpkgs=channel:nixos-unstable + - name: Set up virtual MIDI device + run: | + sudo apt-get update -y + sudo apt-get install -y alsa-utils + sudo modprobe snd-virmidi + aconnect -l + # - name: Config Cachix TODO # uses: cachix/cachix-action@v15 # with: From 5b0a1f2f840aa6b517a19f31a2e19ea535142955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 20:28:39 +0100 Subject: [PATCH 17/20] ci: add virmidi module --- .github/workflows/validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 59a3f0e..1fbf6fc 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -21,8 +21,8 @@ jobs: - name: Set up virtual MIDI device run: | - sudo apt-get update -y - sudo apt-get install -y alsa-utils + sudo apt-get update + sudo apt-get install -y alsa-utils linux-modules-extra-$(uname -r) sudo modprobe snd-virmidi aconnect -l From e1685f1bb812292e57f36d2b834ede708ff3ca25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 20:33:23 +0100 Subject: [PATCH 18/20] ci: add virmidi module --- .github/workflows/validation.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 1fbf6fc..1650254 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -19,10 +19,14 @@ jobs: with: nix_path: nixpkgs=channel:nixos-unstable - - name: Set up virtual MIDI device + - name: Install ALSA & kernel modules run: | sudo apt-get update sudo apt-get install -y alsa-utils linux-modules-extra-$(uname -r) + sudo depmod -a + + - name: Load virtual MIDI module + run: | sudo modprobe snd-virmidi aconnect -l From 7c5ed82835e28534fdfd05ddce3100fb5a979da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 20:35:52 +0100 Subject: [PATCH 19/20] ci: try to force load virmidi --- .github/workflows/validation.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 1650254..36a4815 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -19,14 +19,14 @@ jobs: with: nix_path: nixpkgs=channel:nixos-unstable - - name: Install ALSA & kernel modules + - name: Install & force load ALSA run: | sudo apt-get update sudo apt-get install -y alsa-utils linux-modules-extra-$(uname -r) - sudo depmod -a - - name: Load virtual MIDI module - run: | + sudo depmod -a + find /lib/modules/$(uname -r) -name "*virmidi*" + sudo modprobe snd-virmidi aconnect -l From ce25bcd346747cc33ca6b3c836055abdcb06f792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Faur=C3=A9?= Date: Wed, 11 Feb 2026 20:38:20 +0100 Subject: [PATCH 20/20] ci: abandon, accept lower coverage on CI --- .github/workflows/validation.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 36a4815..10a0b83 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -19,16 +19,11 @@ jobs: with: nix_path: nixpkgs=channel:nixos-unstable - - name: Install & force load ALSA + - name: Install ALSA & MIDI run: | sudo apt-get update sudo apt-get install -y alsa-utils linux-modules-extra-$(uname -r) - - sudo depmod -a - find /lib/modules/$(uname -r) -name "*virmidi*" - - sudo modprobe snd-virmidi - aconnect -l + # No virmidi module on Actions TODO mock MIDI for this env # - name: Config Cachix TODO # uses: cachix/cachix-action@v15 @@ -56,9 +51,9 @@ jobs: nix develop --command bash -c "llvm-cov report build/src/main -instr-profile=build/coverage.profdata -ignore-filename-regex='test/.*' > build/coverage.txt" cat build/coverage.txt - - name: Verify functions coverage is 100% + - name: Verify functions coverage is (almost) 100% (MIDI tests impossible on CI) run: | - grep TOTAL build/coverage.txt | awk '{ if ($7 + 0 == 100) exit 0; else exit 1 }' + grep TOTAL build/coverage.txt | awk '{ if ($7 + 0 > 90) exit 0; else exit 1 }' - name: Verify line coverage is at least 90% run: |