feat: Coolify auto-updater

This commit is contained in:
Andras Bacsai
2022-04-25 09:54:28 +02:00
parent 8290ee856f
commit 11d74c0c1f
9 changed files with 118 additions and 9 deletions

View File

@@ -302,7 +302,9 @@
"registration_allowed": "Registration allowed?",
"registration_allowed_explainer": "Allow further registrations to the application. <br>It's turned off after the first registration.",
"coolify_proxy_settings": "Coolify Proxy Settings",
"credential_stat_explainer": "Credentials for <a class=\"text-white font-bold\" href=\"{{link}}\" target=\"_blank\">stats</a> page."
"credential_stat_explainer": "Credentials for <a class=\"text-white font-bold\" href=\"{{link}}\" target=\"_blank\">stats</a> page.",
"auto_update_enabled": "Auto update enabled?",
"auto_update_enabled_explainer": "Enable automatic updates for Coolify."
},
"team": {
"pending_invitations": "Pending invitations",

View File

@@ -0,0 +1,39 @@
import { prisma } from '$lib/database';
import { buildQueue } from '.';
import got from 'got';
import { asyncExecShell, version } from '$lib/common';
import compare from 'compare-versions';
import { dev } from '$app/env';
export default async function (): Promise<void> {
const currentVersion = version;
const { isAutoUpdateEnabled } = await prisma.setting.findFirst();
if (isAutoUpdateEnabled) {
const versions = await got
.get(
`https://get.coollabs.io/versions.json?appId=${process.env['COOLIFY_APP_ID']}&version=${currentVersion}`
)
.json();
const latestVersion = versions['coolify'].main.version;
const isUpdateAvailable = compare(latestVersion, currentVersion);
if (isUpdateAvailable === 1) {
const activeCount = await buildQueue.getActiveCount();
if (activeCount === 0) {
if (!dev) {
console.log('Updating...');
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
await asyncExecShell(`env | grep COOLIFY > .env`);
await asyncExecShell(
`docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-redis && docker rm coolify coolify-redis && docker compose up -d --force-recreate"`
);
} else {
console.log('Updating (not really in dev mode).');
}
}
} else {
console.log('No update available.');
}
} else {
console.log('Auto update is disabled.');
}
}

View File

@@ -10,6 +10,7 @@ import proxy from './proxy';
import proxyTcpHttp from './proxyTcpHttp';
import ssl from './ssl';
import sslrenewal from './sslrenewal';
import autoUpdater from './autoUpdater';
import { asyncExecShell, saveBuildLog } from '$lib/common';
@@ -34,19 +35,22 @@ const cron = async (): Promise<void> => {
new QueueScheduler('cleanup', connectionOptions);
new QueueScheduler('ssl', connectionOptions);
new QueueScheduler('sslRenew', connectionOptions);
new QueueScheduler('autoUpdater', connectionOptions);
const queue = {
proxy: new Queue('proxy', { ...connectionOptions }),
proxyTcpHttp: new Queue('proxyTcpHttp', { ...connectionOptions }),
cleanup: new Queue('cleanup', { ...connectionOptions }),
ssl: new Queue('ssl', { ...connectionOptions }),
sslRenew: new Queue('sslRenew', { ...connectionOptions })
sslRenew: new Queue('sslRenew', { ...connectionOptions }),
autoUpdater: new Queue('autoUpdater', { ...connectionOptions })
};
await queue.proxy.drain();
await queue.proxyTcpHttp.drain();
await queue.cleanup.drain();
await queue.ssl.drain();
await queue.sslRenew.drain();
await queue.autoUpdater.drain();
new Worker(
'proxy',
@@ -98,11 +102,22 @@ const cron = async (): Promise<void> => {
}
);
new Worker(
'autoUpdater',
async () => {
await autoUpdater();
},
{
...connectionOptions
}
);
await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } });
await queue.proxyTcpHttp.add('proxyTcpHttp', {}, { repeat: { every: 10000 } });
await queue.ssl.add('ssl', {}, { repeat: { every: dev ? 10000 : 60000 } });
if (!dev) await queue.cleanup.add('cleanup', {}, { repeat: { every: 300000 } });
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
await queue.autoUpdater.add('autoUpdater', {}, { repeat: { every: 60000 } });
};
cron().catch((error) => {
console.log('cron failed to start');

View File

@@ -64,10 +64,14 @@ export const post: RequestHandler = async (event) => {
};
if (status === 401) return { status, body };
const { fqdn, isRegistrationEnabled, dualCerts, minPort, maxPort } = await event.request.json();
const { fqdn, isRegistrationEnabled, dualCerts, minPort, maxPort, isAutoUpdateEnabled } =
await event.request.json();
try {
const { id } = await db.listSettings();
await db.prisma.setting.update({ where: { id }, data: { isRegistrationEnabled, dualCerts } });
await db.prisma.setting.update({
where: { id },
data: { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled }
});
if (fqdn) {
await db.prisma.setting.update({ where: { id }, data: { fqdn } });
}

View File

@@ -40,10 +40,9 @@
import { toast } from '@zerodevx/svelte-toast';
import { t } from '$lib/translations';
import Language from './_Language.svelte';
let isRegistrationEnabled = settings.isRegistrationEnabled;
let dualCerts = settings.dualCerts;
let isAutoUpdateEnabled = settings.isAutoUpdateEnabled;
let minPort = settings.minPort;
let maxPort = settings.maxPort;
@@ -76,7 +75,10 @@
if (name === 'dualCerts') {
dualCerts = !dualCerts;
}
await post(`/settings.json`, { isRegistrationEnabled, dualCerts });
if (name === 'isAutoUpdateEnabled') {
isAutoUpdateEnabled = !isAutoUpdateEnabled;
}
await post(`/settings.json`, { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled });
return toast.push(t.get('application.settings_saved'));
} catch ({ error }) {
return errorNotification(error);
@@ -192,6 +194,14 @@
on:click={() => changeSettings('isRegistrationEnabled')}
/>
</div>
<div class="grid grid-cols-2 items-center">
<Setting
bind:setting={isAutoUpdateEnabled}
title={$t('setting.auto_update_enabled')}
description={$t('setting.auto_update_enabled_explainer')}
on:click={() => changeSettings('isAutoUpdateEnabled')}
/>
</div>
</div>
</form>
<div class="flex space-x-1 pt-6 font-bold">