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 {