mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-21 05:09:23 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1881e646d4 | ||
|
|
aa98808a1a | ||
|
|
f9a2232703 | ||
|
|
19d6be8663 | ||
|
|
0eb7c890ad | ||
|
|
7bfa68aa58 | ||
|
|
857a38050e | ||
|
|
c5b7f92caf | ||
|
|
df31ffd7fb | ||
|
|
0df0322d36 | ||
|
|
260552322d | ||
|
|
88ef6496a2 | ||
|
|
bdf123bf7b | ||
|
|
8fc3760eef | ||
|
|
5656f6f709 | ||
|
|
53e7e8b77e | ||
|
|
b990915b7a | ||
|
|
15b7822ffd | ||
|
|
cfa28419cb | ||
|
|
30ef0d2a3a | ||
|
|
755f99200a | ||
|
|
7af79ed3a2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@ node_modules
|
|||||||
/build
|
/build
|
||||||
/.svelte-kit
|
/.svelte-kit
|
||||||
/package
|
/package
|
||||||
|
/yarn.lock
|
||||||
|
|
||||||
.env
|
.env
|
||||||
.env.prod
|
.env.prod
|
||||||
|
|||||||
@@ -71,9 +71,7 @@ You can use the official ones or your self hosted version!
|
|||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
[See the Roadmap here](https://github.com/coollabsio/coolify/projects/1)
|
[See the Roadmap here](https://github.com/orgs/coollabsio/projects/3/views/8)
|
||||||
|
|
||||||
(Will be updated soon!)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||||
"version": "2.0.8",
|
"version": "2.0.11",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "docker compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0",
|
"dev": "docker compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0",
|
||||||
|
|||||||
@@ -59,10 +59,14 @@ export async function removeApplication({ id, teamId }) {
|
|||||||
const id = containerObj.ID;
|
const id = containerObj.ID;
|
||||||
const preview = containerObj.Image.split('-')[1];
|
const preview = containerObj.Image.split('-')[1];
|
||||||
await removeDestinationDocker({ id, engine: destinationDocker.engine });
|
await removeDestinationDocker({ id, engine: destinationDocker.engine });
|
||||||
if (preview) {
|
try {
|
||||||
await removeProxyConfiguration({ domain: `${preview}.${domain}` });
|
if (preview) {
|
||||||
} else {
|
await removeProxyConfiguration({ domain: `${preview}.${domain}` });
|
||||||
await removeProxyConfiguration({ domain });
|
} else {
|
||||||
|
await removeProxyConfiguration({ domain });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function ErrorHandler(e) {
|
|||||||
e = new Error(e.toString());
|
e = new Error(e.toString());
|
||||||
}
|
}
|
||||||
let truncatedError = e;
|
let truncatedError = e;
|
||||||
if (e.message.includes('docker run')) {
|
if (e.message?.includes('docker run')) {
|
||||||
let truncatedArray = [];
|
let truncatedArray = [];
|
||||||
truncatedArray = truncatedError.message.split('-').filter((line) => {
|
truncatedArray = truncatedError.message.split('-').filter((line) => {
|
||||||
if (!line.startsWith('e ')) {
|
if (!line.startsWith('e ')) {
|
||||||
@@ -50,7 +50,7 @@ export function ErrorHandler(e) {
|
|||||||
});
|
});
|
||||||
truncatedError.message = truncatedArray.join('-');
|
truncatedError.message = truncatedArray.join('-');
|
||||||
}
|
}
|
||||||
if (e.message.includes('git clone')) {
|
if (e.message?.includes('git clone')) {
|
||||||
truncatedError.message = 'git clone failed';
|
truncatedError.message = 'git clone failed';
|
||||||
}
|
}
|
||||||
sentry.captureException(truncatedError);
|
sentry.captureException(truncatedError);
|
||||||
@@ -61,11 +61,11 @@ export function ErrorHandler(e) {
|
|||||||
error: truncatedError.error || truncatedError.message
|
error: truncatedError.error || truncatedError.message
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (truncatedError.name === 'NotFoundError') {
|
if (truncatedError?.name === 'NotFoundError') {
|
||||||
payload.status = 404;
|
payload.status = 404;
|
||||||
}
|
}
|
||||||
if (truncatedError instanceof P.PrismaClientKnownRequestError) {
|
if (truncatedError instanceof P.PrismaClientKnownRequestError) {
|
||||||
if (truncatedError.code === 'P2002') {
|
if (truncatedError?.code === 'P2002') {
|
||||||
payload.body.message = 'Already exists. Choose another name.';
|
payload.body.message = 'Already exists. Choose another name.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,11 +107,7 @@ export async function forceSSLOffApplication({ domain }) {
|
|||||||
export async function forceSSLOnApplication({ domain }) {
|
export async function forceSSLOnApplication({ domain }) {
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const transactionId = await getNextTransactionId();
|
const transactionId = await getNextTransactionId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -162,11 +158,7 @@ export async function forceSSLOnApplication({ domain }) {
|
|||||||
|
|
||||||
export async function deleteProxy({ id }) {
|
export async function deleteProxy({ id }) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const transactionId = await getNextTransactionId();
|
const transactionId = await getNextTransactionId();
|
||||||
try {
|
try {
|
||||||
await haproxy.get(`v2/services/haproxy/configuration/backends/${id}`).json();
|
await haproxy.get(`v2/services/haproxy/configuration/backends/${id}`).json();
|
||||||
@@ -198,11 +190,7 @@ export async function reloadHaproxy(engine) {
|
|||||||
}
|
}
|
||||||
export async function configureProxyForApplication({ domain, imageId, applicationId, port }) {
|
export async function configureProxyForApplication({ domain, imageId, applicationId, port }) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let serverConfigured = false;
|
let serverConfigured = false;
|
||||||
let backendAvailable: any = null;
|
let backendAvailable: any = null;
|
||||||
@@ -283,11 +271,7 @@ export async function configureProxyForApplication({ domain, imageId, applicatio
|
|||||||
export async function configureCoolifyProxyOff(fqdn) {
|
export async function configureCoolifyProxyOff(fqdn) {
|
||||||
const domain = getDomain(fqdn);
|
const domain = getDomain(fqdn);
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const transactionId = await getNextTransactionId();
|
const transactionId = await getNextTransactionId();
|
||||||
@@ -308,22 +292,21 @@ export async function configureCoolifyProxyOff(fqdn) {
|
|||||||
throw error?.response?.body || error;
|
throw error?.response?.body || error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function checkHAProxy(haproxy) {
|
export async function checkHAProxy(haproxy?: any) {
|
||||||
if (!haproxy) haproxy = await haproxyInstance();
|
if (!haproxy) haproxy = await haproxyInstance();
|
||||||
try {
|
try {
|
||||||
await haproxy.get('v2/info');
|
await haproxy.get('v2/info');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw 'HAProxy is not running, but it should be!';
|
throw {
|
||||||
|
message:
|
||||||
|
'Coolify Proxy is not running, but it should be!<br><br>Start it in the "Destinations" menu.'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function configureCoolifyProxyOn(fqdn) {
|
export async function configureCoolifyProxyOn(fqdn) {
|
||||||
const domain = getDomain(fqdn);
|
const domain = getDomain(fqdn);
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let serverConfigured = false;
|
let serverConfigured = false;
|
||||||
let backendAvailable: any = null;
|
let backendAvailable: any = null;
|
||||||
try {
|
try {
|
||||||
@@ -460,7 +443,7 @@ export async function startCoolifyProxy(engine) {
|
|||||||
);
|
);
|
||||||
const ip = JSON.parse(Config)[0].Gateway;
|
const ip = JSON.parse(Config)[0].Gateway;
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restarts always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}`
|
`DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restart always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await configureNetworkCoolifyProxy(engine);
|
await configureNetworkCoolifyProxy(engine);
|
||||||
@@ -572,12 +555,7 @@ export async function configureSimpleServiceProxyOn({ id, domain, port }) {
|
|||||||
|
|
||||||
export async function configureSimpleServiceProxyOff({ domain }) {
|
export async function configureSimpleServiceProxyOff({ domain }) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
|
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
|
||||||
const transactionId = await getNextTransactionId();
|
const transactionId = await getNextTransactionId();
|
||||||
@@ -596,12 +574,7 @@ export async function configureSimpleServiceProxyOff({ domain }) {
|
|||||||
|
|
||||||
export async function removeWwwRedirection(domain) {
|
export async function removeWwwRedirection(domain) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy();
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rules: any = await haproxy
|
const rules: any = await haproxy
|
||||||
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
||||||
searchParams: {
|
searchParams: {
|
||||||
@@ -631,11 +604,7 @@ export async function removeWwwRedirection(domain) {
|
|||||||
}
|
}
|
||||||
export async function setWwwRedirection(fqdn) {
|
export async function setWwwRedirection(fqdn) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
try {
|
await checkHAProxy(haproxy);
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
} catch (error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const transactionId = await getNextTransactionId();
|
const transactionId = await getNextTransactionId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -96,10 +96,9 @@
|
|||||||
|
|
||||||
async function update() {
|
async function update() {
|
||||||
updateStatus.loading = true;
|
updateStatus.loading = true;
|
||||||
// if (!dev) {
|
|
||||||
try {
|
try {
|
||||||
await post(`/update.json`, { type: 'update', latestVersion });
|
await post(`/update.json`, { type: 'update', latestVersion });
|
||||||
toast.push('Update completed. Waiting for the new version to start...');
|
toast.push('Update completed.<br>Waiting for the new version to start...');
|
||||||
let reachable = false;
|
let reachable = false;
|
||||||
let tries = 0;
|
let tries = 0;
|
||||||
do {
|
do {
|
||||||
@@ -119,10 +118,9 @@
|
|||||||
await asyncSleep(3000);
|
await asyncSleep(3000);
|
||||||
return window.location.reload();
|
return window.location.reload();
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
return errorNotification(error);
|
|
||||||
} finally {
|
|
||||||
updateStatus.success = false;
|
updateStatus.success = false;
|
||||||
updateStatus.loading = false;
|
updateStatus.loading = false;
|
||||||
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -15,16 +15,32 @@
|
|||||||
let loading = true;
|
let loading = true;
|
||||||
let currentStatus;
|
let currentStatus;
|
||||||
let streamInterval;
|
let streamInterval;
|
||||||
|
let followingBuild;
|
||||||
|
let followingInterval;
|
||||||
|
let logsEl;
|
||||||
|
|
||||||
const { id } = $page.params;
|
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) {
|
async function streamLogs(sequence = 0) {
|
||||||
try {
|
try {
|
||||||
let { logs: responseLogs, status } = await get(
|
let { logs: responseLogs, status } = await get(
|
||||||
`/applications/${id}/logs/build/build.json?buildId=${buildId}&sequence=${sequence}`
|
`/applications/${id}/logs/build/build.json?buildId=${buildId}&sequence=${sequence}`
|
||||||
);
|
);
|
||||||
currentStatus = status;
|
currentStatus = status;
|
||||||
logs = logs.concat(responseLogs);
|
logs = logs.concat(responseLogs.map((log) => ({ ...log, line: cleanAnsiCodes(log.line) })));
|
||||||
loading = false;
|
loading = false;
|
||||||
streamInterval = setInterval(async () => {
|
streamInterval = setInterval(async () => {
|
||||||
if (status !== 'running') {
|
if (status !== 'running') {
|
||||||
@@ -38,8 +54,13 @@
|
|||||||
);
|
);
|
||||||
status = data.status;
|
status = data.status;
|
||||||
currentStatus = status;
|
currentStatus = status;
|
||||||
logs = logs.concat(data.logs);
|
|
||||||
|
logs = logs.concat(data.logs.map((log) => ({ ...log, line: cleanAnsiCodes(log.line) })));
|
||||||
dispatch('updateBuildStatus', { status });
|
dispatch('updateBuildStatus', { status });
|
||||||
|
if (followingBuild) {
|
||||||
|
const logEl = document.getElementById('logs');
|
||||||
|
logEl.scrollTop = logEl.scrollHeight;
|
||||||
|
}
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
@@ -50,6 +71,7 @@
|
|||||||
}
|
}
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
clearInterval(streamInterval);
|
clearInterval(streamInterval);
|
||||||
|
clearInterval(followingInterval);
|
||||||
});
|
});
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
@@ -60,12 +82,37 @@
|
|||||||
{#if loading}
|
{#if loading}
|
||||||
<Loading />
|
<Loading />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="relative">
|
<div class="relative ">
|
||||||
{#if currentStatus === 'running'}
|
{#if currentStatus === 'running'}
|
||||||
<LoadingLogs />
|
<LoadingLogs />
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="flex justify-end sticky top-0 p-2">
|
||||||
|
<button
|
||||||
|
on:click={followBuild}
|
||||||
|
data-tooltip="Follow logs"
|
||||||
|
class:text-green-500={followingBuild}
|
||||||
|
>
|
||||||
|
<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" />
|
||||||
|
<circle cx="12" cy="12" r="9" />
|
||||||
|
<line x1="8" y1="12" x2="12" y2="16" />
|
||||||
|
<line x1="12" y1="8" x2="12" y2="16" />
|
||||||
|
<line x1="16" y1="12" x2="12" y2="16" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<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"
|
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"
|
||||||
|
bind:this={logsEl}
|
||||||
>
|
>
|
||||||
{#each logs as log}
|
{#each logs as log}
|
||||||
<div>{log.line + '\n'}</div>
|
<div>{log.line + '\n'}</div>
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
export let buildCount;
|
export let buildCount;
|
||||||
|
|
||||||
let buildId;
|
let buildId;
|
||||||
$: buildId;
|
|
||||||
|
|
||||||
let skip = 0;
|
let skip = 0;
|
||||||
let noMoreBuilds = buildCount < 5 || buildCount <= skip;
|
let noMoreBuilds = buildCount < 5 || buildCount <= skip;
|
||||||
@@ -92,45 +91,47 @@
|
|||||||
Build logs of <a href={application.fqdn} target="_blank">{getDomain(application.fqdn)}</a>
|
Build logs of <a href={application.fqdn} target="_blank">{getDomain(application.fqdn)}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-start space-x-2 px-10 pt-6 ">
|
<div class="block flex-row justify-start space-x-2 px-5 pt-6 sm:px-10 md:flex">
|
||||||
<div class="min-w-[16rem] space-y-2">
|
<div class="mb-4 min-w-[16rem] space-y-2 md:mb-0 ">
|
||||||
{#each builds as build (build.id)}
|
<div class="top-4 md:sticky">
|
||||||
<div
|
{#each builds as build (build.id)}
|
||||||
data-tooltip={new Intl.DateTimeFormat('default', dateOptions).format(
|
<div
|
||||||
new Date(build.createdAt)
|
data-tooltip={new Intl.DateTimeFormat('default', dateOptions).format(
|
||||||
) + `\n${build.status}`}
|
new Date(build.createdAt)
|
||||||
on:click={() => loadBuild(build.id)}
|
) + `\n${build.status}`}
|
||||||
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"
|
on:click={() => loadBuild(build.id)}
|
||||||
class:bg-coolgray-400={buildId === 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:border-red-500={build.status === 'failed'}
|
class:bg-coolgray-400={buildId === build.id}
|
||||||
class:border-green-500={build.status === 'success'}
|
class:border-red-500={build.status === 'failed'}
|
||||||
class:border-yellow-500={build.status === 'inprogress'}
|
class:border-green-500={build.status === 'success'}
|
||||||
>
|
class:border-yellow-500={build.status === 'inprogress'}
|
||||||
<div class="flex-col px-2">
|
>
|
||||||
<div class="text-sm font-bold">
|
<div class="flex-col px-2">
|
||||||
{application.branch}
|
<div class="text-sm font-bold">
|
||||||
|
{application.branch}
|
||||||
|
</div>
|
||||||
|
<div class="text-xs">
|
||||||
|
{build.type}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs">
|
<div class="flex-1" />
|
||||||
{build.type}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1" />
|
|
||||||
|
|
||||||
<div class="w-48 text-center text-xs">
|
<div class="w-48 text-center text-xs">
|
||||||
{#if build.status === 'running'}
|
{#if build.status === 'running'}
|
||||||
<div class="font-bold">Running</div>
|
<div class="font-bold">Running</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div>{build.since}</div>
|
<div>{build.since}</div>
|
||||||
<div>Finished in <span class="font-bold">{build.took}s</span></div>
|
<div>Finished in <span class="font-bold">{build.took}s</span></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
{/each}
|
</div>
|
||||||
{#if buildCount > 0 && !noMoreBuilds}
|
<div class="flex space-x-2">
|
||||||
<button class="w-full" on:click={loadMoreBuilds}>Load More</button>
|
<button disabled={noMoreBuilds} class="w-full" on:click={loadMoreBuilds}>Load More</button>
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-96 flex-1">
|
<div class="flex-1 md:w-96">
|
||||||
{#if buildId}
|
{#if buildId}
|
||||||
{#key buildId}
|
{#key buildId}
|
||||||
<svelte:component this={BuildLog} {buildId} on:updateBuildStatus={updateBuildStatus} />
|
<svelte:component this={BuildLog} {buildId} on:updateBuildStatus={updateBuildStatus} />
|
||||||
|
|||||||
@@ -27,19 +27,23 @@
|
|||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { get } from '$lib/api';
|
import { get } from '$lib/api';
|
||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
|
|
||||||
let loadLogsInterval = null;
|
let loadLogsInterval = null;
|
||||||
let logs = [];
|
let logs = [];
|
||||||
|
let followingBuild;
|
||||||
|
let followingInterval;
|
||||||
|
let logsEl;
|
||||||
|
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
loadLogs();
|
loadLogs();
|
||||||
loadLogsInterval = setInterval(() => {
|
loadLogsInterval = setInterval(() => {
|
||||||
loadLogs();
|
loadLogs();
|
||||||
}, 3000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
clearInterval(loadLogsInterval);
|
clearInterval(loadLogsInterval);
|
||||||
|
clearInterval(followingInterval);
|
||||||
});
|
});
|
||||||
async function loadLogs() {
|
async function loadLogs() {
|
||||||
try {
|
try {
|
||||||
@@ -50,6 +54,18 @@
|
|||||||
return errorNotification(error);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex space-x-1 p-6 font-bold">
|
<div class="flex space-x-1 p-6 font-bold">
|
||||||
@@ -63,8 +79,33 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
<LoadingLogs />
|
<LoadingLogs />
|
||||||
|
<div class="flex justify-end sticky top-0 p-2">
|
||||||
|
<button
|
||||||
|
on:click={followBuild}
|
||||||
|
data-tooltip="Follow logs"
|
||||||
|
class:text-green-500={followingBuild}
|
||||||
|
>
|
||||||
|
<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" />
|
||||||
|
<circle cx="12" cy="12" r="9" />
|
||||||
|
<line x1="8" y1="12" x2="12" y2="16" />
|
||||||
|
<line x1="12" y1="8" x2="12" y2="16" />
|
||||||
|
<line x1="16" y1="12" x2="12" y2="16" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 p-6 whitespace-pre-wrap break-words w-full"
|
class="font-mono leading-6 text-left text-md tracking-tighter rounded bg-coolgray-200 p-6 whitespace-pre-wrap break-words w-full mb-10 -mt-12"
|
||||||
|
bind:this={logsEl}
|
||||||
>
|
>
|
||||||
{#each logs as log}
|
{#each logs as log}
|
||||||
{log + '\n'}
|
{log + '\n'}
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
|
||||||
} finally {
|
|
||||||
await stopCoolifyProxy(engine);
|
await stopCoolifyProxy(engine);
|
||||||
|
return ErrorHandler(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -110,23 +110,23 @@
|
|||||||
loading = false;
|
loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMount(async () => {
|
// onMount(async () => {
|
||||||
if (
|
// if (
|
||||||
service.type &&
|
// service.type &&
|
||||||
service.destinationDockerId &&
|
// service.destinationDockerId &&
|
||||||
service.version &&
|
// service.version &&
|
||||||
service.fqdn &&
|
// service.fqdn &&
|
||||||
!isRunning
|
// !isRunning
|
||||||
) {
|
// ) {
|
||||||
try {
|
// try {
|
||||||
await post(`/services/${service.id}/${service.type}/stop.json`, {});
|
// await post(`/services/${service.id}/${service.type}/stop.json`, {});
|
||||||
} catch ({ error }) {
|
// } catch ({ error }) {
|
||||||
return errorNotification(error);
|
// return errorNotification(error);
|
||||||
} finally {
|
// } finally {
|
||||||
loading = false;
|
// loading = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav class="nav-side">
|
<nav class="nav-side">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import yaml from 'js-yaml';
|
|||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import {
|
import {
|
||||||
|
checkHAProxy,
|
||||||
configureSimpleServiceProxyOn,
|
configureSimpleServiceProxyOn,
|
||||||
reloadHaproxy,
|
reloadHaproxy,
|
||||||
setWwwRedirection,
|
setWwwRedirection,
|
||||||
@@ -22,6 +23,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -33,8 +33,12 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
await stopTcpHttpProxy(destinationDocker, publicPort);
|
try {
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
await stopTcpHttpProxy(destinationDocker, publicPort);
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { promises as fs } from 'fs';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
|
import {
|
||||||
|
checkHAProxy,
|
||||||
|
configureSimpleServiceProxyOn,
|
||||||
|
reloadHaproxy,
|
||||||
|
setWwwRedirection
|
||||||
|
} from '$lib/haproxy';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
|
|
||||||
@@ -15,6 +20,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
||||||
|
|
||||||
@@ -58,7 +64,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
try {
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { promises as fs } from 'fs';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
|
import {
|
||||||
|
checkHAProxy,
|
||||||
|
configureSimpleServiceProxyOn,
|
||||||
|
reloadHaproxy,
|
||||||
|
setWwwRedirection
|
||||||
|
} from '$lib/haproxy';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
|
|
||||||
@@ -15,6 +20,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ export const post: RequestHandler = async (event) => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
try {
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { promises as fs } from 'fs';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
|
import {
|
||||||
|
checkHAProxy,
|
||||||
|
configureSimpleServiceProxyOn,
|
||||||
|
reloadHaproxy,
|
||||||
|
setWwwRedirection
|
||||||
|
} from '$lib/haproxy';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { getServiceImage, ErrorHandler } from '$lib/database';
|
import { getServiceImage, ErrorHandler } from '$lib/database';
|
||||||
|
|
||||||
@@ -15,6 +20,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
try {
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { promises as fs } from 'fs';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
|
import {
|
||||||
|
checkHAProxy,
|
||||||
|
configureSimpleServiceProxyOn,
|
||||||
|
reloadHaproxy,
|
||||||
|
setWwwRedirection
|
||||||
|
} from '$lib/haproxy';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
|
|
||||||
@@ -15,6 +20,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
try {
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { promises as fs } from 'fs';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { letsEncrypt } from '$lib/letsencrypt';
|
||||||
import { configureSimpleServiceProxyOn, reloadHaproxy, setWwwRedirection } from '$lib/haproxy';
|
import {
|
||||||
|
checkHAProxy,
|
||||||
|
configureSimpleServiceProxyOn,
|
||||||
|
reloadHaproxy,
|
||||||
|
setWwwRedirection
|
||||||
|
} from '$lib/haproxy';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
|
|
||||||
@@ -15,6 +20,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkHAProxy();
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
await configureSimpleServiceProxyOff({ domain });
|
try {
|
||||||
|
await configureSimpleServiceProxyOff({ domain });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
body: {}
|
body: {}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
|
|
||||||
await asyncSleep(2000);
|
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: {}
|
body: {}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import cuid from 'cuid';
|
|||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { buildQueue } from '$lib/queues';
|
import { buildQueue } from '$lib/queues';
|
||||||
import { checkContainer, removeProxyConfiguration } from '$lib/haproxy';
|
import { checkContainer, removeProxyConfiguration } from '$lib/haproxy';
|
||||||
|
import { dev } from '$app/env';
|
||||||
|
|
||||||
export const options: RequestHandler = async () => {
|
export const options: RequestHandler = async () => {
|
||||||
return {
|
return {
|
||||||
@@ -22,8 +23,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const buildId = cuid();
|
const buildId = cuid();
|
||||||
const allowedGithubEvents = ['push', 'pull_request'];
|
const allowedGithubEvents = ['push', 'pull_request'];
|
||||||
const allowedActions = ['opened', 'reopened', 'synchronize', 'closed'];
|
const allowedActions = ['opened', 'reopened', 'synchronize', 'closed'];
|
||||||
const githubEvent = event.request.headers.get('x-github-event').toLowerCase();
|
const githubEvent = event.request.headers.get('x-github-event')?.toLowerCase();
|
||||||
const githubSignature = event.request.headers.get('x-hub-signature-256').toLowerCase();
|
const githubSignature = event.request.headers.get('x-hub-signature-256')?.toLowerCase();
|
||||||
if (!allowedGithubEvents.includes(githubEvent)) {
|
if (!allowedGithubEvents.includes(githubEvent)) {
|
||||||
return {
|
return {
|
||||||
status: 500,
|
status: 500,
|
||||||
@@ -34,7 +35,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
let repository, projectId, branch;
|
let repository, projectId, branch;
|
||||||
const body = await event.request.json();
|
const body = await event.request.json();
|
||||||
|
|
||||||
if (githubEvent === 'push') {
|
if (githubEvent === 'push') {
|
||||||
repository = body.repository;
|
repository = body.repository;
|
||||||
projectId = repository.id;
|
projectId = repository.id;
|
||||||
@@ -54,14 +54,17 @@ export const post: RequestHandler = async (event) => {
|
|||||||
'utf8'
|
'utf8'
|
||||||
);
|
);
|
||||||
const checksum = Buffer.from(githubSignature, 'utf8');
|
const checksum = Buffer.from(githubSignature, 'utf8');
|
||||||
if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) {
|
if (!dev) {
|
||||||
return {
|
if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) {
|
||||||
status: 500,
|
return {
|
||||||
body: {
|
status: 500,
|
||||||
message: 'SHA256 checksum failed. Are you doing something fishy?'
|
body: {
|
||||||
}
|
message: 'SHA256 checksum failed. Are you doing something fishy?'
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (githubEvent === 'push') {
|
if (githubEvent === 'push') {
|
||||||
if (!applicationFound.configHash) {
|
if (!applicationFound.configHash) {
|
||||||
const configHash = crypto
|
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, {
|
await buildQueue.add(buildId, {
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
type: 'webhook_pr',
|
type: 'webhook_pr',
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-side {
|
.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 {
|
.add-icon {
|
||||||
|
|||||||
Reference in New Issue
Block a user