---
title: "Guide d'entretien technique — Candidat 1 (Tech Lead Python/Django-React)"
type: career
area: career
status: reference
interview_role: "Interviewer (Me)"
category: "Conducting Interview"
target_candidate: "Candidat 1 (Tech Lead)"
role: "Python/Django - React Developer"
stage: "Technical Interview Assessment"
date: 2026-07-06
created: 2026-07-06
updated: 2026-07-06
tags:
  - career
  - conducting-interviews
---
# Guide d’entretien technique

Profil ciblé : développeur Python/Django–React, environ 5 ans d’expérience, avec des responsabilités déclarées de Tech Lead.

Contexte : maintenance de FUSE et SECHEL/PROCURE, migration de GitHub Actions vers GitLab CI/CD, déploiement AWS/Terraform.

## Format recommandé — 90 minutes

- 10 min : parcours et responsabilités réelles
- 25 min : Python/Django et maintenance
- 15 min : questions liées à FUSE et SECHEL
- 15 min : AWS/Terraform
- 15 min : GitLab CI/CD
- 10 min : cas pratique de diagnostic

## 1. Python et Django

### 1. Transactions

**FR :** Un import Excel met à jour plusieurs milliers d’objets Django. Une erreur survient après 70 % du traitement. Comment garantissez-vous la cohérence des données ?

**EN:** An Excel import updates several thousand Django objects. An error occurs after 70% of the processing. How would you guarantee data consistency?

**Attendu :** `transaction.atomic`, stratégie par lot, idempotence, reprise et journalisation.


#### Réponse attendue détaillée

Le fichier doit d’abord être validé sans écriture. Les écritures peuvent ensuite être protégées par `transaction.atomic()`.

Pour un volume raisonnable, une transaction globale garantit un « tout ou rien ». Pour un très gros volume, elle peut maintenir trop longtemps des verrous et grossir fortement. Une stratégie par lots est alors préférable, avec :

- un objet `Import` ayant un statut et un identifiant unique ;
- des lots transactionnels ;
- des opérations idempotentes ;
- un checkpoint permettant la reprise ;
- un journal des lignes acceptées et rejetées ;
- des contraintes DB pour empêcher les doublons.

Le choix entre transaction globale et lots doit être fondé sur la volumétrie et la règle métier.

### 2. Optimisation ORM

**FR :** Quelle différence existe-t-il entre `select_related()` et `prefetch_related()` ? Comment détecteriez-vous un problème N+1 ?

**EN:** What is the difference between `select_related()` and `prefetch_related()`? How would you detect an N+1 query problem?

**Attendu :** jointure SQL pour FK/OneToOne, requête séparée pour relations multiples, inspection des requêtes et profiling.


#### Réponse attendue détaillée

`select_related()` effectue une jointure SQL et convient aux relations simples comme `ForeignKey` et `OneToOneField`.

`prefetch_related()` exécute des requêtes séparées puis associe les résultats en Python. Il convient aux relations multiples et `ManyToMany`.

Un N+1 se détecte en :

- comptant les requêtes sur une page ou dans un test ;
- observant une même requête répétée avec des paramètres différents ;
- utilisant la Django Debug Toolbar, les logs SQL ou un outil APM ;
- analysant le temps DB.

Il faut mesurer avant et après la correction et éviter un préchargement massif inutile.

### 3. Concurrence

**FR :** Deux utilisateurs ou deux workers Celery modifient simultanément le même objet. Comment évitez-vous une mise à jour perdue ?

**EN:** Two users or Celery workers update the same object concurrently. How do you prevent a lost update?

**Attendu :** `select_for_update`, transaction, mise à jour conditionnelle, expressions `F()`, verrou optimiste ou contrainte DB.


#### Réponse attendue détaillée

Pour une section critique courte, une transaction avec `select_for_update()` verrouille la ligne jusqu’au commit. Une autre solution est une mise à jour conditionnelle :

```python
updated = Task.objects.filter(
    pk=task_id,
    version=expected_version,
).update(assignee=user, version=F("version") + 1)
```

Si `updated == 0`, une modification concurrente a eu lieu. Les expressions `F()` permettent aussi des incréments atomiques. Une contrainte unique doit protéger les invariants qui peuvent être exprimés par la base.

Lire un objet, le modifier en mémoire puis appeler `save()` sans protection peut écraser une modification concurrente.

### 4. Migrations

**FR :** Comment ajouteriez-vous une colonne obligatoire à une table volumineuse sans interrompre la production ?

**EN:** How would you add a required column to a large table without causing production downtime?

**Attendu :** colonne nullable, backfill par lots, déploiement applicatif, puis contrainte finale.


#### Réponse attendue détaillée

Une stratégie compatible avec plusieurs versions de l’application :

1. ajouter la colonne comme nullable, sans valeur par défaut coûteuse si la table est volumineuse ;
2. déployer le code capable de fonctionner avec l’ancien et le nouveau schéma ;
3. remplir la colonne par lots ;
4. contrôler qu’aucune valeur n’est nulle ;
5. ajouter la contrainte `NOT NULL` ;
6. supprimer ultérieurement le code de compatibilité.

Une migration qui ajoute la colonne obligatoire et transforme toutes les lignes en une seule opération peut verrouiller la table.

### 5. Django 4.2 et 5.2

**FR :** SECHEL utilise Django 4.2 et FUSE Django 5.2. Comment prépareriez-vous et sécuriseriez-vous une montée de version ?

**EN:** SECHEL uses Django 4.2 and FUSE uses Django 5.2. How would you prepare and secure a framework upgrade?

**Attendu :** release notes, dépréciations, dépendances, tests, QA, déploiement progressif et rollback.


#### Réponse attendue détaillée

Le candidat doit :

- vérifier les versions Python et la compatibilité des dépendances ;
- lire les notes de publication et les dépréciations ;
- exécuter les contrôles Django et la suite de tests ;
- rechercher les API supprimées ;
- mettre à jour par étapes si plusieurs versions majeures sont traversées ;
- tester les migrations, tâches Celery, fichiers statiques, authentification et intégrations ;
- valider en QA avec des données représentatives ;
- prévoir une sauvegarde et un rollback.

Une mise à jour de framework ne doit pas être mélangée à de nombreuses modifications fonctionnelles.

### 6. Sécurité Django

**FR :** Quelles protections Django fournit-il contre CSRF, XSS et injection SQL ? Dans quelles situations peut-on les contourner accidentellement ?

**EN:** What protections does Django provide against CSRF, XSS, and SQL injection? How can developers accidentally bypass them?


#### Réponse attendue détaillée

Django fournit notamment :

- un token et un middleware contre CSRF ;
- l’échappement automatique des variables dans les templates contre XSS ;
- la paramétrisation des requêtes produites par l’ORM contre l’injection SQL.

Ces protections peuvent être contournées avec :

- `csrf_exempt` ou une mauvaise configuration des origines ;
- `mark_safe`, le filtre `safe`, du HTML utilisateur ou du JavaScript injecté ;
- `raw()`, `RawSQL`, `extra()` ou une requête SQL construite par concaténation ;
- une autorisation vérifiée uniquement dans le frontend.

Le candidat devrait également citer les cookies sécurisés, HTTPS, CSP, validation des uploads et gestion des secrets.

### 7. Permissions

**FR :** Comment implémenteriez-vous des permissions par objet pour limiter les tâches visibles selon le site ou l’utilisateur ?

**EN:** How would you implement object-level permissions to restrict task visibility by site or user?

**Attendu :** filtrage serveur systématique, permissions objet et tests d’autorisation.


#### Réponse attendue détaillée

Le queryset doit être filtré selon les sites et rôles autorisés avant de récupérer l’objet. Il ne suffit pas de masquer un bouton.

Les vues, API, exports et tâches asynchrones doivent appliquer la même politique. Django Guardian peut gérer des permissions par objet, mais un filtrage métier explicite peut être plus simple selon le modèle.

Les tests doivent vérifier :

- accès autorisé ;
- accès d’un autre site refusé ;
- modification directe par URL refusée ;
- export ne contenant aucune donnée interdite.

### 8. API REST asynchrone

**FR :** Comment concevoir une API REST d’import qui peut durer plusieurs minutes ?

**EN:** How would you design a REST import endpoint that can take several minutes to complete?

**Attendu :** `202 Accepted`, tâche asynchrone, identifiant de suivi, endpoint de statut et clé d’idempotence.


#### Réponse attendue détaillée

L’endpoint :

1. valide rapidement la requête et stocke le fichier ;
2. crée une ressource d’import ;
3. lance une tâche Celery ;
4. renvoie `202 Accepted` avec l’identifiant et l’URL de statut.

Un endpoint de statut expose la progression, le résultat et les erreurs. Une clé d’idempotence ou un checksum empêche le double lancement. Le résultat volumineux peut être stocké dans S3 et fourni par une URL temporaire.

## 2. Maintenance FUSE et SECHEL/PROCURE

### 9. Affectation concurrente

**FR :** Deux responsables affectent simultanément la même tâche à deux utilisateurs différents. Quelle règle technique mettriez-vous en place ?

**EN:** Two managers assign the same task to different users at the same time. What technical control would you implement?


#### Réponse attendue détaillée

La règle métier doit être explicite : première affectation gagnante, dernière modification gagnante ou conflit présenté à l’utilisateur.

Une solution fiable utilise une mise à jour conditionnelle sur la version ou l’ancien responsable. Si aucune ligne n’est modifiée, l’interface signale que la tâche a changé. Pour une opération complexe, `select_for_update()` dans une transaction est approprié.

L’historique doit enregistrer l’auteur, la date, l’ancienne et la nouvelle valeur.

### 10. Tableau de bord lent

**FR :** Le tableau de bord devient lent avec plusieurs millions de tâches. Quelle méthode de diagnostic appliquez-vous avant de modifier le code ?

**EN:** The dashboard becomes slow with several million tasks. What diagnostic process would you follow before changing code?

**Attendu :** mesurer frontend/backend/DB, plan SQL, index, N+1, volume transféré et agrégations.


#### Réponse attendue détaillée

La démarche attendue :

1. mesurer la latence côté navigateur, application et base ;
2. identifier les endpoints et requêtes dominants ;
3. analyser les plans SQL avec `EXPLAIN`;
4. rechercher N+1, scans complets et tris coûteux ;
5. vérifier index, cardinalité et filtres ;
6. réduire les colonnes et lignes transférées ;
7. préagréger ou mettre en cache seulement si les requêtes optimisées restent insuffisantes.

Ajouter du cache avant d’identifier la cause peut masquer un mauvais modèle de requête.

### 11. Export volumineux

**FR :** Un export provoque un dépassement mémoire du conteneur ECS. Comment corrigez-vous le problème ?

**EN:** A data export causes the ECS container to run out of memory. How would you fix it?

**Attendu :** streaming, pagination ou chunks, traitement asynchrone, stockage S3 et lien temporaire.


#### Réponse attendue détaillée

Il ne faut pas charger tout le queryset et tout le fichier en mémoire. Les solutions incluent :

- `iterator()` ou pagination stable ;
- génération par chunks ;
- format CSV en streaming si acceptable ;
- tâche asynchrone pour les exports longs ;
- écriture progressive dans S3 ;
- URL présignée limitée dans le temps ;
- quotas de taille et nettoyage automatique.

Augmenter uniquement la mémoire ECS reporte le problème.

### 12. Historique et audit

**FR :** Comment garantir un historique fiable des changements de statut et d’affectation d’une tâche ?

**EN:** How would you guarantee a reliable audit history of task status and assignment changes?


#### Réponse attendue détaillée

L’audit doit être produit côté serveur dans la même transaction que la modification. Chaque événement contient :

- objet concerné ;
- utilisateur ou processus ;
- date UTC ;
- ancienne et nouvelle valeur ;
- source : interface, import, API ou tâche ;
- identifiant de corrélation.

Les événements doivent être difficiles à modifier et consultables selon les droits. Les logs applicatifs seuls ne remplacent pas toujours un historique métier durable.



SECHEL est un outil de reporting pour la planification des pièces, utilisé par environ 150 utilisateurs sur plusieurs usines. Il contient de nombreux imports Excel, Pandas et des calculs métier.

### 13. Import fiable

**FR :** Comment valideriez-vous un fichier avant de modifier la base : colonnes, types, références et règles métier ?

**EN:** How would you validate an import file before modifying the database: columns, types, references, and business rules?

**Attendu :** validation en plusieurs phases, rapport d’erreurs, transaction et tests.


#### Réponse attendue détaillée

Une bonne chaîne sépare :

1. validation du type, nom et taille du fichier ;
2. validation des colonnes obligatoires ;
3. normalisation contrôlée des valeurs ;
4. validation des types et formats ;
5. validation des références et règles métier ;
6. détection des doublons ;
7. génération d’un rapport d’erreurs ;
8. écriture transactionnelle.

Les numéros de ligne et valeurs fautives doivent apparaître dans le rapport. Il faut fixer des limites contre les fichiers trop gros et les fichiers Excel malveillants.

### 14. Gros fichiers Pandas

**FR :** Un import Pandas fonctionne en local mais dépasse la mémoire en production. Quelles solutions envisagez-vous ?

**EN:** A Pandas import works locally but exceeds memory in production. What solutions would you consider?

**Attendu :** lecture par chunks, colonnes nécessaires uniquement, types optimisés ou traitement streaming.


#### Réponse attendue détaillée

Pandas peut consommer plusieurs fois la taille du fichier. Le candidat doit proposer :

- `usecols` pour ne lire que les colonnes utiles ;
- types explicites, notamment catégories ;
- lecture par chunks quand le format le permet ;
- suppression rapide des DataFrames intermédiaires ;
- opérations vectorisées plutôt que boucles et copies ;
- traitement ligne par ligne ou moteur plus adapté si le fichier dépasse la mémoire disponible.

La mémoire doit être mesurée avec un fichier représentatif de production.

### 15. Rejeu d’un fichier

**FR :** Que doit-il se passer si le même fichier SECHEL est importé deux fois ?

**EN:** What should happen if the same SECHEL file is imported twice?

**Attendu :** règle métier explicite, checksum ou identifiant d’import, rejet ou remplacement contrôlé.


#### Réponse attendue détaillée

Le comportement doit être défini avec le métier :

- rejeter le fichier déjà traité ;
- autoriser un remplacement versionné ;
- ou rendre l’import entièrement idempotent.

Un checksum seul peut être insuffisant si le même contenu est légitimement réutilisé. On peut combiner checksum, période métier, source et version. Une contrainte DB ou transaction doit empêcher deux imports simultanés identiques.

### 16. Traçabilité

**FR :** Un utilisateur affirme que les données d’une pièce ont changé après un import. Quelles informations doivent être disponibles pour enquêter ?

**EN:** A user claims that a part’s data changed after an import. What information should be available for investigation?


#### Réponse attendue détaillée

L’enquête nécessite :

- fichier source ou son empreinte ;
- utilisateur et date ;
- version de l’application ;
- paramètres d’import ;
- lignes acceptées, transformées et rejetées ;
- anciennes et nouvelles valeurs ;
- identifiant de tâche Celery ;
- logs avec identifiant de corrélation ;
- règles métier appliquées.

Les données personnelles ou sensibles du fichier doivent avoir une durée de rétention maîtrisée.

### 17. MySQL et PostgreSQL

**FR :** SECHEL utilise MySQL alors que FUSE utilise PostgreSQL. Quelles différences surveilleriez-vous lors d’une migration ou d’un partage de composants ?

**EN:** SECHEL uses MySQL while FUSE uses PostgreSQL. What differences would you watch for during a migration or when sharing components?

**Attendu :** types, collations, contraintes, SQL spécifique, dates, JSON, index et verrouillage.


#### Réponse attendue détaillée

Points à contrôler :

- types et tailles ;
- booléens, dates, fuseaux horaires et JSON ;
- collations, comparaison sensible à la casse et tri ;
- auto-incréments et séquences ;
- SQL spécifique à chaque moteur ;
- contraintes et comportement des valeurs nulles ;
- index et plans d’exécution ;
- isolation transactionnelle et verrouillage ;
- migrations Django et bibliothèques spécifiques comme `django_mysql`.

La migration doit comporter une comparaison des volumes, contraintes et résultats fonctionnels.

## 3. AWS et Terraform

### 18. Architecture AWS

**FR :** Décrivez le trajet d’une requête HTTPS vers une application Django exécutée sur ECS.

**EN:** Describe the path of an HTTPS request to a Django application running on ECS.

**Attendu :** DNS, ALB, TLS, listener, target group, security groups, tâche ECS, serveur applicatif et logs.


#### Réponse attendue détaillée

Le DNS résout le domaine vers l’ALB. Le listener HTTPS termine TLS avec un certificat. Les règles transmettent la requête à un target group. Le security group de l’ALB autorise HTTPS ; celui des tâches ECS n’autorise le port applicatif que depuis l’ALB.

La tâche exécute Gunicorn/Uvicorn et Django. Elle accède aux services privés selon son rôle IAM et ses security groups. Les logs sont envoyés vers CloudWatch. Une réponse doit aussi mentionner les health checks et éventuellement WAF devant l’ALB.

### 19. Diagnostic ECS

**FR :** Une nouvelle tâche ECS démarre puis est continuellement remplacée. Où cherchez-vous la cause ?

**EN:** A new ECS task starts and is continuously replaced. Where would you investigate?

**Attendu :** événements ECS, CloudWatch, health check ALB, commande, secrets, réseau, CPU et mémoire.


#### Réponse attendue détaillée

Examiner :

- événements du service ECS et raison d’arrêt ;
- logs du conteneur ;
- code de sortie et commande de démarrage ;
- health checks du conteneur et de l’ALB ;
- image et architecture CPU ;
- variables et secrets manquants ;
- accès réseau à RDS/Redis ;
- limites CPU et mémoire ;
- durée de grâce du health check.

Il faut éviter de modifier plusieurs paramètres simultanément avant d’avoir une hypothèse.

### 20. Health checks

**FR :** Que doit vérifier un endpoint de health check ? Doit-il systématiquement tester PostgreSQL et Redis ?

**EN:** What should a health-check endpoint verify? Should it always test PostgreSQL and Redis?

**Attendu :** distinguer liveness et readiness.


#### Réponse attendue détaillée

La liveness indique que le processus fonctionne. Elle doit être rapide et avoir peu de dépendances.

La readiness indique que l’instance peut recevoir du trafic. Elle peut vérifier les dépendances indispensables avec des timeouts courts.

Tester systématiquement Redis ou un service non critique dans la liveness peut provoquer le redémarrage de toutes les tâches lors d’une panne secondaire. Les checks doivent être séparés selon leur objectif.

### 21. RDS

**FR :** Comment préparez-vous une modification risquée de base de données et comment restaurez-vous les données en cas d’échec ?

**EN:** How do you prepare for a risky database change, and how do you restore data if it fails?

**Attendu :** snapshot, sauvegardes/PITR, test de restauration, migration compatible et rollback.


#### Réponse attendue détaillée

Avant une modification risquée :

- confirmer les sauvegardes automatiques et la rétention ;
- créer un snapshot si nécessaire ;
- vérifier le point-in-time recovery ;
- surtout tester une restauration ;
- estimer le RTO et le RPO ;
- rendre la migration applicative rétrocompatible ;
- surveiller verrous, espace disque et durée.

Un rollback applicatif ne suffit pas si la migration de données est destructive.

### 22. VPC

**FR :** Quels composants doivent être dans des subnets publics ou privés : ALB, tâches ECS, RDS et Redis ?

**EN:** Which components should be placed in public or private subnets: ALB, ECS tasks, RDS, and Redis?

**Attendu :** ALB public si nécessaire ; ECS, RDS et Redis privés.


#### Réponse attendue détaillée

Dans une architecture classique :

- ALB Internet-facing dans des subnets publics de plusieurs zones ;
- tâches ECS sans IP publique dans des subnets privés ;
- RDS et Redis dans des subnets privés ;
- règles entrantes basées sur les security groups sources ;
- sortie des tâches par NAT ou VPC endpoints si nécessaire.

RDS et Redis ne doivent pas être exposés à `0.0.0.0/0`.

### 23. IAM

**FR :** Quelle différence existe-t-il entre le rôle d’exécution ECS et le rôle de la tâche ECS ?

**EN:** What is the difference between the ECS task execution role and the ECS task role?


#### Réponse attendue détaillée

Le rôle d’exécution est utilisé par l’agent ECS pour récupérer l’image, publier les logs et récupérer certains secrets nécessaires au démarrage.

Le rôle de tâche est assumé par le code exécuté dans le conteneur pour appeler S3, SES ou d’autres services AWS.

Les deux doivent appliquer le moindre privilège. Donner des permissions applicatives au rôle d’exécution ou utiliser un rôle très large rend l’audit et la sécurité plus difficiles.

### 24. Secrets

**FR :** Comment fournissez-vous les mots de passe et clés à Django sans les placer dans Git, l’image Docker ou le fichier Terraform ?

**EN:** How do you provide passwords and keys to Django without storing them in Git, the Docker image, or Terraform configuration?

**Attendu :** Secrets Manager/SSM, IAM, rotation et protection du state Terraform.


#### Réponse attendue détaillée

Les secrets sont stockés dans Secrets Manager ou SSM Parameter Store, chiffrés par KMS et accessibles par un rôle IAM limité. Ils sont injectés au runtime ou récupérés par l’application.

Il faut prévoir :

- rotation ;
- audit des accès ;
- séparation QA/production ;
- absence dans les logs ;
- révocation ;
- protection du state Terraform, qui peut contenir des valeurs sensibles même marquées `sensitive`.

### 25. Déploiement sans interruption

**FR :** Comment déployer une nouvelle image sur ECS sans interrompre les utilisateurs ni casser les migrations ?

**EN:** How would you deploy a new image to ECS without interrupting users or breaking database migrations?

**Attendu :** rolling ou blue/green, health checks, migrations rétrocompatibles et rollback.


#### Réponse attendue détaillée

Une nouvelle task definition référence une image immuable, idéalement par digest ou SHA. ECS lance les nouvelles tâches, attend leur readiness puis retire les anciennes.

Il faut configurer :

- capacité minimale garantissant le service ;
- grace period des health checks ;
- rolling update ou blue/green ;
- alarmes déclenchant un rollback ;
- migrations « expand and contract » compatibles avec les deux versions ;
- vérification fonctionnelle après déploiement.

### 26. Observabilité

**FR :** Quelles métriques et alertes minimales mettriez-vous en place ?

**EN:** What minimum metrics and alerts would you configure?

**Attendu :** erreurs HTTP, latence, CPU/mémoire, files Celery, erreurs applicatives, RDS et échecs d’import.


#### Réponse attendue détaillée

Minimum recommandé :

- taux d’erreurs HTTP et latence par percentile ;
- nombre de targets ALB saines ;
- CPU, mémoire, redémarrages et nombre de tâches ECS ;
- profondeur et âge des files Celery ;
- erreurs et durée des imports ;
- connexions, CPU, stockage, latence et locks RDS ;
- mémoire et évictions Redis ;
- erreurs applicatives corrélées dans Sentry/CloudWatch.

Une alerte doit être actionable, avoir un seuil justifié et une procédure associée.

### 27. Terraform

**FR :** Pourquoi le state Terraform est-il sensible ? Comment le partager et empêcher deux pipelines de le modifier simultanément ?

**EN:** Why is Terraform state sensitive? How would you share it and prevent two pipelines from modifying it concurrently?

**Attendu :** backend distant chiffré, contrôle d’accès, verrouillage et versionnement.


#### Réponse attendue détaillée

Le state contient les identifiants, attributs et parfois des secrets des ressources. Il doit être :

- stocké dans un backend distant ;
- chiffré ;
- versionné ;
- protégé par IAM ;
- verrouillé pendant les opérations ;
- séparé par environnement ;
- sauvegardé et audité.

Le plan doit être relu avant application. Les déploiements concurrents doivent être sérialisés, par le backend et par le pipeline.

## 4. GitLab et migration CI/CD

### 28. Migration GitHub Actions

**FR :** Comment convertiriez-vous les workflows GitHub Actions actuels en `.gitlab-ci.yml` ?

**EN:** How would you convert the existing GitHub Actions workflows into `.gitlab-ci.yml`?

**Attendu :** inventorier triggers, jobs, services et secrets ; traduire en `workflow: rules`, `rules`, stages, jobs, runners, artifacts et environments.


#### Réponse attendue détaillée

Commencer par inventorier chaque workflow :

- événement déclencheur ;
- permissions ;
- jobs et dépendances ;
- services PostgreSQL/Redis ;
- secrets et clés SSH ;
- artifacts et caches ;
- environnements et déploiements.

Dans GitLab, créer `.gitlab-ci.yml`, traduire les déclencheurs avec `workflow: rules` et `rules`, choisir les images et runners, puis valider chaque pipeline en parallèle de l’ancien avant bascule. Les workflows communs aux deux projets peuvent être factorisés avec `include` ou un composant CI partagé, sans créer prématurément une abstraction complexe.

### 29. Pipeline Django

**FR :** Concevez oralement les étapes du pipeline GitLab pour FUSE.

**EN:** Verbally design the GitLab pipeline stages for FUSE.

**Attendu :**

1. lint et contrôles ;
2. installation avec lockfile ;
3. PostgreSQL et Redis comme services ;
4. vérification des migrations ;
5. tests ;
6. build Docker ;
7. scan ;
8. publication ;
9. déploiement QA ;
10. validation manuelle de production.


#### Réponse attendue détaillée

Un pipeline cohérent peut contenir :

- contrôle du format, lint et sécurité ;
- installation reproductible avec `uv sync --frozen` ;
- PostgreSQL et Redis comme services ;
- `makemigrations --check --dry-run` ;
- tests Django en parallèle ;
- build d’une seule image Docker immuable ;
- scan de l’image et des dépendances ;
- publication dans le registry ;
- déploiement automatique en QA ;
- tests de fumée ;
- production manuelle et protégée ;
- vérification et rollback.

L’image testée doit être la même que celle déployée.

### 30. `stages` et `needs`

**FR :** Quelle différence existe-t-il entre l’ordre défini par `stages` et les dépendances définies par `needs` ?

**EN:** What is the difference between ordering jobs with `stages` and defining dependencies with `needs`?


#### Réponse attendue détaillée

Les stages imposent une barrière : par défaut, tous les jobs d’un stage attendent la fin du stage précédent.

`needs` exprime une dépendance directe et crée un graphe. Un job peut commencer dès que ses dépendances sont terminées, même si d’autres jobs du stage précédent continuent. Cela réduit la durée du pipeline.

Il ne faut pas ajouter `needs` partout : le graphe doit rester lisible et refléter de vraies dépendances.

### 31. Artifacts et cache

**FR :** Quelle différence existe-t-il entre un artifact et un cache GitLab ?

**EN:** What is the difference between a GitLab artifact and a cache?

**Attendu :** artifact = résultat transmis ou conservé ; cache = accélération sans garantie fonctionnelle.


#### Réponse attendue détaillée

Les artifacts sont des résultats d’un job : rapports de tests, couverture, binaire ou plan Terraform. Ils peuvent être transmis aux jobs suivants et conservés pendant une durée définie.

Le cache accélère une exécution, par exemple les téléchargements de dépendances. Un pipeline doit rester correct si le cache est vide ou périmé.

Une image de production ne doit pas dépendre d’un cache non maîtrisé pour sa reproductibilité.

### 32. Runners

**FR :** Quand utiliser un runner partagé ou dédié ? Quels sont les risques de Docker-in-Docker ?

**EN:** When would you use a shared runner versus a dedicated runner? What are the risks of Docker-in-Docker?


#### Réponse attendue détaillée

Les runners partagés conviennent aux jobs standards sans accès réseau privilégié. Un runner dédié peut être nécessaire pour :

- réseau privé AWS ;
- exigences de conformité ;
- ressources spécifiques ;
- meilleure isolation ;
- performance stable.

Docker-in-Docker utilise souvent un daemon privilégié, augmente la surface d’attaque et complexifie TLS, cache et stockage. Des alternatives comme BuildKit rootless ou Kaniko peuvent être étudiées selon les contraintes.

### 33. Variables et secrets

**FR :** Quelle différence existe-t-il entre une variable masquée, protégée et une variable de type fichier ?

**EN:** What is the difference between a masked, protected, and file-type variable?


#### Réponse attendue détaillée

- **Masquée :** sa valeur ne doit pas apparaître dans les logs, sous réserve des règles de masquage.
- **Protégée :** disponible seulement sur les branches ou tags protégés.
- **Type fichier :** GitLab crée un fichier temporaire et fournit son chemin, utile pour certificats et configurations.

Le masquage ne remplace pas la protection des branches ni le moindre privilège. Un script peut toujours exfiltrer un secret auquel son job a accès.

### 34. Authentification AWS

**FR :** Comment permettre au pipeline GitLab de déployer sur AWS sans stocker de clé AWS permanente ?

**EN:** How can a GitLab pipeline deploy to AWS without storing permanent AWS access keys?

**Attendu :** jeton OIDC GitLab, rôle IAM et credentials temporaires AWS STS.


#### Réponse attendue détaillée

Configurer GitLab comme fournisseur d’identité OIDC dans AWS. Le job reçoit un ID token avec une audience appropriée et appelle STS pour assumer un rôle.

La trust policy du rôle limite :

- le projet ;
- la branche ou le tag ;
- l’environnement ;
- l’audience.

Le job obtient des credentials temporaires. Il n’y a donc pas de clé AWS longue durée à stocker ou faire tourner dans GitLab.

### 35. Protection de production

**FR :** Comment empêcher un pipeline de feature branch de déployer en production ?

**EN:** How would you prevent a feature-branch pipeline from deploying to production?

**Attendu :** branche et environnement protégés, `rules`, job manuel, approbations et rôle AWS limité.


#### Réponse attendue détaillée

La protection doit être réalisée à plusieurs niveaux :

- `rules` limitant le job à une branche ou un tag de release ;
- branche/tag protégé ;
- environnement de production protégé ;
- job manuel avec approbation ;
- runner autorisé ;
- rôle AWS assumable uniquement depuis le contexte GitLab autorisé ;
- permissions IAM limitées au déploiement.

Une condition YAML seule n’est pas une frontière de sécurité suffisante.

### 36. Dépendances Git privées

**FR :** Les projets utilisent des dépendances installées par SSH depuis GitHub. Que faut-il modifier pendant la migration vers GitLab ?

**EN:** The projects install private Git dependencies over SSH from GitHub. What must change during the GitLab migration?

**Attendu :** migrer les dépôts ou conserver un accès contrôlé, deploy tokens/keys, URLs, `known_hosts`, droits minimaux et rotation des anciennes clés.


#### Réponse attendue détaillée

Il faut inventorier les dépendances Git privées et décider si elles migrent vers GitLab. Ensuite :

- modifier les URLs dans `pyproject.toml` ou les requirements ;
- préférer un deploy token ou `CI_JOB_TOKEN` si compatible ;
- limiter la clé en lecture ;
- configurer `known_hosts` ;
- ne pas désactiver la vérification SSH ;
- mettre à jour Docker BuildKit si la clé est utilisée pendant le build ;
- révoquer les anciennes clés après validation.

Idéalement, publier les dépendances versionnées dans un package registry plutôt que dépendre d’une branche `main`.

### 37. Rollback

**FR :** Le pipeline est vert, mais l’application renvoie des erreurs après le déploiement. Comment organisez-vous le rollback ?

**EN:** The pipeline is green, but the application returns errors after deployment. How would you organize the rollback?

**Attendu :** image immuable identifiée par SHA, ancienne task definition, rollback contrôlé et migrations compatibles.


#### Réponse attendue détaillée

Chaque image doit porter un identifiant immuable, comme le SHA du commit. Le déploiement conserve la task definition précédente.

En cas d’erreur :

1. empêcher la poursuite du rollout ;
2. réactiver la version précédente ;
3. attendre les health checks ;
4. exécuter des smoke tests ;
5. vérifier les métriques ;
6. traiter séparément les migrations de données.

Le rollback est dangereux si une migration irréversible a déjà supprimé ou transformé les données. D’où la nécessité de migrations rétrocompatibles.

## 5. Celery, Redis et traitements asynchrones

### 38. Idempotence

**FR :** Une tâche Celery est exécutée deux fois après un redémarrage du worker. Comment éviter les doublons fonctionnels ?

**EN:** A Celery task runs twice after a worker restart. How do you prevent functional duplicates?

**Attendu :** tâche idempotente, identifiant métier unique, contrainte DB et vérification de l’état.


#### Réponse attendue détaillée

Celery fonctionne généralement avec une livraison « au moins une fois » : une tâche peut être rejouée. La tâche doit donc produire le même résultat si elle est exécutée plusieurs fois.

Les protections possibles sont :

- identifiant métier unique ;
- contrainte unique en base ;
- statut vérifié et mis à jour dans une transaction ;
- `get_or_create()` ou mise à jour conditionnelle ;
- appel externe avec une clé d’idempotence ;
- verrou limité à la ressource concernée.

Se fier uniquement à l’identifiant de tâche Celery est souvent insuffisant.

### 39. Retry

**FR :** Quand faut-il réessayer automatiquement une tâche Celery, et quand ne faut-il surtout pas le faire ?

**EN:** When should a Celery task be retried automatically, and when should it not be retried?

**Attendu :** erreurs transitoires contre erreurs métier, backoff exponentiel, nombre maximal de tentatives et alerte.


#### Réponse attendue détaillée

Un retry convient aux erreurs transitoires : timeout réseau, limitation temporaire, service momentanément indisponible ou verrou concurrent.

Il ne convient pas aux données invalides, permissions refusées, erreurs de programmation ou règles métier non satisfaites.

Le mécanisme doit avoir :

- un backoff exponentiel avec jitter ;
- un nombre maximal de tentatives ;
- des timeouts ;
- une tâche idempotente ;
- une alerte ou file d’échec après épuisement.

### 40. Redis

**FR :** Redis peut servir de cache, de broker Celery et de backend Channels. Quels risques voyez-vous à partager une même instance ?

**EN:** Redis can be used as a cache, Celery broker, and Channels backend. What risks do you see in sharing one instance?

**Attendu :** contention, éviction, isolation, capacité, persistance et impact d’une panne.


#### Réponse attendue détaillée

Les usages ont des caractéristiques différentes :

- le cache peut évincer des données ;
- le broker ne doit pas perdre silencieusement des messages ;
- Channels peut créer de nombreux messages courts ;
- Celery Results peut accumuler des clés.

Une instance partagée peut provoquer contention mémoire/CPU, éviction de messages, saturation ou panne commune. La séparation logique par base Redis ne fournit pas une isolation des ressources. Pour des charges critiques, il faut des instances ou clusters séparés, des politiques mémoire adaptées et une surveillance dédiée.

### 41. WebSockets

**FR :** Comment diffuser la progression d’un import avec Django Channels sans bloquer la requête HTTP ?

**EN:** How would you stream import progress with Django Channels without blocking the HTTP request?


#### Réponse attendue détaillée

La requête HTTP crée l’import et lance Celery. Le worker publie périodiquement la progression dans un groupe Channels lié à l’utilisateur ou à l’import. Le consumer WebSocket transmet les messages au navigateur.

Il faut :

- autoriser l’accès au groupe ;
- limiter la fréquence des mises à jour ;
- persister l’état principal en base pour permettre une reconnexion ;
- ne pas considérer le WebSocket comme la source de vérité ;
- gérer l’échec définitif et l’expiration.



FUSE gère la création, l’affectation et le suivi de tâches sur 12 sites, avec tableaux de bord et exports.

## 6. Parcours et validation du CV

### 42. Responsabilités de Tech Lead

**FR :** Vous indiquez avoir défini des architectures et réalisé des revues de code. Donnez un exemple précis d’une décision d’architecture que vous avez prise, les alternatives considérées et son résultat.

**EN:** You mention defining architectures and performing code reviews. Give a concrete example of an architectural decision you made, the alternatives considered, and the outcome.

**Attendu :** contexte précis, contraintes, compromis, métriques ou résultat observable. Éviter une réponse uniquement théorique.


#### Réponse attendue détaillée

Le candidat doit partir d’un problème réel : volumétrie, dette technique, délais, disponibilité ou organisation de l’équipe. Il doit expliquer :

- les contraintes fonctionnelles et techniques ;
- au moins deux solutions envisagées ;
- les compromis : coût, délai, complexité, performance et maintenabilité ;
- la manière dont la décision a été documentée et partagée ;
- un résultat mesurable : réduction des erreurs, temps de réponse, fréquence de livraison ou simplification du code.

Un bon Tech Lead ne présente pas son choix comme évident. Il montre comment il a obtenu l’adhésion de l’équipe et réévalué la décision après sa mise en production.

### 43. Incident de production

**FR :** Décrivez l’incident de production le plus difficile que vous avez résolu. Comment avez-vous identifié la cause racine ?

**EN:** Describe the most difficult production incident you resolved. How did you identify the root cause?

**Attendu :** logs, métriques, reproduction, hypothèses vérifiées, correction, tests et prévention.


#### Réponse attendue détaillée

Une démarche solide suit généralement cet ordre :

1. mesurer l’impact et sécuriser le service ;
2. arrêter un déploiement ou revenir à la version stable si nécessaire ;
3. établir une chronologie à partir des logs, métriques et changements récents ;
4. formuler puis vérifier des hypothèses ;
5. reproduire le problème lorsque c’est possible ;
6. corriger la cause racine ;
7. ajouter un test, une alerte ou une procédure empêchant la récidive ;
8. réaliser un compte rendu sans recherche de culpabilité.

Une réponse limitée à « j’ai redémarré le serveur » est insuffisante.

### 44. DDD

**FR :** Vous mentionnez une architecture Domain-Driven Design. Quels problèmes concrets le DDD a-t-il résolus dans votre projet ?

**EN:** You mention a Domain-Driven Design architecture. What concrete problems did DDD solve in your project?

**Attendu :** bounded contexts, langage métier, séparation domaine/infrastructure. Vérifier qu’il ne confond pas DDD avec une simple organisation en dossiers.


#### Réponse attendue détaillée

Le candidat devrait expliquer que le DDD sert surtout lorsque le métier est complexe :

- vocabulaire commun entre développeurs et utilisateurs ;
- séparation en bounded contexts ;
- règles métier placées dans le domaine plutôt que dispersées dans les vues ;
- agrégats protégeant les invariants ;
- interfaces entre domaines clairement définies.

Créer des dossiers `domain`, `services` et `repositories` ne suffit pas. Le candidat doit citer une règle métier réelle et expliquer où elle était implémentée.

### 45. Tests et TDD

**FR :** Donnez un exemple où un test vous a permis d’éviter une régression importante.

**EN:** Give an example where a test helped you prevent a significant regression.


#### Réponse attendue détaillée

Une bonne réponse contient :

- la régression ou le comportement métier concerné ;
- le test qui échouait avant la correction ;
- le niveau du test : unitaire, intégration ou bout en bout ;
- pourquoi ce niveau était approprié ;
- ce que le test vérifie précisément ;
- le résultat obtenu lors d’une modification ultérieure.

Le candidat doit éviter les tests fortement couplés à l’implémentation ou qui ne font que reproduire le code testé.

## 7. Cas pratique final

**FR :**

Après un déploiement de SECHEL :

- le site répond lentement ;
- certaines tâches Celery sont exécutées deux fois ;
- la mémoire ECS augmente ;
- RDS atteint 95 % de connexions ;
- aucun test n’a échoué.

Expliquez votre démarche pendant les 30 premières minutes.

**EN:**

After a SECHEL deployment:

- the website responds slowly;
- some Celery tasks run twice;
- ECS memory usage increases;
- RDS reaches 95% connection utilization;
- no tests failed.

Explain what you would do during the first 30 minutes.

**Bonne réponse attendue :**

- stopper ou annuler le déploiement si l’impact augmente ;
- comparer avec la version précédente ;
- examiner les événements ECS, CloudWatch, Sentry et les métriques RDS ;
- rechercher une boucle, une fuite ou un mauvais paramétrage des workers ;
- vérifier les connexions DB et la concurrence Celery ;
- restaurer l’image précédente ;
- conserver les preuves avant redémarrage ;
- créer ensuite un test reproduisant la régression.

## Grille de notation

Noter chaque question de 0 a 4 :

- **0 :** aucune connaissance
- **1 :** notions theoriques tres faibles
- **2 :** reponse correcte mais peu de pratique
- **3 :** reponse precise avec experience et compromis
- **4 :** maitrise et diagnostic structure

Ponderation par ordre de priorite :

- Python/Django : 30 %
- Maintenance FUSE/SECHEL : 20 %
- AWS/Terraform : 15 %
- GitLab CI/CD : 15 %
- Celery/Redis : 10 %
- Parcours et communication : 10 %

## Feuille de notation

| Question | Domaine                                  |   Note    | Observation                    |
| -------: | ---------------------------------------- | :-------: | ------------------------------ |
|        1 | Python et Django                         | __4__ / 4 | ______________________________ |
|        2 | Python et Django                         | ____ / 4  | ______________________________ |
|        3 | Python et Django                         | ____ / 4  | ______________________________ |
|        4 | Python et Django                         | ____ / 4  | ______________________________ |
|        5 | Python et Django                         | ____ / 4  | ______________________________ |
|        6 | Python et Django                         | ____ / 4  | ______________________________ |
|        7 | Python et Django                         | ____ / 4  | ______________________________ |
|        8 | Python et Django                         | ____ / 4  | ______________________________ |
|        9 | Maintenance FUSE et SECHEL/PROCURE       | 3____ / 4 | ______________________________ |
|       10 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       11 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       12 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       13 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       14 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       15 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       16 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       17 | Maintenance FUSE et SECHEL/PROCURE       | ____ / 4  | ______________________________ |
|       18 | AWS et Terraform                         | ____1 / 4 | ______________________________ |
|       19 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       20 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       21 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       22 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       23 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       24 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       25 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       26 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       27 | AWS et Terraform                         | ____ / 4  | ______________________________ |
|       28 | GitLab et migration CI/CD                | __2__ / 4 | ______________________________ |
|       29 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       30 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       31 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       32 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       33 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       34 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       35 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       36 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       37 | GitLab et migration CI/CD                | ____ / 4  | ______________________________ |
|       38 | Celery, Redis et traitements asynchrones | __4__ / 4 | ______________________________ |
|       39 | Celery, Redis et traitements asynchrones | ____ / 4  | ______________________________ |
|       40 | Celery, Redis et traitements asynchrones | ____ / 4  | ______________________________ |
|       41 | Celery, Redis et traitements asynchrones | ____ / 4  | ______________________________ |
|       42 | Parcours et validation du CV             | __3_ / 4  | ______________________________ |
|       43 | Parcours et validation du CV             | __3__ / 4 | ______________________________ |
|       44 | Parcours et validation du CV             | __3__ / 4 | ______________________________ |
|       45 | Parcours et validation du CV             | __3__ / 4 | ______________________________ |

### Resultat

- Total brut : ______ / 180
- Score pondere : ______ %
- Decision : Favorable / A discuter / Defavorable
- Commentaire general : ______________________________
