feat : UpdateChecker délègue la mise à jour à un script sudo externe

Le bouton "Mettre à jour" appelle désormais `sudo /usr/local/bin/folio-upgrade.sh`
via exec() plutôt que d'exécuter git pull + composer + migrations directement en PHP.
Le script shell (template dans scripts/server/) gère la séquence complète : clone fresh,
permissions www-data, restauration .env, composer install, migrations SQL, .sessions,
safe.directory. Le journal de la dernière mise à jour est conservé dans DATA_PATH/.upgrade-log
et affiché en <details> dans l'admin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 15:46:26 +02:00
parent 53dbce5bb0
commit af0a0bb9d5
4 changed files with 121 additions and 77 deletions
+21 -11
View File
@@ -103,9 +103,10 @@ function adminStatusBadge(array $a, int $now): string
<?php
$_deployedVer = trim((string) @file_get_contents(BASE_PATH . '/public/version.txt'));
$_deployedLabel = $_deployedVer !== '' ? $_deployedVer : '—';
$_notices = isset($_updateChecker) ? $_updateChecker->adminNotices() : [];
$_branch = isset($_updateChecker) ? $_updateChecker->getBranch() : 'main';
$_lastChecked = isset($_updateChecker) ? $_updateChecker->getLastChecked() : null;
$_notices = isset($_updateChecker) ? $_updateChecker->adminNotices() : [];
$_branch = isset($_updateChecker) ? $_updateChecker->getBranch() : 'main';
$_lastChecked = isset($_updateChecker) ? $_updateChecker->getLastChecked() : null;
$_upgradeLog = isset($_updateChecker) ? $_updateChecker->getLastUpgradeLog() : null;
$_repoConfigured = folioRepoUrl() !== '';
$_remoteLabel = '—';
foreach ($_notices as $_n) {
@@ -145,19 +146,28 @@ function adminStatusBadge(array $a, int $now): string
<td><code><?= htmlspecialchars($_branch) ?></code><?= $_lastChecked !== null ? ' <span class="text-muted ms-2">· vérifié le ' . date('d/m/Y à H:i', $_lastChecked) . '</span>' : '' ?></td>
</tr>
<?php if (($_GET['notice'] ?? '') === 'engine_updated'): ?>
<tr><td colspan="2"><div class="alert alert-success py-1 mb-0 small">Moteur mis à jour avec succès (code, base de données, contenu).</div></td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'update_git_error'): ?>
<tr><td colspan="2"><div class="alert alert-success py-1 mb-0 small">Moteur mis à jour avec succès.</div></td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'upgrade_error'): ?>
<tr><td colspan="2">
<div class="alert alert-danger py-1 mb-0 small">
Erreur git pull — vérifiez les droits d'accès au dépôt.
<?php if (!empty($_SESSION['_update_log'])): ?>
<pre class="mt-1 mb-0 small"><?= htmlspecialchars($_SESSION['_update_log']) ?></pre>
<?php unset($_SESSION['_update_log']); ?>
Erreur lors de la mise à jour.
<?php if (!empty($_SESSION['_upgrade_log'])): ?>
<pre class="mt-1 mb-0 small"><?= htmlspecialchars($_SESSION['_upgrade_log']) ?></pre>
<?php unset($_SESSION['_upgrade_log']); ?>
<?php endif; ?>
</div>
</td></tr>
<?php elseif (($_GET['notice'] ?? '') === 'update_content_error'): ?>
<tr><td colspan="2"><div class="alert alert-warning py-1 mb-0 small">Code et base de données mis à jour, mais une migration de contenu a échoué.</div></td></tr>
<?php endif; ?>
<?php if ($_upgradeLog !== null): ?>
<tr>
<th class="text-muted fw-normal ps-0 pe-2 text-nowrap align-top">Journal</th>
<td>
<details>
<summary class="small text-muted" style="cursor:pointer">Dernière mise à jour</summary>
<pre class="mt-1 mb-0 small"><?= htmlspecialchars($_upgradeLog) ?></pre>
</details>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>