Address CodeRabbit review feedback
- Fix null-safe operator on currentTeam() call in Upgrade.php - Add --rm flag to docker run in upgrade.sh for cleanup consistency - Store beforeunload handler as named reference and clean up on success - Add clarifying comments for upgrade method calls - Add error state handling with close option in upgrade modal - Add step mapping documentation comment in upgrade-progress component 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
dc12cbc6a0
commit
20a9855c04
4 changed files with 78 additions and 7 deletions
|
|
@ -55,7 +55,7 @@ public function upgrade()
|
||||||
public function getUpgradeStatus(): array
|
public function getUpgradeStatus(): array
|
||||||
{
|
{
|
||||||
// Only root team members can view upgrade status
|
// Only root team members can view upgrade status
|
||||||
if (auth()->user()?->currentTeam()->id !== 0) {
|
if (auth()->user()?->currentTeam()?->id !== 0) {
|
||||||
return ['status' => 'none'];
|
return ['status' => 'none'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
@props(['step' => 0])
|
@props(['step' => 0])
|
||||||
|
|
||||||
|
{{--
|
||||||
|
Step Mapping (Backend → UI):
|
||||||
|
Backend steps 1-2 (config download, env update) → UI Step 1: Preparing
|
||||||
|
Backend step 3 (pulling images) → UI Step 2: Helper + UI Step 3: Image
|
||||||
|
Backend steps 4-5 (stop/start containers) → UI Step 4: Restart
|
||||||
|
Backend step 6 (complete) → mapped in JS mapStepToUI() in upgrade.blade.php
|
||||||
|
|
||||||
|
The currentStep variable is inherited from parent Alpine component (upgradeModal).
|
||||||
|
--}}
|
||||||
<div class="w-full max-w-md mx-auto" x-data="{ activeStep: {{ $step }} }" x-effect="activeStep = $el.closest('[x-data]')?.__x?.$data?.currentStep ?? {{ $step }}">
|
<div class="w-full max-w-md mx-auto" x-data="{ activeStep: {{ $step }} }" x-effect="activeStep = $el.closest('[x-data]')?.__x?.$data?.currentStep ?? {{ $step }}">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
{{-- Step 1: Preparing --}}
|
{{-- Step 1: Preparing --}}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class="relative w-full py-6 border rounded-sm min-w-full lg:min-w-[36rem] max-w-
|
||||||
{{ $currentVersion }} <span class="mx-1">→</span> {{ $latestVersion }}
|
{{ $currentVersion }} <span class="mx-1">→</span> {{ $latestVersion }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button x-show="!showProgress" @click="modalOpen=false"
|
<button x-show="!showProgress || upgradeError" @click="upgradeError ? closeErrorModal() : modalOpen=false"
|
||||||
class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50 dark:text-neutral-400 dark:hover:text-white dark:hover:bg-coolgray-300">
|
class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50 dark:text-neutral-400 dark:hover:text-white dark:hover:bg-coolgray-300">
|
||||||
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||||
stroke-width="1.5" stroke="currentColor">
|
stroke-width="1.5" stroke="currentColor">
|
||||||
|
|
@ -79,7 +79,7 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5
|
||||||
{{-- Current Status Message --}}
|
{{-- Current Status Message --}}
|
||||||
<div class="p-4 rounded-lg bg-neutral-200 dark:bg-coolgray-200">
|
<div class="p-4 rounded-lg bg-neutral-200 dark:bg-coolgray-200">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<template x-if="!upgradeComplete">
|
<template x-if="!upgradeComplete && !upgradeError">
|
||||||
<svg class="w-5 h-5 text-warning animate-spin"
|
<svg class="w-5 h-5 text-warning animate-spin"
|
||||||
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
|
||||||
|
|
@ -97,6 +97,14 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5
|
||||||
clip-rule="evenodd" />
|
clip-rule="evenodd" />
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
<template x-if="upgradeError">
|
||||||
|
<svg class="w-5 h-5 text-error" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
|
||||||
|
clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
<span x-text="currentStatus" class="text-sm"></span>
|
<span x-text="currentStatus" class="text-sm"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -113,6 +121,18 @@ class="font-bold text-warning"></span> seconds...
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
{{-- Error State with Close Button --}}
|
||||||
|
<template x-if="upgradeError">
|
||||||
|
<div class="flex flex-col items-center gap-4">
|
||||||
|
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
||||||
|
Check the logs on the server at /data/coolify/source/upgrade*.
|
||||||
|
</p>
|
||||||
|
<x-forms.button @click="closeErrorModal()" type="button">
|
||||||
|
Close
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -168,6 +188,7 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||||
elapsedTime: 0,
|
elapsedTime: 0,
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
upgradeComplete: false,
|
upgradeComplete: false,
|
||||||
|
upgradeError: false,
|
||||||
successCountdown: 3,
|
successCountdown: 3,
|
||||||
currentVersion: config.currentVersion || '',
|
currentVersion: config.currentVersion || '',
|
||||||
latestVersion: config.latestVersion || '',
|
latestVersion: config.latestVersion || '',
|
||||||
|
|
@ -178,12 +199,16 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||||
this.currentStep = 1;
|
this.currentStep = 1;
|
||||||
this.currentStatus = 'Starting upgrade...';
|
this.currentStatus = 'Starting upgrade...';
|
||||||
this.startTimer();
|
this.startTimer();
|
||||||
|
// Trigger server-side upgrade script via Livewire
|
||||||
this.$wire.$call('upgrade');
|
this.$wire.$call('upgrade');
|
||||||
|
// Start client-side status polling
|
||||||
this.upgrade();
|
this.upgrade();
|
||||||
window.addEventListener('beforeunload', (event) => {
|
// Prevent accidental navigation during upgrade
|
||||||
|
this.beforeUnloadHandler = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.returnValue = '';
|
event.returnValue = '';
|
||||||
});
|
};
|
||||||
|
window.addEventListener('beforeunload', this.beforeUnloadHandler);
|
||||||
},
|
},
|
||||||
|
|
||||||
startTimer() {
|
startTimer() {
|
||||||
|
|
@ -259,6 +284,11 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||||
clearInterval(this.elapsedInterval);
|
clearInterval(this.elapsedInterval);
|
||||||
this.elapsedInterval = null;
|
this.elapsedInterval = null;
|
||||||
}
|
}
|
||||||
|
// Remove beforeunload handler now that upgrade is complete
|
||||||
|
if (this.beforeUnloadHandler) {
|
||||||
|
window.removeEventListener('beforeunload', this.beforeUnloadHandler);
|
||||||
|
this.beforeUnloadHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.upgradeComplete = true;
|
this.upgradeComplete = true;
|
||||||
this.currentStep = 5;
|
this.currentStep = 5;
|
||||||
|
|
@ -278,6 +308,38 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showError(message) {
|
||||||
|
// Stop all intervals
|
||||||
|
if (this.checkHealthInterval) {
|
||||||
|
clearInterval(this.checkHealthInterval);
|
||||||
|
this.checkHealthInterval = null;
|
||||||
|
}
|
||||||
|
if (this.checkUpgradeStatusInterval) {
|
||||||
|
clearInterval(this.checkUpgradeStatusInterval);
|
||||||
|
this.checkUpgradeStatusInterval = null;
|
||||||
|
}
|
||||||
|
if (this.elapsedInterval) {
|
||||||
|
clearInterval(this.elapsedInterval);
|
||||||
|
this.elapsedInterval = null;
|
||||||
|
}
|
||||||
|
// Remove beforeunload handler so user can close modal
|
||||||
|
if (this.beforeUnloadHandler) {
|
||||||
|
window.removeEventListener('beforeunload', this.beforeUnloadHandler);
|
||||||
|
this.beforeUnloadHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.upgradeError = true;
|
||||||
|
this.currentStatus = `Error: ${message}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
closeErrorModal() {
|
||||||
|
this.modalOpen = false;
|
||||||
|
this.showProgress = false;
|
||||||
|
this.upgradeError = false;
|
||||||
|
this.currentStatus = '';
|
||||||
|
this.currentStep = 0;
|
||||||
|
},
|
||||||
|
|
||||||
upgrade() {
|
upgrade() {
|
||||||
if (this.checkUpgradeStatusInterval) return true;
|
if (this.checkUpgradeStatusInterval) return true;
|
||||||
this.currentStep = 1;
|
this.currentStep = 1;
|
||||||
|
|
@ -294,7 +356,7 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
|
||||||
} else if (data.status === 'complete') {
|
} else if (data.status === 'complete') {
|
||||||
this.showSuccess();
|
this.showSuccess();
|
||||||
} else if (data.status === 'error') {
|
} else if (data.status === 'error') {
|
||||||
this.currentStatus = `Error: ${data.message}`;
|
this.showError(data.message);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Service is down - switch to health check mode
|
// Service is down - switch to health check mode
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ nohup bash -c "
|
||||||
else
|
else
|
||||||
log 'Using standard docker-compose configuration'
|
log 'Using standard docker-compose configuration'
|
||||||
log 'Running docker compose up...'
|
log 'Running docker compose up...'
|
||||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock \${DOCKER_CONFIG_MOUNT} \${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-helper:\${LATEST_HELPER_VERSION} bash -c \"LATEST_IMAGE=\${LATEST_IMAGE} docker compose --project-name coolify --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --wait --wait-timeout 60\" >>\"\$LOGFILE\" 2>&1
|
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock \${DOCKER_CONFIG_MOUNT} --rm \${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-helper:\${LATEST_HELPER_VERSION} bash -c \"LATEST_IMAGE=\${LATEST_IMAGE} docker compose --project-name coolify --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --wait --wait-timeout 60\" >>\"\$LOGFILE\" 2>&1
|
||||||
fi
|
fi
|
||||||
log 'Docker compose up completed'
|
log 'Docker compose up completed'
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue