diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index 945883bb2..5722dbcfb 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -261,7 +261,10 @@ import * as buildpacks from '../lib/buildPacks'; if (secrets.length > 0) { secrets.forEach((secret) => { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + envs.push(`${secret.name}=${isSecretFound[0].value}`); + } else { envs.push(`${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/common.ts b/apps/api/src/lib/buildPacks/common.ts index 93b8ca076..0e188ae36 100644 --- a/apps/api/src/lib/buildPacks/common.ts +++ b/apps/api/src/lib/buildPacks/common.ts @@ -556,7 +556,6 @@ export function checkPnpm(installCommand = null, buildCommand = null, startComma ); } - export async function buildImage({ applicationId, tag, @@ -677,8 +676,6 @@ export async function buildCacheImageWithNode(data, imageForBuild) { secrets, pullmergeRequestId } = data; - - const isPnpm = checkPnpm(installCommand, buildCommand); const Dockerfile: Array = []; Dockerfile.push(`FROM ${imageForBuild}`); @@ -688,7 +685,10 @@ export async function buildCacheImageWithNode(data, imageForBuild) { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { @@ -707,6 +707,7 @@ export async function buildCacheImageWithNode(data, imageForBuild) { Dockerfile.push(`RUN ${installCommand}`); } Dockerfile.push(`RUN ${buildCommand}`); + console.log(Dockerfile.join('\n')) await fs.writeFile(`${workdir}/Dockerfile-cache`, Dockerfile.join('\n')); await buildImage({ ...data, isCache: true }); } @@ -722,7 +723,10 @@ export async function buildCacheImageForLaravel(data, imageForBuild) { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/deno.ts b/apps/api/src/lib/buildPacks/deno.ts index 6dafa55ed..f255a5983 100644 --- a/apps/api/src/lib/buildPacks/deno.ts +++ b/apps/api/src/lib/buildPacks/deno.ts @@ -27,7 +27,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/docker.ts b/apps/api/src/lib/buildPacks/docker.ts index 04041b190..c017b4bed 100644 --- a/apps/api/src/lib/buildPacks/docker.ts +++ b/apps/api/src/lib/buildPacks/docker.ts @@ -28,6 +28,7 @@ export default async function (data) { if (secrets.length > 0) { secrets.forEach((secret) => { if (secret.isBuildSecret) { + // TODO: fix secrets if ( (pullmergeRequestId && secret.isPRMRSecret) || (!pullmergeRequestId && !secret.isPRMRSecret) diff --git a/apps/api/src/lib/buildPacks/nextjs.ts b/apps/api/src/lib/buildPacks/nextjs.ts index 90d80449e..90a70f89b 100644 --- a/apps/api/src/lib/buildPacks/nextjs.ts +++ b/apps/api/src/lib/buildPacks/nextjs.ts @@ -27,7 +27,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/node.ts b/apps/api/src/lib/buildPacks/node.ts index ad234aed1..546942542 100644 --- a/apps/api/src/lib/buildPacks/node.ts +++ b/apps/api/src/lib/buildPacks/node.ts @@ -23,7 +23,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/nuxtjs.ts b/apps/api/src/lib/buildPacks/nuxtjs.ts index 90d80449e..90a70f89b 100644 --- a/apps/api/src/lib/buildPacks/nuxtjs.ts +++ b/apps/api/src/lib/buildPacks/nuxtjs.ts @@ -27,7 +27,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/php.ts b/apps/api/src/lib/buildPacks/php.ts index e6dc1699f..eaf97d1b1 100644 --- a/apps/api/src/lib/buildPacks/php.ts +++ b/apps/api/src/lib/buildPacks/php.ts @@ -16,7 +16,10 @@ const createDockerfile = async (data, image, htaccessFound): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/python.ts b/apps/api/src/lib/buildPacks/python.ts index 110471179..36d707f16 100644 --- a/apps/api/src/lib/buildPacks/python.ts +++ b/apps/api/src/lib/buildPacks/python.ts @@ -21,7 +21,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/buildPacks/static.ts b/apps/api/src/lib/buildPacks/static.ts index 47fa0dfa4..c727985ca 100644 --- a/apps/api/src/lib/buildPacks/static.ts +++ b/apps/api/src/lib/buildPacks/static.ts @@ -24,7 +24,10 @@ const createDockerfile = async (data, image): Promise => { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + Dockerfile.push(`ARG ${secret.name}=${isSecretFound[0].value}`); + } else { Dockerfile.push(`ARG ${secret.name}=${secret.value}`); } } else { diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 50a8dd4db..55bfb08ab 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -21,7 +21,7 @@ import { scheduler } from './scheduler'; import { supportedServiceTypesAndVersions } from './services/supportedVersions'; import { includeServices } from './services/common'; -export const version = '3.10.0'; +export const version = '3.10.1'; export const isDev = process.env.NODE_ENV === 'development'; const algorithm = 'aes-256-ctr'; @@ -537,7 +537,7 @@ export async function executeDockerCmd({ debug, buildId, applicationId, dockerId } export async function startTraefikProxy(id: string): Promise { const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } }) - const found = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true }); + const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true }); const { id: settingsId, ipv4, ipv6 } = await listSettings(); if (!found) { @@ -621,7 +621,7 @@ export async function configureNetworkTraefikProxy(destination: any): Promise { - const found = await checkContainer({ dockerId: id, container: 'coolify-proxy' }); + const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy' }); await prisma.destinationDocker.update({ where: { id }, data: { isCoolifyProxyUsed: false } @@ -1062,7 +1062,7 @@ export async function stopTcpHttpProxy( const { id: dockerId } = destinationDocker; let container = `${id}-${publicPort}`; if (forceName) container = forceName; - const found = await checkContainer({ dockerId, container }); + const { found } = await checkContainer({ dockerId, container }); try { if (found) { return await executeDockerCmd({ @@ -1284,7 +1284,7 @@ export async function startTraefikTCPProxy( ): Promise<{ stdout: string; stderr: string } | Error> { const { network, id: dockerId, remoteEngine } = destinationDocker; const container = `${id}-${publicPort}`; - const found = await checkContainer({ dockerId, container, remove: true }); + const { found } = await checkContainer({ dockerId, container, remove: true }); const { ipv4, ipv6 } = await listSettings(); let dependentId = id; diff --git a/apps/api/src/lib/docker.ts b/apps/api/src/lib/docker.ts index f0b13d5f1..dff59b7db 100644 --- a/apps/api/src/lib/docker.ts +++ b/apps/api/src/lib/docker.ts @@ -13,7 +13,7 @@ export function formatLabelsOnDocker(data) { return container }) } -export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise { +export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise<{ found: boolean, status?: { isExited: boolean, isRunning: boolean, isRestarting: boolean } }> { let containerFound = false; try { const { stdout } = await executeDockerCmd({ @@ -21,10 +21,12 @@ export async function checkContainer({ dockerId, container, remove = false }: { command: `docker inspect --format '{{json .State}}' ${container}` }); - + containerFound = true const parsedStdout = JSON.parse(stdout); const status = parsedStdout.Status; const isRunning = status === 'running'; + const isRestarting = status === 'restarting' + const isExited = status === 'exited' if (status === 'created') { await executeDockerCmd({ dockerId, @@ -39,13 +41,23 @@ export async function checkContainer({ dockerId, container, remove = false }: { `docker rm ${container}` }); } - if (isRunning) { - containerFound = true; - } + + return { + found: containerFound, + status: { + isRunning, + isRestarting, + isExited + + } + }; } catch (err) { // Container not found } - return containerFound; + return { + found: false + }; + } export async function isContainerExited(dockerId: string, containerName: string): Promise { diff --git a/apps/api/src/lib/importers/gitlab.ts b/apps/api/src/lib/importers/gitlab.ts index b1784b6b9..69f204155 100644 --- a/apps/api/src/lib/importers/gitlab.ts +++ b/apps/api/src/lib/importers/gitlab.ts @@ -10,7 +10,8 @@ export default async function ({ branch, buildId, privateSshKey, - customPort + customPort, + forPublic }: { applicationId: string; workdir: string; @@ -21,11 +22,15 @@ export default async function ({ repodir: string; privateSshKey: string; customPort: number; + forPublic: boolean; }): Promise { const url = htmlUrl.replace('https://', '').replace('http://', '').replace(/\/$/, ''); await saveBuildLog({ line: 'GitLab importer started.', buildId, applicationId }); - await asyncExecShell(`echo '${privateSshKey}' > ${repodir}/id.rsa`); - await asyncExecShell(`chmod 600 ${repodir}/id.rsa`); + + if (!forPublic) { + await asyncExecShell(`echo '${privateSshKey}' > ${repodir}/id.rsa`); + await asyncExecShell(`chmod 600 ${repodir}/id.rsa`); + } await saveBuildLog({ line: `Cloning ${repository}:${branch} branch.`, @@ -33,9 +38,16 @@ export default async function ({ applicationId }); - await asyncExecShell( - `git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -p ${customPort} -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. ` - ); + if (forPublic) { + await asyncExecShell( + `git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -p ${customPort} -q -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. ` + ); + } else { + await asyncExecShell( + `git clone -q -b ${branch} git@${url}:${repository}.git --config core.sshCommand="ssh -p ${customPort} -q -i ${repodir}id.rsa -o StrictHostKeyChecking=no" ${workdir}/ && cd ${workdir}/ && git submodule update --init --recursive && git lfs pull && cd .. ` + ); + } + const { stdout: commit } = await asyncExecShell(`cd ${workdir}/ && git rev-parse HEAD`); return commit.replace('\n', ''); } diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index 7f13f7219..903f53035 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -655,7 +655,7 @@ async function startLanguageToolService(request: FastifyRequest) { [id]: { container_name: id, image: config.n8n.image, - volumes: config.n8n, + volumes: config.n8n.volumes, environment: config.n8n.environmentVariables, labels: makeLabelForServices('n8n'), ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -1116,7 +1116,6 @@ async function startUmamiService(request: FastifyRequest) { }, volumes: volumeMounts }; - console.log(composeFile) const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); await startServiceContainers(destinationDocker.id, composeFileDestination) diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index 8a390a3f5..c2b375c2a 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -74,14 +74,21 @@ export async function getApplicationStatus(request: FastifyRequest) { const { teamId } = request.user let isRunning = false; let isExited = false; - + let isRestarting = false; const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId) { - isRunning = await checkContainer({ dockerId: application.destinationDocker.id, container: id }); - isExited = await isContainerExited(application.destinationDocker.id, id); + const status = await checkContainer({ dockerId: application.destinationDocker.id, container: id }); + if (status?.found) { + isRunning = status.status.isRunning; + isExited = status.status.isExited; + isRestarting = status.status.isRestarting + } + + // isExited = await isContainerExited(application.destinationDocker.id, id); } return { isRunning, + isRestarting, isExited, }; } catch ({ status, message }) { @@ -339,7 +346,7 @@ export async function stopPreviewApplication(request: FastifyRequest, reply: if (secrets.length > 0) { secrets.forEach((secret) => { if (pullmergeRequestId) { - if (secret.isPRMRSecret) { + const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + if (isSecretFound.length > 0) { + envs.push(`${secret.name}=${isSecretFound[0].value}`); + } else { envs.push(`${secret.name}=${secret.value}`); } } else { @@ -463,7 +473,7 @@ export async function stopApplication(request: FastifyRequest, reply: Fa const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId) { const { id: dockerId } = application.destinationDocker; - const found = await checkContainer({ dockerId, container: id }); + const { found } = await checkContainer({ dockerId, container: id }); if (found) { await removeContainer({ id, dockerId: application.destinationDocker.id }); } diff --git a/apps/api/src/routes/api/v1/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index bb96981cf..e4f038881 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -229,7 +229,7 @@ export async function getDestinationStatus(request: FastifyRequest) { try { const { id } = request.params const destination = await prisma.destinationDocker.findUnique({ where: { id } }) - const isRunning = await checkContainer({ dockerId: destination.id, container: 'coolify-proxy', remove: true }) + const { found: isRunning } = await checkContainer({ dockerId: destination.id, container: 'coolify-proxy', remove: true }) return { isRunning } diff --git a/apps/api/src/routes/api/v1/handlers.ts b/apps/api/src/routes/api/v1/handlers.ts index cdb115af3..4e877f13c 100644 --- a/apps/api/src/routes/api/v1/handlers.ts +++ b/apps/api/src/routes/api/v1/handlers.ts @@ -26,7 +26,7 @@ export async function cleanupManually(request: FastifyRequest) { } export async function checkUpdate(request: FastifyRequest) { try { - const isStaging = request.hostname === 'staging.coolify.io' + const isStaging = request.hostname === 'staging.coolify.io' || request.hostname === 'arm.coolify.io' const currentVersion = version; const { data: versions } = await axios.get( `https://get.coollabs.io/versions.json?appId=${process.env['COOLIFY_APP_ID']}&version=${currentVersion}` diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index c6f10cbb4..48e58ca78 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -43,13 +43,17 @@ export async function getServiceStatus(request: FastifyRequest) { let isRunning = false; let isExited = false - + let isRestarting = false; const service = await getServiceFromDB({ id, teamId }); const { destinationDockerId, settings } = service; if (destinationDockerId) { - isRunning = await checkContainer({ dockerId: service.destinationDocker.id, container: id }); - isExited = await isContainerExited(service.destinationDocker.id, id); + const status = await checkContainer({ dockerId: service.destinationDocker.id, container: id }); + if (status?.found) { + isRunning = status.status.isRunning; + isExited = status.status.isExited; + isRestarting = status.status.isRestarting + } } return { isRunning, @@ -554,7 +558,7 @@ export async function activateWordpressFtp(request: FastifyRequest): Promi if (application.settings.previews) { if (application.destinationDockerId) { - const isRunning = await checkContainer( + const { found: isRunning } = await checkContainer( { dockerId: application.destinationDocker.id, container: application.id diff --git a/apps/api/src/routes/webhooks/gitlab/handlers.ts b/apps/api/src/routes/webhooks/gitlab/handlers.ts index 58d01182a..264344c4a 100644 --- a/apps/api/src/routes/webhooks/gitlab/handlers.ts +++ b/apps/api/src/routes/webhooks/gitlab/handlers.ts @@ -107,7 +107,7 @@ export async function gitLabEvents(request: FastifyRequest) { const buildId = cuid(); if (application.settings.previews) { if (application.destinationDockerId) { - const isRunning = await checkContainer( + const { found: isRunning } = await checkContainer( { dockerId: application.destinationDocker.id, container: application.id diff --git a/apps/ui/src/lib/store.ts b/apps/ui/src/lib/store.ts index ec841a2e5..b0719e591 100644 --- a/apps/ui/src/lib/store.ts +++ b/apps/ui/src/lib/store.ts @@ -73,6 +73,7 @@ export const status: Writable = writable({ application: { isRunning: false, isExited: false, + isRestarting: false, loading: false, initialLoading: true }, diff --git a/apps/ui/src/routes/applications/[id]/__layout.svelte b/apps/ui/src/routes/applications/[id]/__layout.svelte index f2854f092..546af6e90 100644 --- a/apps/ui/src/routes/applications/[id]/__layout.svelte +++ b/apps/ui/src/routes/applications/[id]/__layout.svelte @@ -107,7 +107,7 @@ $status.application.initialLoading = true; try { await del(`/applications/${id}`, { id, force }); - return await goto(`/`, { replaceState: true }); + return await window.location.assign(`/`); } catch (error) { if (error.message.startsWith(`Command failed: SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid`)) { forceDelete = true; @@ -154,6 +154,7 @@ const data = await get(`/applications/${id}/status`); $status.application.isRunning = data.isRunning; $status.application.isExited = data.isExited; + $status.application.isRestarting = data.isRestarting; $status.application.loading = false; $status.application.initialLoading = false; } @@ -162,6 +163,7 @@ $status.application.initialLoading = true; $status.application.isRunning = false; $status.application.isExited = false; + $status.application.isRestarting = false; $status.application.loading = false; $location = null; $isDeploymentEnabled = false; @@ -171,6 +173,7 @@ setLocation(application, settings); $status.application.isRunning = false; $status.application.isExited = false; + $status.application.isRestarting = false; $status.application.loading = false; if ( application.gitSourceId && @@ -215,7 +218,7 @@
{/if} - {#if $status.application.isExited} + {#if $status.application.isExited || $status.application.isRestarting} - Application exited with an error! + Application exited or restarting! + + Stop {/if} {#if $status.application.initialLoading}
- {#if source.gitlabApp.groupName} -
- - -
- {/if}