6 Commits

Author SHA1 Message Date
yann64 d685c2211e CHANGELOG : correction des entrées 1.0.2 et 1.0.3 (correctifs partiels)
Les descriptions initiales présentaient ces versions comme des corrections
définitives alors qu'elles n'adressaient qu'une partie du problème.
Mention explicite du renvoi vers 1.0.4 pour le correctif complet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 07:20:32 +02:00
yann64 a400b7cc66 Release 1.0.4 — changelog + bump version dev 1.0.5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 07:17:51 +02:00
yann64 ed5cfcd275 Fix wizard : suppression totale des sous-processus exec() dans install()
- APP_KEY : généré directement en PHP (random_bytes) + écrit dans .env + propagé
  via config() et putenv() → évite le bug de pattern-matching de key:generate
  (la clé en mémoire ≠ clé dans le .env réécrit par writeEnv)
- DB_* + APP_KEY : putenv() écrase l'env OS hérité au boot (pgsql/temp-key) pour
  que tout sous-processus futur hérite des bonnes valeurs
- optimize supprimé de l'installation : config:cache re-boostrappe l'app via
  bootstrap/app.php dans un contexte où l'Encrypter peut lever MissingAppKeyException ;
  optimize:clear seul suffit — Laravel reconstruit ses caches à la première requête
- key:generate converti en Artisan::call() puis remplacé par génération PHP directe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 07:17:32 +02:00
yann64 4110caa25a Release 1.0.3 — changelog + bump version dev 1.0.4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 23:03:14 +02:00
yann64 9225abc804 Fix wizard : migrations via Artisan::call() pour éviter l'héritage d'env pgsql
Cause racine : public/index.php charge le .env auto-créé (pgsql) et appelle
putenv('DB_CONNECTION=pgsql'). Les sous-processus exec() héritent cet env OS.
phpdotenv en mode immutable refuse d'écraser une variable déjà définie →
le nouveau .env mysql est ignoré, la migration tente une connexion pgsql.

Fix : reconfiguration de la connexion BDD en mémoire via config() + DB::purge()
puis exécution des migrations via Artisan::call() dans le processus courant.
Plus aucun subprocess pour les migrations → aucun héritage d'env parasite.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:19:50 +02:00
yann64 56dbd8a0bf Setup : affichage du numéro de version dans l'assistant d'installation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:12:04 +02:00
4 changed files with 104 additions and 20 deletions
+25 -2
View File
@@ -5,12 +5,35 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag
--- ---
## [1.0.4] — 2026-06-05
### Corrigé
- **Assistant d'installation — APP_KEY vide après installation** : `key:generate` remplace `APP_KEY=<clé_en_mémoire>` par regex dans le `.env`. Mais `writeEnv()` écrit `APP_KEY=` (vide) alors que la clé en mémoire est celle de l'auto-création (clé temporaire) — le pattern ne matche pas, la clé reste vide. Correction : la clé est générée directement en PHP (`random_bytes`), écrite dans le `.env` sans regex, puis propagée en mémoire (`config(['app.key'])`) et dans l'env OS (`putenv`).
- **Assistant d'installation — `MissingAppKeyException` lors de l'optimisation** : `optimize` appelle en interne `config:cache`, qui re-boostrappe une seconde instance de l'application depuis `bootstrap/app.php`. Ce second boot passe par tous les ServiceProviders et peut résoudre l'Encrypter avant que la clé soit accessible, levant `MissingAppKeyException` et renvoyant une erreur 500. Correction : `optimize` est supprimé de la procédure d'installation ; seul `optimize:clear` est conservé pour purger tout cache résiduel. Laravel reconstruit ses caches paresseusement à la première requête.
- **Assistant d'installation — connexion PostgreSQL forcée après login (MySQL)** : `putenv()` n'était appelé que pour les variables `DB_*` mais pas pour `APP_KEY`. Correction : tous les `putenv()` (dont `APP_KEY`) sont regroupés en un bloc cohérent, garantissant que tout sous-processus futur hérite des valeurs correctes.
---
## [1.0.3] — 2026-06-04
### Ajouté
- **Numéro de version dans l'assistant d'installation** — affiché sous le titre « Assistant d'installation » dans le layout du wizard (lu depuis le fichier `VERSION`)
### Corrigé
- **Assistant d'installation — conflit pgsql/mysql (correctif partiel, voir 1.0.4)** : identification de la cause racine (`phpdotenv` immutable + héritage `putenv` par les sous-processus `exec()`). Les migrations sont migrées vers `Artisan::call()` avec reconfiguration en mémoire (`config()` + `DB::purge()`), mais `key:generate` et `optimize` restaient des sous-processus — corrigé complètement en 1.0.4.
- **`.htaccess`** — suppression des directives `php_flag display_errors on` ajoutées temporairement pour déboguer l'erreur 500 sur hébergement mutualisé.
---
## [1.0.2] — 2026-06-04 ## [1.0.2] — 2026-06-04
### Corrigé ### Corrigé
- **Assistant d'installation — conflit de connexion pgsql/mysql** : un fichier `bootstrap/cache/config.php` résiduel (produit par `php artisan optimize` sur le poste de développement) était lu en priorité sur le `.env` réécrit par le wizard, forçant une connexion PostgreSQL même quand MySQL était sélectionné. Un appel à `config:clear` est maintenant effectué entre l'écriture du `.env` et l'exécution des migrations. - **Assistant d'installation — conflit de connexion pgsql/mysql** *(correctif partiel, voir 1.0.3 et 1.0.4)* : ajout d'un appel à `config:clear` entre l'écriture du `.env` et l'exécution des migrations, et exclusion de `bootstrap/cache/*.php` des archives de déploiement pour ne pas embarquer un cache de configuration de développement.
- **Archives de déploiement** : `bootstrap/cache/*.php` exclu du build rsync pour éviter qu'un cache de configuration de développement ne soit embarqué dans les distributables. - **Archives de déploiement** : `bootstrap/cache/*.php` exclu du build rsync.
--- ---
+1 -1
View File
@@ -1 +1 @@
1.0.3 1.0.5
+70 -16
View File
@@ -3,6 +3,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use PDO; use PDO;
use PDOException; use PDOException;
@@ -126,8 +128,6 @@ class SetupController extends Controller
$steps = []; $steps = [];
$success = true; $success = true;
$php = $this->phpBinary();
$artisan = $php . ' ' . escapeshellarg(base_path('artisan'));
// 1. Écriture du .env // 1. Écriture du .env
try { try {
@@ -138,24 +138,74 @@ class SetupController extends Controller
$success = false; $success = false;
} }
// 2. Génération de la clé APP_KEY // 2. Génération de la clé APP_KEY — directement en PHP, sans passer par key:generate.
//
// Artisan key:generate remplace APP_KEY=<clé_en_mémoire> dans le .env grâce à un
// pattern regex. Mais writeEnv() vient d'écrire APP_KEY= (vide) alors qu'en mémoire
// la clé est celle de l'auto-création (TEMP_KEY) → le pattern ne matche pas → la
// clé reste vide dans le .env et la config:cache en hérite.
// Solution : générer la clé nous-mêmes, l'écrire directement dans le .env, et la
// propager en mémoire + env OS dès maintenant.
$appKey = null;
if ($success) { if ($success) {
[$ok, $out] = $this->artisanRun($artisan, 'key:generate --force'); try {
$steps[] = ['ok' => $ok, 'label' => 'Génération de la clé de chiffrement (APP_KEY)', 'error' => $ok ? null : $out]; $appKey = 'base64:' . base64_encode(random_bytes(32));
if (! $ok) $success = false; $envPath = base_path('.env');
$env = file_get_contents($envPath);
$env = preg_replace('/^APP_KEY=.*/m', 'APP_KEY=' . $appKey, $env);
file_put_contents($envPath, $env);
config(['app.key' => $appKey]);
$steps[] = ['ok' => true, 'label' => 'Génération de la clé de chiffrement (APP_KEY)'];
} catch (\Exception $e) {
$steps[] = ['ok' => false, 'label' => 'Génération de la clé de chiffrement (APP_KEY)', 'error' => $e->getMessage()];
$success = false;
}
} }
// 2b. Purge du cache de config pour forcer la lecture du nouveau .env // 2b. Reconfiguration de la connexion BDD — processus courant ET sous-processus.
// (un bootstrap/cache/config.php résiduel sinon l'emporte sur le .env réécrit) //
// putenv() écrase l'env OS hérité au boot (pgsql + TEMP_KEY) pour que tous les
// sous-processus futurs (config:cache interne à optimize…) reçoivent les bonnes
// valeurs. config() + DB::purge() reconfigure le processus courant en mémoire.
if ($success) { if ($success) {
$this->artisanRun($artisan, 'config:clear'); putenv("APP_KEY={$appKey}");
putenv("DB_CONNECTION={$dbData['driver']}");
putenv("DB_HOST={$dbData['host']}");
putenv("DB_PORT={$dbData['port']}");
putenv("DB_DATABASE={$dbData['database']}");
putenv("DB_USERNAME={$dbData['username']}");
putenv('DB_PASSWORD=' . ($dbData['password'] ?? ''));
$connConfig = $dbData['driver'] === 'pgsql'
? ['driver' => 'pgsql', 'host' => $dbData['host'], 'port' => (int) $dbData['port'],
'database' => $dbData['database'], 'username' => $dbData['username'],
'password' => $dbData['password'] ?? '', 'charset' => 'utf8', 'prefix' => '',
'schema' => 'public', 'sslmode' => 'prefer']
: ['driver' => 'mysql', 'host' => $dbData['host'], 'port' => (int) $dbData['port'],
'database' => $dbData['database'], 'username' => $dbData['username'],
'password' => $dbData['password'] ?? '', 'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true];
config([
'database.default' => $dbData['driver'],
"database.connections.{$dbData['driver']}" => $connConfig,
]);
DB::purge($dbData['driver']);
} }
// 3. Migrations // 3. Migrations (dans le processus courant, config BDD déjà écrasée ci-dessus)
if ($success) { if ($success) {
[$ok, $out] = $this->artisanRun($artisan, 'migrate --force'); try {
$steps[] = ['ok' => $ok, 'label' => 'Migration de la base de données', 'error' => $ok ? null : $out]; $exitCode = Artisan::call('migrate', ['--force' => true]);
if (! $ok) $success = false; $out = trim(Artisan::output());
$ok = $exitCode === 0;
$steps[] = ['ok' => $ok, 'label' => 'Migration de la base de données', 'error' => $ok ? null : $out];
if (! $ok) $success = false;
} catch (\Exception $e) {
$steps[] = ['ok' => false, 'label' => 'Migration de la base de données', 'error' => $e->getMessage()];
$success = false;
}
} }
// 4. Création du compte administrateur // 4. Création du compte administrateur
@@ -182,10 +232,14 @@ class SetupController extends Controller
} }
} }
// 6. Optimisation des caches // 6. Nettoyage des caches
// optimize:clear supprime tout cache résiduel (config, routes, vues, events).
// On n'appelle PAS optimize : config:cache re-boostrappe l'app depuis bootstrap/app.php
// dans un contexte qui peut ne pas avoir accès à notre APP_KEY via putenv, ce qui
// provoque MissingAppKeyException. Laravel reconstruit ses caches à la première
// requête — pas besoin de les préchauffer pendant l'installation.
if ($success) { if ($success) {
$this->artisanRun($artisan, 'optimize:clear'); Artisan::call('optimize:clear');
$this->artisanRun($artisan, 'optimize');
} }
// 7. Marquage installation // 7. Marquage installation
+8 -1
View File
@@ -16,7 +16,14 @@
<div class="text-center mb-8"> <div class="text-center mb-8">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-blue-600 text-white text-2xl font-bold mb-3 select-none">M</div> <div class="inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-blue-600 text-white text-2xl font-bold mb-3 select-none">M</div>
<h1 class="text-2xl font-bold text-slate-800">MesRelevés</h1> <h1 class="text-2xl font-bold text-slate-800">MesRelevés</h1>
<p class="text-slate-500 text-sm mt-1">Assistant d'installation</p> <p class="text-slate-500 text-sm mt-1">
Assistant d'installation
@php $version = trim(@file_get_contents(base_path('VERSION')) ?: ''); @endphp
@if($version)
<span class="mx-1.5 text-slate-300">·</span>
<span class="font-mono text-slate-400">v{{ $version }}</span>
@endif
</p>
</div> </div>
{{-- Indicateur d'étapes --}} {{-- Indicateur d'étapes --}}