116 lines
4.7 KiB
PHP
116 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
|
|
class CheckUpdates extends Command
|
|
{
|
|
protected $signature = 'mailwolt:check-updates';
|
|
protected $description = 'Check for newer MailWolt releases via git tags';
|
|
|
|
public function handle(): int
|
|
{
|
|
$currentNorm = $this->readInstalledVersionNorm();
|
|
$currentRaw = $this->readInstalledVersionRaw() ?? ($currentNorm ? 'v'.$currentNorm : null);
|
|
|
|
$appPath = base_path();
|
|
|
|
// www-data hat keine git-Credentials für private Repos.
|
|
// Fallback-Kette (erste funktionierende Methode gewinnt):
|
|
// 1. mailwolt-update --check-only (verfügbar wenn update.sh neu genug, sudoers: mailwolt-update)
|
|
// 2. mailwolt-fetch-tags (verfügbar ab v1.1.268)
|
|
// Sicherheitscheck: --check-only nur aufrufen wenn das Skript das Flag auch kennt.
|
|
$updateBin = '/usr/local/sbin/mailwolt-update';
|
|
$fetchHelper = '/usr/local/sbin/mailwolt-fetch-tags';
|
|
|
|
// Beide versuchen — --check-only schreibt version_remote, fetch-tags als Fallback
|
|
$fetched = false;
|
|
if (file_exists($updateBin) && str_contains((string) @file_get_contents($updateBin), '--check-only')) {
|
|
$result = @shell_exec('sudo -n ' . escapeshellarg($updateBin) . ' --check-only 2>/dev/null');
|
|
$fetched = ($result !== null);
|
|
}
|
|
if (!$fetched && file_exists($fetchHelper)) {
|
|
@shell_exec('sudo -n ' . escapeshellarg($fetchHelper) . ' 2>/dev/null');
|
|
}
|
|
|
|
// Version_remote wurde von einem der Helfer geschrieben; frisch genug wenn < 2h alt
|
|
$remoteFile = '/var/lib/mailwolt/version_remote';
|
|
$remoteRaw = '';
|
|
if (file_exists($remoteFile) && (time() - filemtime($remoteFile)) < 7200) {
|
|
$remoteRaw = trim((string) file_get_contents($remoteFile));
|
|
}
|
|
|
|
$latestTagRaw = $remoteRaw !== '' ? $remoteRaw
|
|
: trim((string) shell_exec("git -C " . escapeshellarg($appPath) . " tag -l 'v*' --sort=-v:refname 2>/dev/null | head -n1"));
|
|
|
|
$latestNorm = $this->normalizeVersion($latestTagRaw);
|
|
|
|
// Nichts gefunden -> alles leeren
|
|
if (!$latestNorm) {
|
|
cache()->forget('updates:latest');
|
|
cache()->forget('updates:latest_raw');
|
|
cache()->forget('mailwolt.update_available'); // legacy
|
|
$this->warn('Keine Release-Tags gefunden.');
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
// Nur wenn wirklich neuer als installiert -> Keys setzen
|
|
if ($currentNorm && version_compare($latestNorm, $currentNorm, '>')) {
|
|
cache()->forever('updates:latest', $latestNorm);
|
|
cache()->forever('updates:latest_raw', $latestTagRaw ?: ('v'.$latestNorm));
|
|
cache()->forever('mailwolt.update_available', $latestNorm); // legacy-kompat
|
|
$this->info("Update verfügbar: {$latestTagRaw} (installiert: ".($currentRaw ?? $currentNorm).")");
|
|
} else {
|
|
// Kein Update -> Keys löschen
|
|
cache()->forget('updates:latest');
|
|
cache()->forget('updates:latest_raw');
|
|
cache()->forget('mailwolt.update_available'); // legacy
|
|
$this->info("Aktuell (installiert: ".($currentRaw ?? $currentNorm ?? 'unbekannt').").");
|
|
}
|
|
|
|
cache()->put('updates:last_checked_at', now(), now()->addMinutes(10));
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
/* ===== Helpers ===== */
|
|
|
|
private function readInstalledVersionNorm(): ?string
|
|
{
|
|
// Lokal: git describe gibt immer den aktuellen Stand
|
|
if (app()->isLocal()) {
|
|
$tag = @trim((string) shell_exec('git -C ' . escapeshellarg(base_path()) . ' describe --tags --abbrev=0 2>/dev/null'));
|
|
$v = $this->normalizeVersion($tag);
|
|
if ($v) return $v;
|
|
}
|
|
|
|
$paths = [
|
|
'/var/lib/mailwolt/version',
|
|
base_path('VERSION'),
|
|
];
|
|
foreach ($paths as $p) {
|
|
$raw = @trim(@file_get_contents($p) ?: '');
|
|
if ($raw !== '') return $this->normalizeVersion($raw);
|
|
}
|
|
$raw = $this->readInstalledVersionRaw();
|
|
return $raw ? $this->normalizeVersion($raw) : null;
|
|
}
|
|
|
|
private function readInstalledVersionRaw(): ?string
|
|
{
|
|
$p = '/var/lib/mailwolt/version_raw'; // vom Wrapper (z.B. "v1.0.25" oder "v1.0.25-3-gabcd")
|
|
$raw = @trim(@file_get_contents($p) ?: '');
|
|
return $raw !== '' ? $raw : null;
|
|
}
|
|
|
|
private function normalizeVersion(?string $v): ?string
|
|
{
|
|
if (!$v) return null;
|
|
$v = trim($v);
|
|
if ($v === '') return null;
|
|
$v = ltrim($v, "vV \t\n\r\0\x0B"); // führendes v entfernen
|
|
$v = preg_replace('/-.*$/', '', $v); // Build-/dirty-Suffix abschneiden
|
|
return $v !== '' ? $v : null;
|
|
}
|
|
}
|