Truth File strategy: never seed from latest, calibrate or detect
CheckModpackUpdates: - Reads .modpack-checker.json Truth File from server filesystem - Falls back to manifest.json, extracts fileID, writes Truth File - NEVER seeds current_version from latest API result - Unknown version → status: pending_calibration (not up_to_date) - Removed seedCurrentVersion heuristic — replaced with Truth File - writeTruthFile() helper writes .modpack-checker.json via Wings ModpackAPIController: - calibrate() now writes Truth File after DB update - Persists across server reinstalls and cron runs wrapper.tsx: - pending_calibration: shows "Version unknown" + "Identify Version" button - Ignored servers: muted card with "Resume" button (not hidden) - Extracted renderCalibrateDropdown() for reuse - Error state shows message instead of vanishing Migration: - Updates existing unknown+detected rows to pending_calibration Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f39b6d6c67
commit
27b2744786
@@ -240,7 +240,7 @@ class CheckModpackUpdates extends Command
|
||||
$latestVersion = $latestData['version'] ?? 'Unknown';
|
||||
$latestFileId = $latestData['file_id'] ?? null;
|
||||
|
||||
// Get current_version: manifest > egg variable > existing DB > seed with latest
|
||||
// Get current_version: manifest arg > egg variable > existing DB
|
||||
$currentVersion = $installedVersion;
|
||||
$currentFileId = null;
|
||||
|
||||
@@ -257,11 +257,53 @@ class CheckModpackUpdates extends Command
|
||||
}
|
||||
$currentFileId = $existing->current_file_id ?? null;
|
||||
|
||||
// First time — try date-time seeding, fall back to latest
|
||||
if (empty($currentVersion)) {
|
||||
$seeded = $this->seedCurrentVersion($server, $platform, $modpackId, $latestVersion, $latestFileId);
|
||||
$currentVersion = $seeded['version'];
|
||||
$currentFileId = $seeded['file_id'];
|
||||
// Truth File: read .modpack-checker.json from server filesystem
|
||||
if (empty($currentFileId)) {
|
||||
try {
|
||||
$this->fileRepository->setServer($server);
|
||||
$truthRaw = $this->fileRepository->getContent('.modpack-checker.json');
|
||||
$truthFile = json_decode($truthRaw, true);
|
||||
if (!empty($truthFile['file_id'])) {
|
||||
$currentFileId = $truthFile['file_id'];
|
||||
$currentVersion = $currentVersion ?: ($truthFile['version'] ?? null);
|
||||
$this->line(" [truth] Read file_id {$currentFileId} from .modpack-checker.json");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Truth File doesn't exist yet
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy manifest.json: extract fileID, write Truth File
|
||||
if (empty($currentFileId)) {
|
||||
try {
|
||||
$this->fileRepository->setServer($server);
|
||||
$manifest = json_decode($this->fileRepository->getContent('manifest.json'), true);
|
||||
if (!empty($manifest['files'][0]['fileID'])) {
|
||||
$currentFileId = (string) $manifest['files'][0]['fileID'];
|
||||
$this->writeTruthFile($server, $modpackId, $currentFileId, $manifest['version'] ?? null);
|
||||
$currentVersion = $currentVersion ?: ($manifest['version'] ?? null);
|
||||
$this->line(" [manifest] Extracted file_id {$currentFileId}, wrote Truth File");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// No manifest
|
||||
}
|
||||
}
|
||||
|
||||
// NEVER seed from latest — if unknown, mark pending_calibration
|
||||
if (empty($currentVersion) && empty($currentFileId)) {
|
||||
$this->updateDatabase($server, [
|
||||
'platform' => $platform,
|
||||
'modpack_id' => $modpackId,
|
||||
'modpack_name' => $latestData['name'],
|
||||
'latest_version' => $latestVersion,
|
||||
'latest_file_id' => $latestFileId,
|
||||
'status' => 'pending_calibration',
|
||||
'detection_method' => $method,
|
||||
'error_message' => null,
|
||||
'last_checked' => now(),
|
||||
]);
|
||||
$this->info(" ⏳ PENDING: {$latestData['name']} — calibration required");
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare: prefer file ID, fall back to string
|
||||
@@ -328,40 +370,22 @@ class CheckModpackUpdates extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed current version using date-time heuristic.
|
||||
* Finds the release closest to (but not after) the server's created_at date.
|
||||
* Write .modpack-checker.json Truth File to server filesystem.
|
||||
*/
|
||||
private function seedCurrentVersion(Server $server, string $platform, string $modpackId, string $fallbackVersion, ?string $fallbackFileId): array
|
||||
private function writeTruthFile(Server $server, string $projectId, string $fileId, ?string $version): void
|
||||
{
|
||||
try {
|
||||
$installDate = $server->created_at?->toISOString();
|
||||
if (!$installDate) {
|
||||
return ['version' => $fallbackVersion, 'file_id' => $fallbackFileId];
|
||||
}
|
||||
|
||||
$history = $this->apiService->fetchFileHistory($platform, $modpackId);
|
||||
if (empty($history)) {
|
||||
return ['version' => $fallbackVersion, 'file_id' => $fallbackFileId];
|
||||
}
|
||||
|
||||
// Find the release closest to but not after install date
|
||||
$matched = collect($history)
|
||||
->filter(fn($f) => !empty($f['release_date']) && $f['release_date'] <= $installDate)
|
||||
->sortByDesc('release_date')
|
||||
->first();
|
||||
|
||||
if ($matched) {
|
||||
$this->line(" [seed] Matched version {$matched['version']} (released {$matched['release_date']}) to install date {$installDate}");
|
||||
return [
|
||||
'version' => $matched['version'],
|
||||
'file_id' => $matched['file_id'] ?? $fallbackFileId,
|
||||
];
|
||||
}
|
||||
$this->fileRepository->setServer($server);
|
||||
$this->fileRepository->putContent('.modpack-checker.json', json_encode([
|
||||
'extension' => 'modpackchecker',
|
||||
'project_id' => $projectId,
|
||||
'file_id' => $fileId,
|
||||
'version' => $version,
|
||||
'calibrated_at' => now()->toIso8601String(),
|
||||
], JSON_PRETTY_PRINT));
|
||||
} catch (\Exception $e) {
|
||||
$this->line(" [seed] Heuristic failed: " . $e->getMessage());
|
||||
\Log::warning('[MVC] Could not write Truth File: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return ['version' => $fallbackVersion, 'file_id' => $fallbackFileId];
|
||||
}
|
||||
|
||||
private function getVariable(Server $server, string $name): ?string
|
||||
|
||||
Reference in New Issue
Block a user