feat: Cancel builds!
This commit is contained in:
71
src/routes/applications/[id]/cancel.json.ts
Normal file
71
src/routes/applications/[id]/cancel.json.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { asyncExecShell, getEngine, removeDestinationDocker, saveBuildLog } from '$lib/common';
|
||||
import { buildQueue } from '$lib/queues';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import * as db from '$lib/database';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
const { buildId, applicationId } = await event.request.json();
|
||||
if (!buildId) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
message: 'Build ID not found.'
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
let count = 0;
|
||||
await new Promise(async (resolve, reject) => {
|
||||
const job = await buildQueue.getJob(buildId);
|
||||
const {
|
||||
destinationDocker: { engine }
|
||||
} = job.data;
|
||||
const host = getEngine(engine);
|
||||
let interval = setInterval(async () => {
|
||||
console.log(`Checking build ${buildId}, try ${count}`);
|
||||
if (count > 100) {
|
||||
clearInterval(interval);
|
||||
reject(new Error('Could not cancel build.'));
|
||||
}
|
||||
try {
|
||||
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);
|
||||
|
||||
resolve('Canceled');
|
||||
});
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
message: 'Build canceled.'
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -45,15 +45,23 @@ export const post: RequestHandler = async (event) => {
|
||||
}
|
||||
});
|
||||
if (pullmergeRequestId) {
|
||||
await buildQueue.add(buildId, {
|
||||
build_id: buildId,
|
||||
type: 'manual',
|
||||
...applicationFound,
|
||||
sourceBranch: branch,
|
||||
pullmergeRequestId
|
||||
});
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{
|
||||
build_id: buildId,
|
||||
type: 'manual',
|
||||
...applicationFound,
|
||||
sourceBranch: branch,
|
||||
pullmergeRequestId
|
||||
},
|
||||
{ jobId: buildId }
|
||||
);
|
||||
} else {
|
||||
await buildQueue.add(buildId, { build_id: buildId, type: 'manual', ...applicationFound });
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{ build_id: buildId, type: 'manual', ...applicationFound },
|
||||
{ jobId: buildId }
|
||||
);
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
|
||||
@@ -339,6 +339,7 @@
|
||||
isClearable={false}
|
||||
/>
|
||||
</div>
|
||||
<Explainer text={$t('application.base_image_explainer')} />
|
||||
</div>
|
||||
{#if application.buildCommand || application.buildPack === 'rust' || application.buildPack === 'laravel'}
|
||||
<div class="grid grid-cols-2 items-center pb-8">
|
||||
@@ -360,6 +361,8 @@
|
||||
</div>
|
||||
{#if application.buildPack === 'laravel'}
|
||||
<Explainer text="For building frontend assets with webpack." />
|
||||
{:else}
|
||||
<Explainer text={$t('application.base_build_image_explainer')} />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Loading from '$lib/components/Loading.svelte';
|
||||
import LoadingLogs from '../_Loading.svelte';
|
||||
import { get } from '$lib/api';
|
||||
import { get, post } from '$lib/api';
|
||||
import { errorNotification } from '$lib/form';
|
||||
import { t } from '$lib/translations';
|
||||
|
||||
@@ -67,6 +67,12 @@
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
async function cancelBuild() {
|
||||
return await post(`/applications/${id}/cancel.json`, {
|
||||
buildId,
|
||||
applicationId: id
|
||||
});
|
||||
}
|
||||
onDestroy(() => {
|
||||
clearInterval(streamInterval);
|
||||
clearInterval(followingInterval);
|
||||
@@ -111,7 +117,26 @@
|
||||
<line x1="16" y1="12" x2="12" y2="16" />
|
||||
</svg>
|
||||
</button>
|
||||
{#if currentStatus === 'running'}
|
||||
<button on:click={cancelBuild} class="bg-transparent" data-tooltip="Cancel build">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<line x1="18" y1="6" x2="6" y2="18" />
|
||||
<line x1="6" y1="6" x2="18" y2="18" />
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 py-5 px-6 whitespace-pre-wrap break-words overflow-auto max-h-[80vh] -mt-12 overflow-y-scroll scrollbar-w-1 scrollbar-thumb-coollabs scrollbar-track-coolgray-200"
|
||||
bind:this={logsEl}
|
||||
|
||||
@@ -100,11 +100,15 @@ export const post: RequestHandler = async (event) => {
|
||||
type: 'webhook_commit'
|
||||
}
|
||||
});
|
||||
await buildQueue.add(buildId, {
|
||||
build_id: buildId,
|
||||
type: 'webhook_commit',
|
||||
...applicationFound
|
||||
});
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{
|
||||
build_id: buildId,
|
||||
type: 'webhook_commit',
|
||||
...applicationFound
|
||||
},
|
||||
{ jobId: buildId }
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
@@ -160,13 +164,17 @@ export const post: RequestHandler = async (event) => {
|
||||
type: 'webhook_pr'
|
||||
}
|
||||
});
|
||||
await buildQueue.add(buildId, {
|
||||
build_id: buildId,
|
||||
type: 'webhook_pr',
|
||||
...applicationFound,
|
||||
sourceBranch,
|
||||
pullmergeRequestId
|
||||
});
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{
|
||||
build_id: buildId,
|
||||
type: 'webhook_pr',
|
||||
...applicationFound,
|
||||
sourceBranch,
|
||||
pullmergeRequestId
|
||||
},
|
||||
{ jobId: buildId }
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
|
||||
@@ -73,11 +73,15 @@ export const post: RequestHandler = async (event) => {
|
||||
type: 'webhook_commit'
|
||||
}
|
||||
});
|
||||
await buildQueue.add(buildId, {
|
||||
build_id: buildId,
|
||||
type: 'webhook_commit',
|
||||
...applicationFound
|
||||
});
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{
|
||||
build_id: buildId,
|
||||
type: 'webhook_commit',
|
||||
...applicationFound
|
||||
},
|
||||
{ jobId: buildId }
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
@@ -156,13 +160,17 @@ export const post: RequestHandler = async (event) => {
|
||||
type: 'webhook_mr'
|
||||
}
|
||||
});
|
||||
await buildQueue.add(buildId, {
|
||||
build_id: buildId,
|
||||
type: 'webhook_mr',
|
||||
...applicationFound,
|
||||
sourceBranch,
|
||||
pullmergeRequestId
|
||||
});
|
||||
await buildQueue.add(
|
||||
buildId,
|
||||
{
|
||||
build_id: buildId,
|
||||
type: 'webhook_mr',
|
||||
...applicationFound,
|
||||
sourceBranch,
|
||||
pullmergeRequestId
|
||||
},
|
||||
{ jobId: buildId }
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
|
||||
Reference in New Issue
Block a user