Aller au contenu principal

Configuration des Quality Gates C++ dans Cursor : 3 vérifications automatisées

Cursor C++ Quality Gate

Le développement C++ exige un contrôle qualité rigoureux. Ce guide vous montre comment configurer trois vérifications automatisées dans Cursor qui s'exécutent avant chaque commit : les builds cibles, les builds sanitizer et l'analyse statique avec cppcheck. Associées à un hook Git pre-push, ces vérifications garantissent que votre code est toujours prêt pour la production.

Les trois vérifications

Vérification 1 : Build cible

Compile votre code avec les mêmes paramètres que votre environnement de déploiement.

Vérification 2 : Build sanitizer

Exécute AddressSanitizer (ASan) et UndefinedBehaviorSanitizer (UBSan) pour détecter les erreurs mémoire et les comportements indéfinis.

Vérification 3 : Analyse statique

Utilise cppcheck pour trouver des bugs, des violations de style et des problèmes potentiels sans exécuter le code.

Prérequis

Installez les outils requis :

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y build-essential cmake cppcheck

# macOS
brew install cmake cppcheck

# Windows (via MSYS2 ou WSL)
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-cppcheck

Structure du projet

my-cpp-project/
├── src/
│ ├── main.cpp
│ └── utils.cpp
├── include/
│ └── utils.h
├── tests/
│ └── test_main.cpp
├── CMakeLists.txt
├── .cursor/
│ └── quality-gate.sh
└── .git/hooks/
└── pre-push

Étape 1 : Configuration CMake

Créez CMakeLists.txt avec les profils de build :

cmake_minimum_required(VERSION 3.14)
project(MyProject CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Fichiers source
add_executable(myapp
src/main.cpp
src/utils.cpp
)

target_include_directories(myapp PRIVATE include)

# Profil de build cible (similaire à la production)
add_library(target_profile INTERFACE)
target_compile_options(target_profile INTERFACE
-O2
-DNDEBUG
-Wall
-Wextra
-Werror
)

# Profil de build sanitizer
add_library(sanitizer_profile INTERFACE)
target_compile_options(sanitizer_profile INTERFACE
-O1
-g
-fsanitize=address,undefined
-fno-omit-frame-pointer
)
target_link_options(sanitizer_profile INTERFACE
-fsanitize=address,undefined
)

# Appliquer les profils
option(USE_SANITIZER "Build with sanitizers" OFF)
if(USE_SANITIZER)
target_link_libraries(myapp sanitizer_profile)
else()
target_link_libraries(myapp target_profile)
endif()

# Tests
enable_testing()
add_executable(myapp_tests tests/test_main.cpp)
target_link_libraries(myapp_tests target_profile)
add_test(NAME unit_tests COMMAND myapp_tests)

Étape 2 : Script de Quality Gate

Créez .cursor/quality-gate.sh :

#!/bin/bash
set -e

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BUILD_DIR="$PROJECT_ROOT/build"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # Pas de couleur

echo "=========================================="
echo " Cursor C++ Quality Gate"
echo "=========================================="

# Nettoyer le répertoire de build
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"

# Vérification 1 : Build cible
echo -e "\n${YELLOW}[1/3] Build cible${NC}"
echo "Compilation avec les paramètres de production..."
mkdir -p "$BUILD_DIR/target"
cd "$BUILD_DIR/target"
cmake ../.. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
echo -e "${GREEN}Build cible : RÉUSSI${NC}"

# Exécuter les tests
echo "Exécution des tests..."
ctest --output-on-failure
echo -e "${GREEN}Tests : RÉUSSI${NC}"

# Vérification 2 : Build sanitizer
echo -e "\n${YELLOW}[2/3] Build sanitizer${NC}"
echo "Compilation avec AddressSanitizer et UBSan..."
mkdir -p "$BUILD_DIR/sanitizer"
cd "$BUILD_DIR/sanitizer"
cmake ../.. -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER=ON
make -j$(nproc)

echo "Exécution avec les sanitizers..."
./myapp || {
echo -e "${RED}Le sanitizer a détecté des erreurs !${NC}"
exit 1
}
echo -e "${GREEN}Build sanitizer : RÉUSSI${NC}"

# Vérification 3 : Analyse statique
echo -e "\n${YELLOW}[3/3] Analyse statique (cppcheck)${NC}"
cd "$PROJECT_ROOT"

cppcheck \
--enable=all \
--suppress=missingIncludeSystem \
--error-exitcode=1 \
--inline-suppr \
--check-config \
-I include \
src/ \
tests/ \
2>&1 | tee "$BUILD_DIR/cppcheck-report.txt"

echo -e "${GREEN}Analyse statique : RÉUSSI${NC}"

# Résumé
echo -e "\n=========================================="
echo -e "${GREEN}Tous les quality gates ont réussi !${NC}"
echo "=========================================="
echo "Artefacts de build : $BUILD_DIR/"
echo "Rapport : $BUILD_DIR/cppcheck-report.txt"

Rendez-le exécutable :

chmod +x .cursor/quality-gate.sh

Étape 3 : Hook Git Pre-Push

Créez .git/hooks/pre-push :

#!/bin/bash

echo "Exécution du quality gate avant le push..."

if [ -f ".cursor/quality-gate.sh" ]; then
bash .cursor/quality-gate.sh
exit $?
else
echo "Attention : Script de quality gate introuvable"
exit 0
fi

Rendez-le exécutable :

chmod +x .git/hooks/pre-push

Étape 4 : Intégration avec Cursor

Ajouter aux tâches Cursor

Créez .vscode/tasks.json (Cursor utilise le système de tâches VS Code) :

{
"version": "2.0.0",
"tasks": [
{
"label": "C++ Quality Gate",
"type": "shell",
"command": "bash",
"args": [".cursor/quality-gate.sh"],
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": ["$gcc"]
},
{
"label": "Quick Build",
"type": "shell",
"command": "cmake",
"args": ["--build", "build/target", "--parallel"],
"group": "build"
},
{
"label": "Run Sanitizer Build",
"type": "shell",
"command": "bash",
"args": ["-c", "mkdir -p build/sanitizer && cd build/sanitizer && cmake ../.. -DUSE_SANITIZER=ON && make -j$(nproc) && ./myapp"],
"group": "test"
}
]
}

Raccourcis clavier

Ajoutez à .vscode/keybindings.json :

[
{
"key": "ctrl+shift+q",
"command": "workbench.action.tasks.runTask",
"args": "C++ Quality Gate"
}
]

Comprendre la sortie des sanitizers

AddressSanitizer (ASan)

Détecte :

  • Utilisation après libération
  • Dépassement de tampon sur le tas
  • Dépassement de tampon sur la pile
  • Dépassement de tampon global
  • Utilisation après retour
  • Utilisation après sortie de portée
  • Double libération
  • Fuites mémoire

Exemple de sortie :

==12345==ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 4 at 0x602000000014 thread T0
#0 0x5555555551a9 in main src/main.cpp:15

UndefinedBehaviorSanitizer (UBSan)

Détecte :

  • Dépassement d'entier signé
  • Division par zéro
  • Déréférencement de pointeur nul
  • Accès à un pointeur non aligné
  • Opérations de décalage invalides

Exemple de sortie :

src/utils.cpp:42:15: runtime error: signed integer overflow

Personnaliser cppcheck

Commentaires de suppression

Dans votre code :

// cppcheck-suppress unusedFunction
void debugHelper() {
// Ceci n'est utilisé que dans les builds de debug
}

// cppcheck-suppress knownConditionTrueFalse
if (x == x) { // Vérification intentionnelle de NaN
// gérer NaN
}

Fichier de configuration

Créez cppcheck-suppressions.txt :

unusedFunction:*test*
missingIncludeSystem
unmatchedSuppression

Mettez à jour le script :

cppcheck \
--enable=all \
--suppressions-list=cppcheck-suppressions.txt \
--error-exitcode=1 \
src/ tests/

Intégration CI/CD

GitHub Actions

name: C++ Quality Gate

on: [push, pull_request]

jobs:
quality-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake cppcheck

- name: Run Quality Gate
run: bash .cursor/quality-gate.sh

Dépannage

ProblèmeSolution
Build sanitizer trop lentUtilisez -O1 au lieu de -O0 pour des builds plus rapides
Faux positifs cppcheckAjoutez des commentaires de suppression ou un fichier de config
Hook ne s'exécute pasAssurez-vous que .git/hooks/pre-push est exécutable
Mémoire insuffisante pendant le buildRéduisez les jobs parallèles : make -j2 au lieu de -j$(nproc)

Référence rapide

# Exécuter le quality gate complet
bash .cursor/quality-gate.sh

# Build cible rapide uniquement
mkdir -p build && cd build && cmake .. && make -j$(nproc)

# Exécuter avec les sanitizers
mkdir -p build-san && cd build-san && cmake .. -DUSE_SANITIZER=ON && make -j$(nproc) && ./myapp

# Exécuter cppcheck uniquement
cppcheck --enable=all --error-exitcode=1 src/

Ressources connexes