diff --git a/.gitignore b/.gitignore index 38eeaa479..09bc9f45b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules /build /.svelte-kit /package +/yarn.lock .env .env.prod diff --git a/package.json b/package.json index d0848ba73..4f3fc8ef4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "2.0.10", + "version": "2.0.11", "license": "AGPL-3.0", "scripts": { "dev": "docker compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0", diff --git a/src/lib/database/applications.ts b/src/lib/database/applications.ts index d7d2a5d8a..738ebe594 100644 --- a/src/lib/database/applications.ts +++ b/src/lib/database/applications.ts @@ -59,10 +59,14 @@ export async function removeApplication({ id, teamId }) { const id = containerObj.ID; const preview = containerObj.Image.split('-')[1]; await removeDestinationDocker({ id, engine: destinationDocker.engine }); - if (preview) { - await removeProxyConfiguration({ domain: `${preview}.${domain}` }); - } else { - await removeProxyConfiguration({ domain }); + try { + if (preview) { + await removeProxyConfiguration({ domain: `${preview}.${domain}` }); + } else { + await removeProxyConfiguration({ domain }); + } + } catch (error) { + console.log(error); } } } diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte index d8e185a13..027a11e3d 100644 --- a/src/routes/__layout.svelte +++ b/src/routes/__layout.svelte @@ -96,10 +96,9 @@ async function update() { updateStatus.loading = true; - // if (!dev) { try { await post(`/update.json`, { type: 'update', latestVersion }); - toast.push('Update completed. Waiting for the new version to start...'); + toast.push('Update completed.
Waiting for the new version to start...'); let reachable = false; let tries = 0; do { @@ -119,10 +118,9 @@ await asyncSleep(3000); return window.location.reload(); } catch ({ error }) { - return errorNotification(error); - } finally { updateStatus.success = false; updateStatus.loading = false; + return errorNotification(error); } } diff --git a/src/routes/applications/[id]/logs/build/_BuildLog.svelte b/src/routes/applications/[id]/logs/build/_BuildLog.svelte index 98f080dd8..839621f28 100644 --- a/src/routes/applications/[id]/logs/build/_BuildLog.svelte +++ b/src/routes/applications/[id]/logs/build/_BuildLog.svelte @@ -15,16 +15,32 @@ let loading = true; let currentStatus; let streamInterval; + let followingBuild; + let followingInterval; + let logsEl; const { id } = $page.params; + const cleanAnsiCodes = (str: string) => str.replace(/\x1B\[(\d+)m/g, ''); + + function followBuild() { + followingBuild = !followingBuild; + if (followingBuild) { + followingInterval = setInterval(() => { + logsEl.scrollTop = logsEl.scrollHeight; + window.scrollTo(0, document.body.scrollHeight); + }, 100); + } else { + window.clearInterval(followingInterval); + } + } async function streamLogs(sequence = 0) { try { let { logs: responseLogs, status } = await get( `/applications/${id}/logs/build/build.json?buildId=${buildId}&sequence=${sequence}` ); currentStatus = status; - logs = logs.concat(responseLogs); + logs = logs.concat(responseLogs.map((log) => ({ ...log, line: cleanAnsiCodes(log.line) }))); loading = false; streamInterval = setInterval(async () => { if (status !== 'running') { @@ -38,8 +54,13 @@ ); status = data.status; currentStatus = status; - logs = logs.concat(data.logs); + + logs = logs.concat(data.logs.map((log) => ({ ...log, line: cleanAnsiCodes(log.line) }))); dispatch('updateBuildStatus', { status }); + if (followingBuild) { + const logEl = document.getElementById('logs'); + logEl.scrollTop = logEl.scrollHeight; + } } catch ({ error }) { return errorNotification(error); } @@ -50,6 +71,7 @@ } onDestroy(() => { clearInterval(streamInterval); + clearInterval(followingInterval); }); onMount(async () => { window.scrollTo(0, 0); @@ -60,12 +82,37 @@ {#if loading} {:else} -
+
{#if currentStatus === 'running'} {/if} +
+ +
{#each logs as log}
{log.line + '\n'}
diff --git a/src/routes/applications/[id]/logs/build/index.svelte b/src/routes/applications/[id]/logs/build/index.svelte index 28740e031..2c43c1c29 100644 --- a/src/routes/applications/[id]/logs/build/index.svelte +++ b/src/routes/applications/[id]/logs/build/index.svelte @@ -33,7 +33,6 @@ export let buildCount; let buildId; - $: buildId; let skip = 0; let noMoreBuilds = buildCount < 5 || buildCount <= skip; @@ -92,45 +91,47 @@ Build logs of {getDomain(application.fqdn)}
-
-
- {#each builds as build (build.id)} -
loadBuild(build.id)} - class="tooltip-top flex cursor-pointer items-center justify-center rounded-r border-l-2 border-transparent py-4 no-underline transition-all duration-100 hover:bg-coolgray-400 hover:shadow-xl" - class:bg-coolgray-400={buildId === build.id} - class:border-red-500={build.status === 'failed'} - class:border-green-500={build.status === 'success'} - class:border-yellow-500={build.status === 'inprogress'} - > -
-
- {application.branch} +
+
+
+ {#each builds as build (build.id)} +
loadBuild(build.id)} + class="tooltip-top flex cursor-pointer items-center justify-center rounded-r border-l-2 border-transparent py-4 no-underline transition-all duration-100 hover:bg-coolgray-400 hover:shadow-xl " + class:bg-coolgray-400={buildId === build.id} + class:border-red-500={build.status === 'failed'} + class:border-green-500={build.status === 'success'} + class:border-yellow-500={build.status === 'inprogress'} + > +
+
+ {application.branch} +
+
+ {build.type} +
-
- {build.type} -
-
-
+
-
- {#if build.status === 'running'} -
Running
- {:else} -
{build.since}
-
Finished in {build.took}s
- {/if} +
+ {#if build.status === 'running'} +
Running
+ {:else} +
{build.since}
+
Finished in {build.took}s
+ {/if} +
-
- {/each} - {#if buildCount > 0 && !noMoreBuilds} - - {/if} + {/each} +
+
+ +
-
+
{#if buildId} {#key buildId} diff --git a/src/routes/applications/[id]/logs/index.svelte b/src/routes/applications/[id]/logs/index.svelte index ae45475fe..e558934a0 100644 --- a/src/routes/applications/[id]/logs/index.svelte +++ b/src/routes/applications/[id]/logs/index.svelte @@ -27,19 +27,23 @@ import { getDomain } from '$lib/components/common'; import { get } from '$lib/api'; import { errorNotification } from '$lib/form'; + let loadLogsInterval = null; let logs = []; + let followingBuild; + let followingInterval; + let logsEl; const { id } = $page.params; - onMount(async () => { loadLogs(); loadLogsInterval = setInterval(() => { loadLogs(); - }, 3000); + }, 1000); }); onDestroy(() => { clearInterval(loadLogsInterval); + clearInterval(followingInterval); }); async function loadLogs() { try { @@ -50,6 +54,18 @@ return errorNotification(error); } } + + function followBuild() { + followingBuild = !followingBuild; + if (followingBuild) { + followingInterval = setInterval(() => { + logsEl.scrollTop = logsEl.scrollHeight; + window.scrollTo(0, document.body.scrollHeight); + }, 100); + } else { + window.clearInterval(followingInterval); + } + }
@@ -63,8 +79,33 @@ {:else}
+
+ +
{#each logs as log} {log + '\n'} diff --git a/src/routes/update.json.ts b/src/routes/update.json.ts index 5c0e1581e..1cfdc5f50 100644 --- a/src/routes/update.json.ts +++ b/src/routes/update.json.ts @@ -36,8 +36,6 @@ export const post: RequestHandler = async (event) => { body: {} }; } else { - await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`); - await asyncSleep(2000); return { status: 200, body: {} diff --git a/src/routes/webhooks/github/events.ts b/src/routes/webhooks/github/events.ts index a370dc42c..77370d9e5 100644 --- a/src/routes/webhooks/github/events.ts +++ b/src/routes/webhooks/github/events.ts @@ -5,6 +5,7 @@ import cuid from 'cuid'; import crypto from 'crypto'; import { buildQueue } from '$lib/queues'; import { checkContainer, removeProxyConfiguration } from '$lib/haproxy'; +import { dev } from '$app/env'; export const options: RequestHandler = async () => { return { @@ -22,8 +23,8 @@ export const post: RequestHandler = async (event) => { const buildId = cuid(); const allowedGithubEvents = ['push', 'pull_request']; const allowedActions = ['opened', 'reopened', 'synchronize', 'closed']; - const githubEvent = event.request.headers.get('x-github-event').toLowerCase(); - const githubSignature = event.request.headers.get('x-hub-signature-256').toLowerCase(); + const githubEvent = event.request.headers.get('x-github-event')?.toLowerCase(); + const githubSignature = event.request.headers.get('x-hub-signature-256')?.toLowerCase(); if (!allowedGithubEvents.includes(githubEvent)) { return { status: 500, @@ -34,7 +35,6 @@ export const post: RequestHandler = async (event) => { } let repository, projectId, branch; const body = await event.request.json(); - if (githubEvent === 'push') { repository = body.repository; projectId = repository.id; @@ -54,14 +54,17 @@ export const post: RequestHandler = async (event) => { 'utf8' ); const checksum = Buffer.from(githubSignature, 'utf8'); - if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) { - return { - status: 500, - body: { - message: 'SHA256 checksum failed. Are you doing something fishy?' - } - }; + if (!dev) { + if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) { + return { + status: 500, + body: { + message: 'SHA256 checksum failed. Are you doing something fishy?' + } + }; + } } + if (githubEvent === 'push') { if (!applicationFound.configHash) { const configHash = crypto @@ -120,7 +123,11 @@ export const post: RequestHandler = async (event) => { }; } } - if (pullmergeRequestAction === 'opened' || pullmergeRequestAction === 'reopened') { + if ( + pullmergeRequestAction === 'opened' || + pullmergeRequestAction === 'reopened' || + pullmergeRequestAction === 'synchronize' + ) { await buildQueue.add(buildId, { build_id: buildId, type: 'webhook_pr', diff --git a/src/tailwind.css b/src/tailwind.css index fec74b8cd..532cc655a 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -69,7 +69,7 @@ a { } .nav-side { - @apply absolute right-0 top-0 z-50 m-5 flex items-center justify-end space-x-2 bg-coolblack/40 text-white; + @apply relative right-0 top-0 z-50 m-5 flex flex-wrap items-center justify-end space-x-2 bg-coolblack/40 text-white sm:absolute; } .add-icon {