fix(upgrade): handle status polling after older release restarts

Treat recovered health checks and polling errors as successful completion when older target releases cannot report upgrade status.
This commit is contained in:
Andras Bacsai 2026-08-13 14:30:47 +02:00
parent 6492d08136
commit 8576214a6d
3 changed files with 43 additions and 1 deletions

View file

@ -30,6 +30,25 @@ # Note: dual Vite HMR is unsupported (shared public/hot); multi-instance always
The app runs at `localhost:8000` by default. Instance **b** is on `8001` (db `5433`, redis `6380`, …); see `./scripts/dev-instances`.
## Testing the Self-Hosted Upgrade Process
Use the following workflow to test a self-hosted upgrade:
1. Install the source version with the upgrade script:
```bash
bash upgrade.sh sha-6492d081362c009519481ac70e50873e39ba1861
```
2. Set the current Coolify version and rebuild the cached configuration:
```bash
docker exec -e COOLIFY_VERSION=4.3.0 coolify php artisan config:cache
```
3. In the Coolify UI, click **Check for Updates**.
4. Confirm that an upgrade is available, then click **Upgrade** and verify that the upgrade completes successfully.
## Common Commands
```bash

View file

@ -281,11 +281,24 @@ class="flex flex-wrap items-center justify-end gap-2 border-t border-neutral-200
return;
}
const data = await this.$wire.getUpgradeStatus();
let data;
try {
data = await this.$wire.getUpgradeStatus();
} catch (error) {
if (this.instanceWentDown) {
this.showSuccess();
return;
}
throw error;
}
if (data.status === 'complete') {
this.showSuccess();
} else if (data.status === 'error') {
this.showError(data.message);
} else if (data.status === 'none' && this.instanceWentDown) {
// Older target releases cannot report the new upgrade status.
// A failed health probe followed by a healthy response proves the restart completed.
this.showSuccess();
} else {
this.currentStatus = data.message ?? this.getReviveStatusMessage(elapsedMinutes, this.healthCheckAttempts);
}

View file

@ -139,6 +139,16 @@
->not->toContain('response.headers.get');
});
it('finishes after health recovers from observed downtime for older target releases', function () {
$upgradeView = file_get_contents(__DIR__.'/../../resources/views/livewire/upgrade.blade.php');
expect($upgradeView)
->toContain("data.status === 'none' && this.instanceWentDown")
->toContain('if (this.instanceWentDown) {')
->toContain('this.showSuccess();')
->toContain('return;');
});
it('starts the upgrade after the Livewire response so status polling is not blocked', function () {
$upgradeComponent = file_get_contents(__DIR__.'/../../app/Livewire/Upgrade.php');