Boucle de vérification Django
À exécuter avant les PRs, après des modifications majeures, et avant le déploiement pour garantir la qualité et la sécurité de l'application Django.
Quand l'activer
- Avant d'ouvrir une pull request pour un projet Django
- Après des modifications majeures de modèles, des mises à jour de migrations ou des mises à niveau de dépendances
- Vérification pré-déploiement pour la staging ou la production
- Exécution du pipeline complet : environnement → lint → test → sécurité → état de préparation au déploiement
- Validation de la sécurité des migrations et de la couverture de tests
Phase 1 : Vérification de l'environnement
# Vérifier la version de Python
python --version # Doit correspondre aux exigences du projet
# Vérifier l'environnement virtuel
which python
pip list --outdated
# Vérifier les variables d'environnement
python -c "import os; import environ; print('DJANGO_SECRET_KEY définie' if os.environ.get('DJANGO_SECRET_KEY') else 'MANQUANTE : DJANGO_SECRET_KEY')"
Si l'environnement est mal configuré, arrêtez-vous et corrigez-le.
Phase 2 : Qualité du code et formatage
# Vérification de typage
mypy . --config-file pyproject.toml
# Linting avec ruff
ruff check . --fix
# Formatage avec black
black . --check
black . # Correction automatique
# Tri des imports
isort . --check-only
isort . # Correction automatique
# Vérifications spécifiques à Django
python manage.py check --deploy
Problèmes courants :
- Indications de type manquantes sur les fonctions publiques
- Violations de formatage PEP 8
- Imports non triés
- Paramètres de débogage laissés dans la configuration de production
Phase 3 : Migrations
# Vérifier les migrations non appliquées
python manage.py showmigrations
# Créer les migrations manquantes
python manage.py makemigrations --check
# Simulation de l'application des migrations
python manage.py migrate --plan
# Appliquer les migrations (environnement de test)
python manage.py migrate
# Vérifier les conflits de migrations
python manage.py makemigrations --merge # Seulement en cas de conflits
Rapport :
- Nombre de migrations en attente
- Éventuels conflits de migrations
- Modifications de modèles sans migrations
Phase 4 : Tests + Couverture
# Exécuter tous les tests avec pytest
pytest --cov=apps --cov-report=html --cov-report=term-missing --reuse-db
# Exécuter les tests d'une application spécifique
pytest apps/users/tests/
# Exécuter avec des marqueurs
pytest -m "not slow" # Ignorer les tests lents
pytest -m integration # Uniquement les tests d'intégration
# Rapport de couverture
open htmlcov/index.html
Rapport :
- Tests totaux : X réussis, Y échoués, Z ignorés
- Couverture globale : XX%
- Répartition de la couverture par application
Objectifs de couverture :
| Composant | Objectif |
|---|---|
| Modèles | 90%+ |
| Sérialiseurs | 85%+ |
| Vues | 80%+ |
| Services | 90%+ |
| Global | 80%+ |
Phase 5 : Analyse de sécurité
# Vulnérabilités des dépendances
pip-audit
safety check --full-report
# Vérifications de sécurité Django
python manage.py check --deploy
# Linter de sécurité Bandit
bandit -r . -f json -o bandit-report.json
# Recherche de secrets (si gitleaks est installé)
gitleaks detect --source . --verbose
# Vérification des variables d'environnement
python -c "from django.core.exceptions import ImproperlyConfigured; from django.conf import settings; settings.DEBUG"
Rapport :
- Dépendances vulnérables trouvées
- Problèmes de configuration de sécurité
- Secrets codés en dur détectés
- Statut du mode DEBUG (doit être False en production)
Phase 6 : Commandes de gestion Django
# Vérifier les problèmes de modèles
python manage.py check
# Collecter les fichiers statiques
python manage.py collectstatic --noinput --clear
# Créer un superutilisateur (si nécessaire pour les tests)
echo "from apps.users.models import User; User.objects.create_superuser('[email protected]', 'admin')" | python manage.py shell
# Intégrité de la base de données
python manage.py check --database default
# Vérification du cache (si Redis est utilisé)
python -c "from django.core.cache import cache; cache.set('test', 'value', 10); print(cache.get('test'))"
Phase 7 : Contrôles de performance
# Sortie de la barre d'outils de débogage Django (vérifier les requêtes N+1)
# Exécuter en mode dev avec DEBUG=True et accéder à une page
# Rechercher les requêtes en double dans le panneau SQL
# Analyse du nombre de requêtes
django-admin debugsqlshell # Si django-debug-sqlshell est installé
# Vérifier les index manquants
python manage.py shell << EOF
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT table_name, index_name FROM information_schema.statistics WHERE table_schema = 'public'")
print(cursor.fetchall())
EOF
Rapport :
- Nombre de requêtes par page (doit être < 50 pour les pages typiques)
- Index de base de données manquants
- Requêtes en double détectées
Phase 8 : Assets statiques
# Vérifier les dépendances npm (si npm est utilisé)
npm audit
npm audit fix
# Build des fichiers statiques (si webpack/vite est utilisé)
npm run build
# Vérifier les fichiers statiques
ls -la staticfiles/
python manage.py findstatic css/style.css
Phase 9 : Revue de configuration
# Exécuter dans le shell Python pour vérifier les paramètres
python manage.py shell << EOF
from django.conf import settings
import os
# Vérifications critiques
verifications = {
'DEBUG est False': not settings.DEBUG,
'SECRET_KEY définie': bool(settings.SECRET_KEY and len(settings.SECRET_KEY) > 30),
'ALLOWED_HOSTS renseigné': len(settings.ALLOWED_HOSTS) > 0,
'HTTPS activé': getattr(settings, 'SECURE_SSL_REDIRECT', False),
'HSTS activé': getattr(settings, 'SECURE_HSTS_SECONDS', 0) > 0,
'Base de données configurée': settings.DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3',
}
for verification, resultat in verifications.items():
statut = '✓' if resultat else '✗'
print(f"{statut} {verification}")
EOF
Phase 10 : Configuration de la journalisation
# Tester la sortie de journalisation
python manage.py shell << EOF
import logging
logger = logging.getLogger('django')
logger.warning('Message de test d\'avertissement')
logger.error('Message de test d\'erreur')
EOF
# Vérifier les fichiers de logs (si configurés)
tail -f /var/log/django/django.log
Phase 11 : Documentation de l'API (si DRF)
# Générer le schéma
python manage.py generateschema --format openapi-json > schema.json
# Valider le schéma
# Vérifier si schema.json est un JSON valide
python -c "import json; json.load(open('schema.json'))"
# Accéder à l'interface Swagger (si drf-yasg est utilisé)
# Visiter http://localhost:8000/swagger/ dans le navigateur
Phase 12 : Revue des différences
# Afficher les statistiques des différences
git diff --stat
# Afficher les modifications réelles
git diff
# Afficher les fichiers modifiés
git diff --name-only
# Rechercher les problèmes courants
git diff | grep -i "todo\|fixme\|hack\|xxx"
git diff | grep "print(" # Instructions de débogage
git diff | grep "DEBUG = True" # Mode débogage
git diff | grep "import pdb" # Débogueur
Liste de contrôle :
- Absence d'instructions de débogage (print, pdb, breakpoint())
- Absence de commentaires TODO/FIXME dans le code critique
- Absence de secrets ou d'identifiants codés en dur
- Migrations de base de données incluses pour les modifications de modèles
- Modifications de configuration documentées
- Gestion des erreurs présente pour les appels externes
- Gestion des transactions là où nécessaire
Modèle de rapport
RAPPORT DE VÉRIFICATION DJANGO
==============================
Phase 1 : Vérification de l'environnement
✓ Python 3.11.5
✓ Environnement virtuel actif
✓ Toutes les variables d'environnement définies
Phase 2 : Qualité du code
✓ mypy : Aucune erreur de type
✗ ruff : 3 problèmes trouvés (corrigés automatiquement)
✓ black : Aucun problème de formatage
✓ isort : Imports correctement triés
✓ manage.py check : Aucun problème
Phase 3 : Migrations
✓ Aucune migration non appliquée
✓ Aucun conflit de migrations
✓ Tous les modèles ont des migrations
Phase 4 : Tests + Couverture
Tests : 247 réussis, 0 échoués, 5 ignorés
Couverture :
Globale : 87%
users : 92%
products : 89%
orders : 85%
payments : 91%
Phase 5 : Analyse de sécurité
✗ pip-audit : 2 vulnérabilités trouvées (correction requise)
✓ safety check : Aucun problème
✓ bandit : Aucun problème de sécurité
✓ Aucun secret détecté
✓ DEBUG = False
Phase 6 : Commandes Django
✓ collectstatic terminé
✓ Intégrité de la base de données OK
✓ Backend de cache accessible
Phase 7 : Performance
✓ Aucune requête N+1 détectée
✓ Index de base de données configurés
✓ Nombre de requêtes acceptable
Phase 8 : Assets statiques
✓ npm audit : Aucune vulnérabilité
✓ Assets construits avec succès
✓ Fichiers statiques collectés
Phase 9 : Configuration
✓ DEBUG = False
✓ SECRET_KEY configurée
✓ ALLOWED_HOSTS renseigné
✓ HTTPS activé
✓ HSTS activé
✓ Base de données configurée
Phase 10 : Journalisation
✓ Journalisation configurée
✓ Fichiers de logs accessibles en écriture
Phase 11 : Documentation de l'API
✓ Schéma généré
✓ Interface Swagger accessible
Phase 12 : Revue des différences
Fichiers modifiés : 12
+450, -120 lignes
✓ Aucune instruction de débogage
✓ Aucun secret codé en dur
✓ Migrations incluses
RECOMMANDATION : ATTENTION : Corriger les vulnérabilités pip-audit avant le déploiement
PROCHAINES ÉTAPES :
1. Mettre à jour les dépendances vulnérables
2. Relancer l'analyse de sécurité
3. Déployer sur la staging pour les tests finaux
Liste de contrôle pré-déploiement
- Tous les tests réussissent
- Couverture ≥ 80%
- Aucune vulnérabilité de sécurité
- Aucune migration non appliquée
- DEBUG = False dans les paramètres de production
- SECRET_KEY correctement configurée
- ALLOWED_HOSTS renseigné correctement
- Sauvegardes de base de données activées
- Fichiers statiques collectés et servis
- Journalisation configurée et fonctionnelle
- Surveillance des erreurs (Sentry, etc.) configurée
- CDN configuré (si applicable)
- Backend de cache Redis configuré
- Workers Celery en cours d'exécution (si applicable)
- HTTPS/SSL configuré
- Variables d'environnement documentées
Intégration continue
Exemple GitHub Actions
# .github/workflows/django-verification.yml
name: Vérification Django
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Configurer Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Mettre en cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
- name: Installer les dépendances
run: |
pip install -r requirements.txt
pip install ruff black mypy pytest pytest-django pytest-cov bandit safety pip-audit
- name: Contrôles de qualité du code
run: |
ruff check .
black . --check
isort . --check-only
mypy .
- name: Analyse de sécurité
run: |
bandit -r . -f json -o bandit-report.json
safety check --full-report
pip-audit
- name: Exécuter les tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test
DJANGO_SECRET_KEY: test-secret-key
run: |
pytest --cov=apps --cov-report=xml --cov-report=term-missing
- name: Télécharger la couverture
uses: codecov/codecov-action@v3
Référence rapide
| Vérification | Commande |
|---|---|
| Environnement | python --version |
| Vérification de typage | mypy . |
| Linting | ruff check . |
| Formatage | black . --check |
| Migrations | python manage.py makemigrations --check |
| Tests | pytest --cov=apps |
| Sécurité | pip-audit && bandit -r . |
| Vérification Django | python manage.py check --deploy |
| Collectstatic | python manage.py collectstatic --noinput |
| Statistiques diff | git diff --stat |
Rappel : La vérification automatisée détecte les problèmes courants mais ne remplace pas la revue de code manuelle et les tests dans l'environnement de staging.