diff --git a/AGENTS.md b/AGENTS.md index 2fb5be7f2..86fc0f00b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,6 +30,25 @@ docker compose -f docker-compose.yml -f docker-compose.dev.yml down 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 diff --git a/resources/views/livewire/upgrade.blade.php b/resources/views/livewire/upgrade.blade.php index b476704f7..eb6c60136 100644 --- a/resources/views/livewire/upgrade.blade.php +++ b/resources/views/livewire/upgrade.blade.php @@ -281,11 +281,24 @@ 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); } diff --git a/tests/Unit/CoolifyUpgradeStatusTest.php b/tests/Unit/CoolifyUpgradeStatusTest.php index 0ce2e7e88..b57afe5d2 100644 --- a/tests/Unit/CoolifyUpgradeStatusTest.php +++ b/tests/Unit/CoolifyUpgradeStatusTest.php @@ -139,6 +139,16 @@ it('uses the public health endpoint only for liveness during an upgrade', functi ->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');