From 07d004b3f0e4081d36c619d99aa42f394f362bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drix?= Date: Fri, 15 May 2026 10:13:56 +0200 Subject: [PATCH] =?UTF-8?q?feat=20:=20bouton=20unique=20Mettre=20=C3=A0=20?= =?UTF-8?q?jour=20(git=20pull=20+=20SQL=20+=20contenu),=20branche=20dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 31 +++++++++++++++++---- public/index.php | 68 ++++++++++++++++++++++++++++++++++++++++++++- scripts/push.sh | 2 +- templates/admin.php | 48 ++++++++++++++++---------------- 4 files changed, 117 insertions(+), 32 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c68c7ee..7c727ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,19 +22,38 @@ Les articles ne sont pas versionnés dans ce dépôt. Ils ont leur propre git lo ## Modifier le moteur -Pour toute correction ou fonctionnalité : **créer un ticket et une PR**. +### Branches -1. Coder ici dans `~/Projects/folio/` (branche feature) -2. **Tester sur varlog.a5l.fr** : +| Branche | Rôle | +|---------|------| +| `dev` | Branche d'intégration permanente. **Tout le développement courant se fait ici.** | +| `main` | Branche de production. **Jamais de commit direct.** | +| `feat/*` | Branches feature optionnelles pour du travail isolé, mergées dans `dev`. | + +### Workflow + +1. Toujours travailler sur `dev` (ou une branche feature mergée dans `dev`) : + ```bash + git checkout dev + ``` +2. **Tester sur varlog.a5l.fr** à chaque itération (rsync des fichiers locaux, DB persistante) : ```bash ~/Projects/varlog/scripts/sync.sh # puis tester sur http://varlog.acegrp.lan ``` -3. Une fois validé, ouvrir une PR sur Gitea. Le commit doit inclure : - - `public/version.txt` (bump semver) - - `CHANGELOG.md` (entrée `### Ajouté / Corrigé / Modifié`) +3. Quand `dev` est stable et prête pour la production : + - Bumper `public/version.txt` (semver) + - Ajouter une entrée `CHANGELOG.md` (`### Ajouté / Corrigé / Modifié`) + - Ouvrir une **PR `dev` → `main`** sur Gitea 4. Merger la PR → abonnel.fr se met à jour automatiquement. +**Règle absolue : ne jamais commiter directement sur `main`.** Le script `scripts/push.sh` bloque cette action. + +### Pourquoi `dev` et non des branches feature à la volée + +- La DB de varlog (test) accumule les migrations au fil du temps — changer de branche ne fait pas reculer les migrations. +- Travailler toujours sur `dev` évite toute désynchronisation entre le code rsyncé et la DB. + ## Données articles (`DATA_PATH`) Les articles sont stockés dans un répertoire **hors du dépôt Folio**, configurable via `DATA_PATH` dans `.env`. diff --git a/public/index.php b/public/index.php index b57a1dc..05f354e 100644 --- a/public/index.php +++ b/public/index.php @@ -45,7 +45,7 @@ $action = $_GET['action'] ?? 'list'; $uuid = $_GET['uuid'] ?? ''; $slug = $_GET['slug'] ?? ''; -$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete', 'admin_save_as_groups', 'admin_save_folio_config']; +$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete', 'admin_save_as_groups', 'admin_save_folio_config', 'run_engine_update']; $metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null; unset($_noindexActions); @@ -2816,6 +2816,72 @@ switch ($action) { header('Location: /admin?tab=dashboard¬ice=' . ($_cmErrors ? 'migration_error' : 'migrated')); exit; + case 'run_engine_update': + requireAuth(); + if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') { + http_response_code(403); + exit; + } + + // 1. git pull + exec('cd ' . escapeshellarg(BASE_PATH) . ' && git pull origin main 2>&1', $_gitOut, $_gitCode); + if ($_gitCode !== 0) { + $_SESSION['_update_log'] = implode("\n", $_gitOut); + header('Location: /admin?tab=dashboard¬ice=update_git_error'); + exit; + } + + // 2. composer install (non-bloquant si absent) + exec('which composer 2>/dev/null', $_composerPath); + if (!empty($_composerPath)) { + exec('cd ' . escapeshellarg(BASE_PATH) . ' && composer install --no-dev --optimize-autoloader -q 2>&1'); + } + + // 3. Migrations SQL + $pdo->exec('CREATE TABLE IF NOT EXISTS schema_migrations (name TEXT NOT NULL PRIMARY KEY, applied_at TIMESTAMP NOT NULL DEFAULT NOW())'); + $_sqlApplied = array_flip($pdo->query('SELECT name FROM schema_migrations ORDER BY name')->fetchAll(PDO::FETCH_COLUMN)); + $_sqlFiles = glob(BASE_PATH . '/database/migration_*.sql') ?: []; + sort($_sqlFiles); + foreach ($_sqlFiles as $_sqlFile) { + $_sqlName = basename($_sqlFile); + if (isset($_sqlApplied[$_sqlName])) { + continue; + } + $pdo->exec((string) file_get_contents($_sqlFile)); + $pdo->prepare('INSERT INTO schema_migrations (name) VALUES (:n)')->execute([':n' => $_sqlName]); + } + + // 4. Migrations de contenu + $_cmDataDir = DATA_PATH; + $_cmTrack = $_cmDataDir . '/.content_migrations.json'; + $_cmFlag = $_cmDataDir . '/.maintenance'; + $_cmApplied = file_exists($_cmTrack) ? (json_decode((string) file_get_contents($_cmTrack), true) ?? []) : []; + $_cmFiles = glob(BASE_PATH . '/scripts/content/migration_*.php') ?: []; + sort($_cmFiles); + $_cmPending = array_values(array_filter($_cmFiles, fn ($f) => !isset($_cmApplied[basename($f)]))); + $_cmErrors = 0; + if (!empty($_cmPending)) { + file_put_contents($_cmFlag, date('Y-m-d H:i:s')); + $dataDir = $_cmDataDir; + foreach ($_cmPending as $_cmFile) { + try { + require $_cmFile; + $_cmApplied[basename($_cmFile)] = date('Y-m-d H:i:s'); + file_put_contents($_cmTrack, json_encode($_cmApplied, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"); + } catch (Throwable $_cmEx) { + $_cmErrors++; + break; + } + } + if (file_exists($_cmFlag)) { + unlink($_cmFlag); + } + } + + $_updateChecker->clearCache(); + header('Location: /admin?tab=dashboard¬ice=' . ($_cmErrors ? 'update_content_error' : 'engine_updated')); + exit; + case 'force_update_check': requireAuth(); if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') { diff --git a/scripts/push.sh b/scripts/push.sh index 3bc618f..096e428 100755 --- a/scripts/push.sh +++ b/scripts/push.sh @@ -24,7 +24,7 @@ fi BRANCH=$(git rev-parse --abbrev-ref HEAD) if [[ "$BRANCH" == "main" ]]; then echo "✗ Refus de pousser directement sur main." - echo " Créer une branche feature : git checkout -b feat/nom" + echo " Travailler sur 'dev' ou une branche feature : git checkout dev" exit 1 fi diff --git a/templates/admin.php b/templates/admin.php index 41e3488..3d02e0e 100644 --- a/templates/admin.php +++ b/templates/admin.php @@ -126,13 +126,17 @@ function adminStatusBadge(array $a, int $now): string Dernière version disponible - Mise à jour disponible' : '' ?> - -
- -
+ + +
+ +
+ +
+ +
- (FOLIO_REPO_URL non configuré) + (FOLIO_REPO_URL non configuré) @@ -140,24 +144,20 @@ function adminStatusBadge(array $a, int $now): string Branche suivie · vérifié le ' . date('d/m/Y à H:i', $_lastChecked) . '' : '' ?> - - - Actions requises - - - -
- -
- - - - - - -
Migrations appliquées avec succès.
- -
Une erreur est survenue pendant la migration.
+ +
Moteur mis à jour avec succès (code, base de données, contenu).
+ + +
+ Erreur git pull — vérifiez les droits d'accès au dépôt. + +
+ + +
+ + +
Code et base de données mis à jour, mais une migration de contenu a échoué.