diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts
index a96e36e91..dfdde81d2 100644
--- a/apps/api/src/lib/common.ts
+++ b/apps/api/src/lib/common.ts
@@ -17,7 +17,7 @@ import { day } from './dayjs';
import { saveBuildLog } from './buildPacks/common';
import { scheduler } from './scheduler';
-export const version = '3.11.4';
+export const version = '3.11.5';
export const isDev = process.env.NODE_ENV === 'development';
const algorithm = 'aes-256-ctr';
diff --git a/apps/ui/src/lib/components/UpdateAvailable.svelte b/apps/ui/src/lib/components/UpdateAvailable.svelte
index 9c4fda2be..5eeacab8b 100644
--- a/apps/ui/src/lib/components/UpdateAvailable.svelte
+++ b/apps/ui/src/lib/components/UpdateAvailable.svelte
@@ -16,9 +16,11 @@
updateStatus.loading = true;
try {
if (dev) {
- await asyncSleep(4000);
+ localStorage.setItem('lastVersion', $appSession.version);
+ await asyncSleep(1000);
return window.location.reload();
} else {
+ localStorage.setItem('lastVersion', $appSession.version);
await post(`/update`, { type: 'update', latestVersion });
addToast({
message: 'Update completed.
Waiting for the new version to start...',
diff --git a/apps/ui/src/routes/settings/coolify.svelte b/apps/ui/src/routes/settings/coolify.svelte
index cf3c21ddb..2c421751b 100644
--- a/apps/ui/src/routes/settings/coolify.svelte
+++ b/apps/ui/src/routes/settings/coolify.svelte
@@ -24,6 +24,7 @@
import { addToast, appSession, features } from '$lib/store';
import { asyncSleep, errorNotification, getDomain } from '$lib/common';
import Explainer from '$lib/components/Explainer.svelte';
+ import { dev } from '$app/env';
let isAPIDebuggingEnabled = settings.isAPIDebuggingEnabled;
let isRegistrationEnabled = settings.isRegistrationEnabled;
@@ -47,7 +48,50 @@
proxyMigration: false,
restart: false
};
+ let rollbackVersion = localStorage.getItem('lastVersion');
+ async function rollback() {
+ const sure = confirm(`Are you sure you want rollback Coolify to ${rollbackVersion}?`);
+ if (sure) {
+ try {
+ if (dev) {
+ console.log('rolling back to', rollbackVersion);
+ await asyncSleep(4000);
+ return window.location.reload();
+ } else {
+ await post(`/update`, { type: 'update', latestVersion: rollbackVersion });
+ addToast({
+ message: 'Update completed.
Waiting for the new version to start...',
+ type: 'success'
+ });
+
+ let reachable = false;
+ let tries = 0;
+ do {
+ await asyncSleep(4000);
+ try {
+ await get(`/undead`);
+ reachable = true;
+ } catch (error) {
+ reachable = false;
+ }
+ if (reachable) break;
+ tries++;
+ } while (!reachable || tries < 120);
+ addToast({
+ message: 'New version reachable. Reloading...',
+ type: 'success'
+ });
+ await asyncSleep(3000);
+ return window.location.reload();
+ }
+ } catch (error) {
+ return errorNotification(error);
+ } finally {
+ loading.remove = false;
+ }
+ }
+ }
async function removeFqdn() {
if (fqdn) {
loading.remove = true;
@@ -281,6 +325,17 @@
{/if}
+