fix(wg): remove SSH hint from setup form + time out a non-responding host (no endless spinner)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat/v1-foundation v0.9.39
boban 2026-06-21 08:38:43 +02:00
parent a064e8eeb8
commit e55e3cc61c
7 changed files with 41 additions and 5 deletions

View File

@ -13,6 +13,19 @@ getaggte Releases (Kanal `stable`, optional `beta`) — niemals Entwicklungs-Bui
_Keine offenen Änderungen — der nächste Stand wird hier gesammelt und als `vX.Y.Z` getaggt._
## [0.9.39] - 2026-06-21
### Geändert
- **WireGuard-Einrichtung: SSH-Hinweis von der Seite entfernt.** Das `sudo clusev wg setup` steht
jetzt nur noch in der Hilfe — die Einrichtung läuft über das Dashboard-Formular.
### Behoben
- **Kein ewiges „Wird angewendet …" mehr.** Antwortet der Host-Dienst nicht (z. B. weil der Stack
noch nicht auf eine Version mit dem Host-Watcher aktualisiert wurde), bricht die Dashboard-Aktion
nach ~30 s mit einer klaren Meldung ab, statt unbegrenzt zu warten. (Hinweis: Peer-Verwaltung +
Einrichtung aus dem Dashboard benötigen den per `sudo clusev update` installierten Host-Watcher —
auf einem reinen Dev-Stack ohne diesen läuft die Brücke nicht.)
## [0.9.38] - 2026-06-21
### Hinzugefügt

View File

@ -47,6 +47,9 @@ class Index extends Component
public ?string $pendingAction = null;
/** Unix time the current request started polling — used to time out a non-responding host. */
public ?int $pendingSince = null;
/** Show-once add-peer result (config text + QR svg). Never persisted. */
public ?string $resultConfig = null;
@ -297,11 +300,22 @@ class Index extends Component
if ($this->pendingId === null) {
return;
}
$this->pendingSince ??= time(); // first poll after a request — start the clock
$res = $bridge->result($this->pendingId);
if ($res === null) {
// No host response after a while → the host watcher (systemd) likely isn't running yet.
// Stop spinning forever and tell the operator instead of leaving "Wird angewendet …".
if (time() - $this->pendingSince > 30) {
$this->pendingId = null;
$this->pendingAction = null;
$this->pendingSince = null;
$this->dispatch('notify', message: __('wireguard.no_host_response'), level: 'error');
}
return;
}
$this->pendingId = null;
$this->pendingSince = null;
if ($res['ok'] && in_array($this->pendingAction, ['add-peer', 'setup'], true) && $res['config'] !== null) {
$this->resultConfig = $res['config'];
$this->resultQr = $res['qr'];

View File

@ -2,7 +2,7 @@
return [
// First tagged release is v0.1.0 (semantic, not -dev).
'version' => '0.9.38',
'version' => '0.9.39',
// Deployed commit + branch. install.sh bakes these into .env from the host's .git (the prod
// image ships no .git); the Versions page prefers them and falls back to a live .git read in

View File

@ -76,5 +76,5 @@ return [
'setup_endpoint_hint' => 'Leer = automatisch erkannte öffentliche IP. Hinter NAT/Cloud-LB manuell setzen.',
'setup_peer' => 'Name des ersten Clients',
'setup_submit' => 'Einrichten',
'setup_or_ssh' => 'Alternativ per SSH:',
'no_host_response' => 'Keine Antwort vom Host — der WireGuard-Host-Dienst läuft nicht. Stack aktualisieren (Version-Seite) und erneut versuchen.',
];

View File

@ -76,5 +76,5 @@ return [
'setup_endpoint_hint' => 'Empty = auto-detected public IP. Behind NAT/cloud LB set it manually.',
'setup_peer' => 'First client name',
'setup_submit' => 'Set up',
'setup_or_ssh' => 'Or over SSH:',
'no_host_response' => 'No response from the host — the WireGuard host service is not running. Update the stack (Versions page) and try again.',
];

View File

@ -59,8 +59,6 @@
@endif
</div>
</form>
<p class="mt-4 font-mono text-[11px] text-ink-4">{{ __('wireguard.setup_or_ssh') }}</p>
<pre class="mt-1 overflow-x-auto rounded-md border border-line bg-void px-3 py-2.5 font-mono text-[11px] text-ink-2">sudo clusev wg setup</pre>
</x-panel>
@else
@if ($status['stale'])

View File

@ -161,4 +161,15 @@ class WireguardPageTest extends TestCase
->call('setupWg')
->assertHasErrors('setupSubnet');
}
public function test_poll_result_times_out_when_the_host_does_not_respond(): void
{
// A pending request with no host result for >30s must stop spinning, not poll forever.
Livewire::test(Index::class)
->set('pendingId', 'AAAAAAAAAAAAAAAAbbbbcccc')
->set('pendingSince', time() - 31)
->call('pollResult')
->assertSet('pendingId', null)
->assertSet('pendingSince', null);
}
}