Merge pull request #413 from coollabsio/next

v2.7.0 again
This commit is contained in:
Andras Bacsai 2022-05-06 15:40:30 +02:00 committed by GitHub
commit 6a3f4ba171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 145 deletions

View File

@ -114,5 +114,5 @@ export const getSession: GetSession = function ({ locals }) {
}; };
export async function handleError({ error, event }) { export async function handleError({ error, event }) {
if (!dev) sentry.captureException(error, event); // if (!dev) sentry.captureException(error, event);
} }

View File

@ -20,21 +20,21 @@ import { t } from './translations';
try { try {
if (!dev) { if (!dev) {
Sentry.init({ // Sentry.init({
dsn: process.env['COOLIFY_SENTRY_DSN'], // dsn: process.env['COOLIFY_SENTRY_DSN'],
tracesSampleRate: 0, // tracesSampleRate: 0,
environment: 'production', // environment: 'production',
debug: true, // debug: true,
release: currentVersion, // release: currentVersion,
initialScope: { // initialScope: {
tags: { // tags: {
appId: process.env['COOLIFY_APP_ID'], // appId: process.env['COOLIFY_APP_ID'],
'os.arch': getOsArch(), // 'os.arch': getOsArch(),
'os.platform': os.platform(), // 'os.platform': os.platform(),
'os.release': os.release() // 'os.release': os.release()
} // }
} // }
}); // });
} }
} catch (err) { } catch (err) {
console.log('Could not initialize Sentry, no worries.'); console.log('Could not initialize Sentry, no worries.');

View File

@ -58,7 +58,7 @@ export function ErrorHandler(e: {
truncatedError.message = 'git clone failed'; truncatedError.message = 'git clone failed';
} }
if (!e.message?.includes('Coolify Proxy is not running')) { if (!e.message?.includes('Coolify Proxy is not running')) {
sentry.captureException(truncatedError); // sentry.captureException(truncatedError);
} }
const payload = { const payload = {
status: truncatedError.status || 500, status: truncatedError.status || 500,
@ -127,73 +127,73 @@ export function getServiceImages(type: string): string[] {
export function generateDatabaseConfiguration(database: Database & { settings: DatabaseSettings }): export function generateDatabaseConfiguration(database: Database & { settings: DatabaseSettings }):
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
MYSQL_DATABASE: string; MYSQL_DATABASE: string;
MYSQL_PASSWORD: string; MYSQL_PASSWORD: string;
MYSQL_ROOT_USER: string; MYSQL_ROOT_USER: string;
MYSQL_USER: string; MYSQL_USER: string;
MYSQL_ROOT_PASSWORD: string; MYSQL_ROOT_PASSWORD: string;
}; };
} }
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
MONGODB_ROOT_USER: string; MONGODB_ROOT_USER: string;
MONGODB_ROOT_PASSWORD: string; MONGODB_ROOT_PASSWORD: string;
}; };
} }
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
MARIADB_ROOT_USER: string; MARIADB_ROOT_USER: string;
MARIADB_ROOT_PASSWORD: string; MARIADB_ROOT_PASSWORD: string;
MARIADB_USER: string; MARIADB_USER: string;
MARIADB_PASSWORD: string; MARIADB_PASSWORD: string;
MARIADB_DATABASE: string; MARIADB_DATABASE: string;
}; };
} }
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
POSTGRESQL_POSTGRES_PASSWORD: string; POSTGRESQL_POSTGRES_PASSWORD: string;
POSTGRESQL_USERNAME: string; POSTGRESQL_USERNAME: string;
POSTGRESQL_PASSWORD: string; POSTGRESQL_PASSWORD: string;
POSTGRESQL_DATABASE: string; POSTGRESQL_DATABASE: string;
}; };
} }
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
REDIS_AOF_ENABLED: string; REDIS_AOF_ENABLED: string;
REDIS_PASSWORD: string; REDIS_PASSWORD: string;
}; };
} }
| { | {
volume: string; volume: string;
image: string; image: string;
ulimits: Record<string, unknown>; ulimits: Record<string, unknown>;
privatePort: number; privatePort: number;
environmentVariables: { environmentVariables: {
COUCHDB_PASSWORD: string; COUCHDB_PASSWORD: string;
COUCHDB_USER: string; COUCHDB_USER: string;
}; };
} { } {
const { const {
id, id,
dbUser, dbUser,

View File

@ -328,7 +328,7 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId });
} catch (error) { } catch (error) {
await saveBuildLog({ line: error, buildId, applicationId }); await saveBuildLog({ line: error, buildId, applicationId });
sentry.captureException(error); // sentry.captureException(error);
throw new Error(error); throw new Error(error);
} }
await saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId }); await saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId });

View File

@ -3,6 +3,61 @@ import { buildQueue } from '$lib/queues';
import type { RequestHandler } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit';
import * as db from '$lib/database'; import * as db from '$lib/database';
async function cleanupDB(buildId: string) {
const data = await db.prisma.build.findUnique({ where: { id: buildId } });
if (data?.status === 'queued' || data?.status === 'running') {
await db.prisma.build.update({ where: { id: buildId }, data: { status: 'failed' } });
}
}
async function stopBuild(buildId, applicationId) {
let count = 0;
await new Promise<void>(async (resolve, reject) => {
const job = await buildQueue.getJob(buildId);
if (!job) {
await cleanupDB(buildId);
return resolve();
}
const {
destinationDocker: { engine }
} = job?.data;
const host = getEngine(engine);
let interval = setInterval(async () => {
try {
const data = await db.prisma.build.findUnique({ where: { id: buildId } });
if (data?.status === 'failed') {
clearInterval(interval);
return resolve();
}
if (count > 100) {
clearInterval(interval);
return reject(new Error('Build canceled'));
}
const { stdout: buildContainers } = await asyncExecShell(
`DOCKER_HOST=${host} docker container ls --filter "label=coolify.buildId=${buildId}" --format '{{json .}}'`
);
if (buildContainers) {
const containersArray = buildContainers.trim().split('\n');
for (const container of containersArray) {
const containerObj = JSON.parse(container);
const id = containerObj.ID;
if (!containerObj.Names.startsWith(`${applicationId}`)) {
await removeDestinationDocker({ id, engine });
clearInterval(interval);
await saveBuildLog({
line: 'Canceled by user!',
buildId: job.data.build_id,
applicationId: job.data.id
});
}
}
}
count++;
} catch (error) {}
}, 100);
});
}
export const post: RequestHandler = async (event) => { export const post: RequestHandler = async (event) => {
const { buildId, applicationId } = await event.request.json(); const { buildId, applicationId } = await event.request.json();
if (!buildId) { if (!buildId) {
@ -14,57 +69,7 @@ export const post: RequestHandler = async (event) => {
}; };
} }
try { try {
let count = 0; await stopBuild(buildId, applicationId);
await new Promise<void>(async (resolve, reject) => {
const job = await buildQueue.getJob(buildId);
if (!job) {
return resolve();
}
const {
destinationDocker: { engine }
} = job?.data;
const host = getEngine(engine);
let interval = setInterval(async () => {
try {
const data = await db.prisma.build.findUnique({ where: { id: buildId } });
if (data?.status === 'failed') {
clearInterval(interval);
return resolve();
}
if (count > 60) {
clearInterval(interval);
reject(new Error('Could not cancel build.'));
}
const { stdout: buildContainers } = await asyncExecShell(
`DOCKER_HOST=${host} docker container ls --filter "label=coolify.buildId=${buildId}" --format '{{json .}}'`
);
if (buildContainers) {
const containersArray = buildContainers.trim().split('\n');
for (const container of containersArray) {
const containerObj = JSON.parse(container);
const id = containerObj.ID;
if (!containerObj.Names.startsWith(`${applicationId}`)) {
await removeDestinationDocker({ id, engine });
clearInterval(interval);
await saveBuildLog({
line: 'Canceled by user!',
buildId: job.data.build_id,
applicationId: job.data.id
});
}
}
}
count++;
} catch (error) {}
}, 1000);
resolve();
});
const data = await db.prisma.build.findUnique({ where: { id: buildId } });
if (data?.status === 'queued' || data?.status === 'running') {
await db.prisma.build.update({ where: { id: buildId }, data: { status: 'failed' } });
}
return { return {
status: 200, status: 200,
body: { body: {

View File

@ -129,23 +129,28 @@
{#if currentStatus === 'running'} {#if currentStatus === 'running'}
<button <button
on:click={cancelBuild} on:click={cancelBuild}
class:animation-spin={cancelInprogress}
class="bg-transparent hover:text-red-500 hover:bg-coolgray-500" class="bg-transparent hover:text-red-500 hover:bg-coolgray-500"
data-tooltip="Cancel build" data-tooltip="Cancel build"
> >
<svg {#if cancelInprogress}
xmlns="http://www.w3.org/2000/svg" Cancelling...
class="w-6 h-6" {:else}
viewBox="0 0 24 24" <svg
stroke-width="1.5" xmlns="http://www.w3.org/2000/svg"
stroke="currentColor" class="w-6 h-6"
fill="none" viewBox="0 0 24 24"
stroke-linecap="round" stroke-width="1.5"
stroke-linejoin="round" stroke="currentColor"
> fill="none"
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> stroke-linecap="round"
<circle cx="12" cy="12" r="9" /> stroke-linejoin="round"
<path d="M10 10l4 4m0 -4l-4 4" /> >
</svg> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="12" cy="12" r="9" />
<path d="M10 10l4 4m0 -4l-4 4" />
</svg>
{/if}
</button> </button>
{/if} {/if}
</div> </div>