Skip to content

Commit b333432

Browse files
committed
fix(plugin-manager): surface plugin update validation failures instead of reporting up-to-date
When a plugin update is available, pre_plugin_checks validates it by re-downloading the update's files and verifying their SHA256/MD5. On any failure it reverted the cached .plg to the installed version and the check returned success, so the Plugins page showed "up-to-date" — hiding the available update entirely. This is most visible when the root filesystem is full: the (often large) txz can't be downloaded for the hash check, validation fails, and the update silently disappears with no error shown to the user. Record the available version and failure reason in a marker file and render an "Update validation failed" state (with the reason as a tooltip) in the Plugins page instead of the silent revert. The marker is cleared once validation passes or the plugin is updated/installed.
1 parent cc6a800 commit b333432

3 files changed

Lines changed: 41 additions & 2 deletions

File tree

emhttp/plugins/dynamix.plugin.manager/include/ShowPlugins.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,27 @@
186186
}
187187
}
188188
}
189+
// an available update that failed validation: surface it instead of the
190+
// silent "up-to-date" the revert would otherwise produce (marker written by
191+
// the pre_plugin_checks hook). Common cause: the root filesystem is full so
192+
// the update files can't be downloaded for the integrity check.
193+
if (!$os && $checked) {
194+
$invalid = "/tmp/plugins/".basename($plugin_file).".invalid";
195+
if (is_file($invalid)) {
196+
$info = json_decode(file_get_contents($invalid),true) ?: [];
197+
$newver = (string)($info['version'] ?? '');
198+
if ($newver !== '' && strcmp($newver,$version) > 0) {
199+
$reason = trim((string)($info['reason'] ?? ''));
200+
$version .= "<br><span class='red-text'>$newver</span>";
201+
$status = "<span class='warning'".($reason ? " title='".htmlspecialchars($reason,ENT_QUOTES)."'" : "")."><i class='fa fa-exclamation-triangle' aria-hidden='true'></i> "._('Update validation failed')."</span>";
202+
} else {
203+
@unlink($invalid);
204+
}
205+
}
206+
}
189207
if (strpos($status,'update')!==false) $rank = '0';
190208
elseif (strpos($status,'install')!==false) $rank = '1';
209+
elseif (strpos($status,'Update validation failed')!==false) $rank = '0';
191210
elseif ($status=='need check') $rank = '2';
192211
elseif ($status=='up-to-date') $rank = '3';
193212
else $rank = '4';

emhttp/plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ case 'plugin':
4242
case 'update':
4343
// abort if method was unsuccessful
4444
if ($error) break;
45+
// a successful install/update clears any prior validation-failure marker
46+
@unlink("/tmp/plugins/$name.invalid");
4547
// update support link in plugin file
4648
$info = readJson('/tmp/community.applications/tempFiles/templates.json');
4749
// find matching support link

emhttp/plugins/dynamix.plugin.manager/pre-hooks/pre_plugin_checks

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,31 @@ case 'plugin':
3939
// validate plugin update (not applicable to OS updates)
4040
if (in_array($name, $unraid)) break;
4141
$new_plugin = "/tmp/plugins/$name";
42+
$invalid = "/tmp/plugins/$name.invalid";
4243
if (plugin('version', $new_plugin) > plugin('version', $plugin)) {
4344
echo "Validating $name update\n";
44-
if (($status = plugin('validate', $new_plugin)) != 'valid') {
45-
echo "$status\n";
45+
$new_version = plugin('version', $new_plugin);
46+
// scripts/plugin exits non-zero and prints "plugin: <reason>" on failure
47+
// (bad hash, or the update files failing to download for the hash check)
48+
$output = [];
49+
exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin validate ".escapeshellarg($new_plugin)." 2>&1", $output, $retval);
50+
if ($retval != 0) {
51+
$reason = trim(preg_replace('/^plugin:\s*/m', '', implode("\n", $output)));
52+
echo ($reason ?: 'validation failed')."\n";
53+
// An update is available but failed validation. Record why so the webGUI
54+
// can surface it, instead of silently reverting to "up-to-date". The most
55+
// common cause is the update files not downloading because the root
56+
// filesystem is full.
57+
file_put_contents($invalid, json_encode(['version'=>$new_version, 'reason'=>$reason]));
4658
// restore original plugin and undo update
4759
copy($plugin, $new_plugin);
60+
} else {
61+
// validation passed - clear any stale failure marker
62+
@unlink($invalid);
4863
}
64+
} else {
65+
// no newer version available - clear any stale failure marker
66+
@unlink($invalid);
4967
}
5068
break;
5169
}

0 commit comments

Comments
 (0)