# Note pour la mise en place de Docker et du pipeline

**Destinataire** : Lilian · **Date** : 06/08/2026
**Objet** : éléments constatés sur le dépôt et les serveurs, à connaître avant de démarrer

Cette note rassemble ce qu'un audit du code, de la base de production et du serveur a mis au
jour ces deux derniers jours. Elle n'est pas prescriptive : elle vise à t'éviter de perdre du
temps sur des problèmes déjà identifiés — et, pour deux d'entre eux, déjà corrigés.

---

## 1. Merger la PR #95 avant de lancer Docker

**C'est le point le plus important de cette note.**

Docker part d'un conteneur neuf, avec une base neuve, puis exécute `migrate` et `seed`. Or dans
l'état actuel de `development`, cette séquence **échoue**, pour trois raisons cumulées :

| Problème | Symptôme |
|---|---|
| `add_category_id_into_courses` (03/10) pose une clé étrangère vers `subcategories`, table créée seulement le 14/10 | `migrate` s'arrête à la 6ᵉ migration : *Failed to open the referenced table 'subcategories'* |
| `RoleSeeder` ne crée que 5 des 7 rôles utilisés (`director` et `manager_general` manquent) | Le seed s'interrompt à la première affectation de l'un de ces rôles |
| `User::getStoredRole()` surcharge la méthode Spatie mais n'accepte qu'un nom en chaîne, pas une instance de `Role` | `ModelNotFoundException` dans les seeders |

La **PR #95** corrige les trois. Après elle, `php artisan migrate:fresh --seed` fonctionne de
bout en bout sur MySQL — vérifié. Avant elle, aucun environnement neuf ne peut être monté, Docker
compris.

**Point important** : ces bugs ne se voient pas dans la suite de tests actuelle, parce qu'elle
tourne sur SQLite (voir §3). Ils n'apparaissent que sur MySQL.

## 2. `laravel/sail` est déjà installé

Le paquet `laravel/sail` figure dans les dépendances de développement, mais n'a jamais été
initialisé : aucun `docker-compose.yml` dans le dépôt. `php artisan sail:install` génère la
configuration. Rien à ajouter côté dépendances.

## 3. Les tests tournent sur SQLite — le basculer sur MySQL révélera des choses

`phpunit.xml` impose `DB_CONNECTION=sqlite` et `DB_DATABASE=:memory:`.

Faire tourner les tests sur MySQL dans Docker est souhaitable — on teste alors ce qu'on exécute
réellement. Mais il faut s'attendre à **de nouveaux échecs**, car SQLite est permissif là où
MySQL ne l'est pas. Le bug de migration du §1 en est l'illustration : il n'est jamais apparu dans
la suite précisément à cause de SQLite.

Ce n'est pas une raison de renoncer, au contraire. Juste de ne pas s'inquiéter si le premier run
sur MySQL sort des choses inattendues.

## 4. Le pipeline sera rouge dès le premier run — et ce ne sera pas ta faute

Il existe **5 échecs de tests antérieurs à tout ce chantier** :

```
ManagerUserManagementTest::test_manager_can_update_user_profile
ManagerUserManagementTest::test_manager_can_store_generic_user
ManagerUserManagementTest::test_director_user_management_crud
UserManagementTest::test_admin_can_create_user
UserManagementTest::test_admin_can_update_user_role
```

Tous ont la même cause : le champ `cta_url` est devenu obligatoire (`required|url` dans
`CreateUserRequest`) sans que ces tests soient mis à jour — ils envoient des requêtes sans ce
champ et reçoivent un 422.

**Référence à connaître** : sur `development`, la suite donne **5 échecs**. Tout échec
supplémentaire est une régression. Deux options : corriger ces 5 tests (c'est mécanique, il
suffit d'ajouter `cta_url` aux payloads), ou les marquer comme attendus le temps de les traiter.
La première est préférable — elle te donne une cible verte.

## 5. PHP 8.2 obligatoire

Le `composer.lock` embarque `phpoffice/phpspreadsheet` 1.30.2, qui exige `php >=7.4 <8.5`. Avec
PHP 8.5, `composer install` échoue. À épingler dans l'image Docker et dans le pipeline.

## 6. Ce qu'un pipeline minimal devrait faire

```
composer install --no-interaction --prefer-dist
php artisan key:generate
php artisan test          # référence : 5 échecs connus (§4)
vendor/bin/pint --test    # le projet utilise déjà Pint
```

Côté front : `npm ci --legacy-peer-deps` (l'installation échoue sans ce drapeau) puis
`npm run build` et `npx vitest run` — une trentaine de fichiers de tests existent.

## 7. Si Docker vise aussi la production — trois pièges

Pour le développement local et la CI, aucune réserve. Pour la production, ces points sont
bloquants s'ils sont manqués :

**Les fichiers téléversés.** `storage/app/public` contient **289 Mo** en production :
149 certificats, avatars, ressources de cours, images. Ils doivent devenir un **volume monté**,
sinon chaque reconstruction du conteneur les efface. Ils ne sont pas dans git — c'est voulu, mais
cela signifie qu'aucune sauvegarde ne les couvre aujourd'hui hors du serveur.

**La racine servie est atypique.** Le `DocumentRoot` Apache pointe sur le dossier **parent** de
l'application, pas sur `public/`. D'où des URL de la forme
`api.efektiv-academie.com/e-learning-api/public/api/…`. Ce chemin fait partie des URL publiques :
il figure dans le front, dans les emails déjà envoyés et dans les notifications. Le conteneur doit
le reproduire à l'identique, sinon tous les liens existants cassent.

**Le serveur est mutualisé.** `57.129.1.122` héberge Efektiv, Formind et OPDO, chacun en
production, préproduction et développement, derrière un seul Apache avec renouvellement SSL
automatique par certbot. Conteneuriser un seul de ces projets impose un proxy inverse et une
reprise de la terminaison TLS.

Pour ces raisons, la suggestion est de **garder la production hors périmètre jusqu'à la
livraison de mi-septembre**, et de viser d'abord le local et la CI.

---

## Deux évolutions récentes à connaître

**La production a été corrigée le 06/08 sur deux points** :

- `APP_ENV=local` et `APP_DEBUG=true` étaient actifs en production. En mode debug, une erreur non
  gérée affiche l'intégralité des variables d'environnement — donc les clés Stripe, Pusher, SMTP
  et le mot de passe de la base. Corrigé, `.env` sauvegardé au préalable.
- La table `migrations` était désynchronisée : 39 entrées enregistrées pour 62 fichiers présents.
  Les 23 manquantes correspondaient à des objets bien présents en base, appliqués manuellement en
  SQL. Elles ont été recalées après vérification objet par objet et export complet. **Conséquence
  directe : `php artisan migrate` est désormais sûr en production**, ce qui n'était pas le cas
  avant.

**Le serveur de préproduction tire désormais son code de `AAZTEKDEV/EFEKTIVACADEMIE-BACK`**
(branche `development`), via une clé de déploiement SSH en lecture seule. Il pointait auparavant
vers un dépôt tiers dont le dernier commit datait d'août 2025, alors que les fichiers étaient
déposés à la main — sans traçabilité ni retour arrière possible.

⚠️ **Une règle à retenir sur ces serveurs** : ne jamais lancer `git clean`. Les fichiers
téléversés ne sont pas suivis par git ; `git reset` et `git checkout` les épargnent, `git clean`
les supprimerait.

---

## En résumé

| Action | Priorité |
|---|---|
| Merger la PR #95 avant de démarrer Docker | **Bloquant** |
| Épingler PHP 8.2 dans l'image et le pipeline | Élevée |
| Corriger les 5 tests `cta_url` pour obtenir une base verte | Élevée |
| Docker pour le local et la CI | Recommandé |
| Docker pour la production | Après mi-septembre |
