@@ -20,7 +20,8 @@ import {
 | 
				
			|||||||
	decryptApplication,
 | 
						decryptApplication,
 | 
				
			||||||
	isDev,
 | 
						isDev,
 | 
				
			||||||
	pushToRegistry,
 | 
						pushToRegistry,
 | 
				
			||||||
	executeCommand
 | 
						executeCommand,
 | 
				
			||||||
 | 
						generateSecrets
 | 
				
			||||||
} from '../lib/common';
 | 
					} from '../lib/common';
 | 
				
			||||||
import * as importers from '../lib/importers';
 | 
					import * as importers from '../lib/importers';
 | 
				
			||||||
import * as buildpacks from '../lib/buildPacks';
 | 
					import * as buildpacks from '../lib/buildPacks';
 | 
				
			||||||
@@ -140,33 +141,10 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
										} catch (error) {
 | 
															} catch (error) {
 | 
				
			||||||
											//
 | 
																//
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
										const envs = [`PORT='${port}'`];
 | 
															let envs = ['NODE_ENV=production', `PORT=${port}`];
 | 
				
			||||||
										if (secrets.length > 0) {
 | 
															if (secrets.length > 0) {
 | 
				
			||||||
											secrets.forEach((secret) => {
 | 
																envs = [...envs, ...generateSecrets(secrets, pullmergeRequestId)];
 | 
				
			||||||
												if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
													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 {
 | 
					 | 
				
			||||||
													if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
														envs.push(`${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
													}
 | 
					 | 
				
			||||||
												}
 | 
					 | 
				
			||||||
											});
 | 
					 | 
				
			||||||
										}
 | 
					 | 
				
			||||||
										await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
 | 
					 | 
				
			||||||
										let envFound = false;
 | 
					 | 
				
			||||||
										try {
 | 
					 | 
				
			||||||
											envFound = !!(await fs.stat(`${workdir}/.env`));
 | 
					 | 
				
			||||||
										} catch (error) {
 | 
					 | 
				
			||||||
											//
 | 
					 | 
				
			||||||
										}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										await fs.writeFile(`${workdir}/Dockerfile`, simpleDockerfile);
 | 
															await fs.writeFile(`${workdir}/Dockerfile`, simpleDockerfile);
 | 
				
			||||||
										if (dockerRegistry) {
 | 
															if (dockerRegistry) {
 | 
				
			||||||
											const { url, username, password } = dockerRegistry;
 | 
																const { url, username, password } = dockerRegistry;
 | 
				
			||||||
@@ -197,7 +175,7 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
														container_name: applicationId,
 | 
																			container_name: applicationId,
 | 
				
			||||||
														volumes,
 | 
																			volumes,
 | 
				
			||||||
														labels,
 | 
																			labels,
 | 
				
			||||||
														env_file: envFound ? [`${workdir}/.env`] : [],
 | 
																			environment: envs,
 | 
				
			||||||
														depends_on: [],
 | 
																			depends_on: [],
 | 
				
			||||||
														expose: [port],
 | 
																			expose: [port],
 | 
				
			||||||
														...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
 | 
																			...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
 | 
				
			||||||
@@ -698,37 +676,14 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
										} catch (error) {
 | 
															} catch (error) {
 | 
				
			||||||
											//
 | 
																//
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
										const envs = [`PORT='${port}'`];
 | 
															let envs = ['NODE_ENV=production', `PORT=${port}`];
 | 
				
			||||||
										if (secrets.length > 0) {
 | 
															if (secrets.length > 0) {
 | 
				
			||||||
											secrets.forEach((secret) => {
 | 
																envs = [...envs, ...generateSecrets(secrets, pullmergeRequestId)];
 | 
				
			||||||
												if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
													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 {
 | 
					 | 
				
			||||||
													if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
														envs.push(`${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
													}
 | 
					 | 
				
			||||||
												}
 | 
					 | 
				
			||||||
											});
 | 
					 | 
				
			||||||
										}
 | 
					 | 
				
			||||||
										await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
 | 
					 | 
				
			||||||
										if (dockerRegistry) {
 | 
															if (dockerRegistry) {
 | 
				
			||||||
											const { url, username, password } = dockerRegistry;
 | 
																const { url, username, password } = dockerRegistry;
 | 
				
			||||||
											await saveDockerRegistryCredentials({ url, username, password, workdir });
 | 
																await saveDockerRegistryCredentials({ url, username, password, workdir });
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
 | 
					 | 
				
			||||||
										let envFound = false;
 | 
					 | 
				
			||||||
										try {
 | 
					 | 
				
			||||||
											envFound = !!(await fs.stat(`${workdir}/.env`));
 | 
					 | 
				
			||||||
										} catch (error) {
 | 
					 | 
				
			||||||
											//
 | 
					 | 
				
			||||||
										}
 | 
					 | 
				
			||||||
										try {
 | 
															try {
 | 
				
			||||||
											const composeVolumes = volumes.map((volume) => {
 | 
																const composeVolumes = volumes.map((volume) => {
 | 
				
			||||||
												return {
 | 
																	return {
 | 
				
			||||||
@@ -744,7 +699,7 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
														image: imageFound,
 | 
																			image: imageFound,
 | 
				
			||||||
														container_name: imageId,
 | 
																			container_name: imageId,
 | 
				
			||||||
														volumes,
 | 
																			volumes,
 | 
				
			||||||
														env_file: envFound ? [`${workdir}/.env`] : [],
 | 
																			environment: envs,
 | 
				
			||||||
														labels,
 | 
																			labels,
 | 
				
			||||||
														depends_on: [],
 | 
																			depends_on: [],
 | 
				
			||||||
														expose: [port],
 | 
																			expose: [port],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ import {
 | 
				
			|||||||
	decrypt,
 | 
						decrypt,
 | 
				
			||||||
	encrypt,
 | 
						encrypt,
 | 
				
			||||||
	executeCommand,
 | 
						executeCommand,
 | 
				
			||||||
 | 
						generateSecrets,
 | 
				
			||||||
	generateTimestamp,
 | 
						generateTimestamp,
 | 
				
			||||||
	getDomain,
 | 
						getDomain,
 | 
				
			||||||
	isARM,
 | 
						isARM,
 | 
				
			||||||
@@ -653,7 +654,7 @@ export async function saveDockerRegistryCredentials({ url, username, password, w
 | 
				
			|||||||
	try {
 | 
						try {
 | 
				
			||||||
		await fs.mkdir(`${workdir}/.docker`);
 | 
							await fs.mkdir(`${workdir}/.docker`);
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.log(error);
 | 
							// console.log(error);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const payload = JSON.stringify({
 | 
						const payload = JSON.stringify({
 | 
				
			||||||
		auths: {
 | 
							auths: {
 | 
				
			||||||
@@ -787,21 +788,8 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (isPnpm) {
 | 
						if (isPnpm) {
 | 
				
			||||||
@@ -811,7 +799,6 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
 | 
				
			|||||||
	if (installCommand) {
 | 
						if (installCommand) {
 | 
				
			||||||
		Dockerfile.push(`RUN ${installCommand}`);
 | 
							Dockerfile.push(`RUN ${installCommand}`);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Dockerfile.push(`ARG CACHEBUST=1`);
 | 
					 | 
				
			||||||
	Dockerfile.push(`RUN ${buildCommand}`);
 | 
						Dockerfile.push(`RUN ${buildCommand}`);
 | 
				
			||||||
	await fs.writeFile(`${workdir}/Dockerfile-cache`, Dockerfile.join('\n'));
 | 
						await fs.writeFile(`${workdir}/Dockerfile-cache`, Dockerfile.join('\n'));
 | 
				
			||||||
	await buildImage({ ...data, isCache: true });
 | 
						await buildImage({ ...data, isCache: true });
 | 
				
			||||||
@@ -819,27 +806,13 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export async function buildCacheImageForLaravel(data, imageForBuild) {
 | 
					export async function buildCacheImageForLaravel(data, imageForBuild) {
 | 
				
			||||||
	const { workdir, buildId, secrets, pullmergeRequestId } = data;
 | 
						const { workdir, buildId, secrets, pullmergeRequestId } = data;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	const Dockerfile: Array<string> = [];
 | 
						const Dockerfile: Array<string> = [];
 | 
				
			||||||
	Dockerfile.push(`FROM ${imageForBuild}`);
 | 
						Dockerfile.push(`FROM ${imageForBuild}`);
 | 
				
			||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Dockerfile.push(`COPY *.json *.mix.js /app/`);
 | 
						Dockerfile.push(`COPY *.json *.mix.js /app/`);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
import { defaultComposeConfiguration, executeCommand } from '../common';
 | 
					import { defaultComposeConfiguration, executeCommand, generateSecrets } from '../common';
 | 
				
			||||||
import { saveBuildLog } from './common';
 | 
					import { saveBuildLog } from './common';
 | 
				
			||||||
import yaml from 'js-yaml';
 | 
					import yaml from 'js-yaml';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,30 +25,11 @@ export default async function (data) {
 | 
				
			|||||||
	if (!dockerComposeYaml.services) {
 | 
						if (!dockerComposeYaml.services) {
 | 
				
			||||||
		throw 'No Services found in docker-compose file.';
 | 
							throw 'No Services found in docker-compose file.';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const envs = [];
 | 
						let envs = ['NODE_ENV=production'];
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							envs = [...envs, ...generateSecrets(secrets, pullmergeRequestId)];
 | 
				
			||||||
			if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
				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 {
 | 
					 | 
				
			||||||
				if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
					envs.push(`${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
 | 
					 | 
				
			||||||
	let envFound = false;
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		envFound = !!(await fs.stat(`${workdir}/.env`));
 | 
					 | 
				
			||||||
	} catch (error) {
 | 
					 | 
				
			||||||
		//
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const composeVolumes = [];
 | 
						const composeVolumes = [];
 | 
				
			||||||
	if (volumes.length > 0) {
 | 
						if (volumes.length > 0) {
 | 
				
			||||||
		for (const volume of volumes) {
 | 
							for (const volume of volumes) {
 | 
				
			||||||
@@ -62,7 +43,7 @@ export default async function (data) {
 | 
				
			|||||||
	let networks = {};
 | 
						let networks = {};
 | 
				
			||||||
	for (let [key, value] of Object.entries(dockerComposeYaml.services)) {
 | 
						for (let [key, value] of Object.entries(dockerComposeYaml.services)) {
 | 
				
			||||||
		value['container_name'] = `${applicationId}-${key}`;
 | 
							value['container_name'] = `${applicationId}-${key}`;
 | 
				
			||||||
		value['env_file'] = envFound ? [`${workdir}/.env`] : [];
 | 
							value['environment'] = [...value['environment'], ...envs];
 | 
				
			||||||
		value['labels'] = labels;
 | 
							value['labels'] = labels;
 | 
				
			||||||
		// TODO: If we support separated volume for each service, we need to add it here
 | 
							// TODO: If we support separated volume for each service, we need to add it here
 | 
				
			||||||
		if (value['volumes']?.length > 0) {
 | 
							if (value['volumes']?.length > 0) {
 | 
				
			||||||
@@ -106,6 +87,7 @@ export default async function (data) {
 | 
				
			|||||||
		dockerComposeYaml['volumes'] = { ...composeVolumes };
 | 
							dockerComposeYaml['volumes'] = { ...composeVolumes };
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dockerComposeYaml['networks'] = Object.assign({ ...networks }, { [network]: { external: true } });
 | 
						dockerComposeYaml['networks'] = Object.assign({ ...networks }, { [network]: { external: true } });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	await fs.writeFile(fileYaml, yaml.dump(dockerComposeYaml));
 | 
						await fs.writeFile(fileYaml, yaml.dump(dockerComposeYaml));
 | 
				
			||||||
	await executeCommand({
 | 
						await executeCommand({
 | 
				
			||||||
		debug,
 | 
							debug,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildImage } from './common';
 | 
					import { buildImage } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -24,21 +25,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (depsFound) {
 | 
						if (depsFound) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildImage } from './common';
 | 
					import { buildImage } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function (data) {
 | 
					export default async function (data) {
 | 
				
			||||||
@@ -13,19 +14,12 @@ export default async function (data) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
					 | 
				
			||||||
				if (
 | 
					 | 
				
			||||||
					(pullmergeRequestId && secret.isPRMRSecret) ||
 | 
					 | 
				
			||||||
					(!pullmergeRequestId && !secret.isPRMRSecret)
 | 
					 | 
				
			||||||
				) {
 | 
					 | 
				
			||||||
			Dockerfile.forEach((line, index) => {
 | 
								Dockerfile.forEach((line, index) => {
 | 
				
			||||||
				if (line.startsWith('FROM')) {
 | 
									if (line.startsWith('FROM')) {
 | 
				
			||||||
							Dockerfile.splice(index + 1, 0, `ARG ${secret.name}='${secret.value}'`);
 | 
										Dockerfile.splice(index + 1, 0, env);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	await fs.writeFile(`${data.workdir}${dockerFileLocation}`, Dockerfile.join('\n'));
 | 
						await fs.writeFile(`${data.workdir}${dockerFileLocation}`, Dockerfile.join('\n'));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildCacheImageWithNode, buildImage, checkPnpm } from './common';
 | 
					import { buildCacheImageWithNode, buildImage, checkPnpm } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -24,21 +25,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (isPnpm) {
 | 
						if (isPnpm) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildImage, checkPnpm } from './common';
 | 
					import { buildImage, checkPnpm } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -20,21 +21,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (isPnpm) {
 | 
						if (isPnpm) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildCacheImageWithNode, buildImage, checkPnpm } from './common';
 | 
					import { buildCacheImageWithNode, buildImage, checkPnpm } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -24,21 +25,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (isPnpm) {
 | 
						if (isPnpm) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildImage } from './common';
 | 
					import { buildImage } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image, htaccessFound): Promise<void> => {
 | 
					const createDockerfile = async (data, image, htaccessFound): Promise<void> => {
 | 
				
			||||||
@@ -13,21 +14,8 @@ const createDockerfile = async (data, image, htaccessFound): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push(`FROM ${image}`);
 | 
						Dockerfile.push(`FROM ${image}`);
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildImage } from './common';
 | 
					import { buildImage } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -18,21 +19,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	Dockerfile.push('WORKDIR /app');
 | 
						Dockerfile.push('WORKDIR /app');
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (pythonWSGI?.toLowerCase() === 'gunicorn') {
 | 
						if (pythonWSGI?.toLowerCase() === 'gunicorn') {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { promises as fs } from 'fs';
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import { generateSecrets } from '../common';
 | 
				
			||||||
import { buildCacheImageWithNode, buildImage } from './common';
 | 
					import { buildCacheImageWithNode, buildImage } from './common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createDockerfile = async (data, image): Promise<void> => {
 | 
					const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			||||||
@@ -25,21 +26,8 @@ const createDockerfile = async (data, image): Promise<void> => {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
						Dockerfile.push(`LABEL coolify.buildId=${buildId}`);
 | 
				
			||||||
	if (secrets.length > 0) {
 | 
						if (secrets.length > 0) {
 | 
				
			||||||
		secrets.forEach((secret) => {
 | 
							generateSecrets(secrets, pullmergeRequestId, true).forEach((env) => {
 | 
				
			||||||
			if (secret.isBuildSecret) {
 | 
								Dockerfile.push(env);
 | 
				
			||||||
				if (pullmergeRequestId) {
 | 
					 | 
				
			||||||
					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 {
 | 
					 | 
				
			||||||
					if (!secret.isPRMRSecret) {
 | 
					 | 
				
			||||||
						Dockerfile.push(`ARG ${secret.name}='${secret.value}'`);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (buildCommand) {
 | 
						if (buildCommand) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ import { saveBuildLog, saveDockerRegistryCredentials } from './buildPacks/common
 | 
				
			|||||||
import { scheduler } from './scheduler';
 | 
					import { scheduler } from './scheduler';
 | 
				
			||||||
import type { ExecaChildProcess } from 'execa';
 | 
					import type { ExecaChildProcess } from 'execa';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const version = '3.12.2';
 | 
					export const version = '3.12.3';
 | 
				
			||||||
export const isDev = process.env.NODE_ENV === 'development';
 | 
					export const isDev = process.env.NODE_ENV === 'development';
 | 
				
			||||||
export const sentryDSN =
 | 
					export const sentryDSN =
 | 
				
			||||||
	'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
 | 
						'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
 | 
				
			||||||
@@ -1875,3 +1875,48 @@ export async function pushToRegistry(
 | 
				
			|||||||
		command: pushCommand
 | 
							command: pushCommand
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function generateSecrets(
 | 
				
			||||||
 | 
						secrets: Array<any>,
 | 
				
			||||||
 | 
						pullmergeRequestId: string,
 | 
				
			||||||
 | 
						isBuild = false
 | 
				
			||||||
 | 
					): Array<string> {
 | 
				
			||||||
 | 
						const envs = [];
 | 
				
			||||||
 | 
						const isPRMRSecret = secrets.filter((s) => s.isPRMRSecret);
 | 
				
			||||||
 | 
						const normalSecrets = secrets.filter((s) => !s.isPRMRSecret);
 | 
				
			||||||
 | 
						if (pullmergeRequestId && isPRMRSecret.length > 0) {
 | 
				
			||||||
 | 
							isPRMRSecret.forEach((secret) => {
 | 
				
			||||||
 | 
								if (isBuild && !secret.isBuildSecret) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								const build = isBuild && secret.isBuildSecret;
 | 
				
			||||||
 | 
								if (build) {
 | 
				
			||||||
 | 
									if (secret.value.includes(' ') || secret.value.includes('\\n')) {
 | 
				
			||||||
 | 
										envs.push(`ARG ${secret.name}='${secret.value}'`);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										envs.push(`ARG ${secret.name}=${secret.value}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									envs.push(`${secret.name}=${secret.value}`);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!pullmergeRequestId && normalSecrets.length > 0) {
 | 
				
			||||||
 | 
							normalSecrets.forEach((secret) => {
 | 
				
			||||||
 | 
								if (isBuild && !secret.isBuildSecret) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								const build = isBuild && secret.isBuildSecret;
 | 
				
			||||||
 | 
								if (build) {
 | 
				
			||||||
 | 
									if (secret.value.includes(' ') || secret.value.includes('\\n')) {
 | 
				
			||||||
 | 
										envs.push(`ARG ${secret.name}='${secret.value}'`);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										envs.push(`ARG ${secret.name}=${secret.value}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									envs.push(`${secret.name}=${secret.value}`);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return envs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -203,20 +203,32 @@ export const applicationsRouter = router({
 | 
				
			|||||||
			let location = null;
 | 
								let location = null;
 | 
				
			||||||
			const labels = [];
 | 
								const labels = [];
 | 
				
			||||||
			let image = null;
 | 
								let image = null;
 | 
				
			||||||
			const envs = [`PORT=${port}`];
 | 
								const envs = [`PORT=${port}`, 'NODE_ENV=production'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (secrets.length > 0) {
 | 
								if (secrets.length > 0) {
 | 
				
			||||||
				secrets.forEach((secret) => {
 | 
									secrets.forEach((secret) => {
 | 
				
			||||||
					if (pullmergeRequestId) {
 | 
										if (pullmergeRequestId) {
 | 
				
			||||||
						const isSecretFound = secrets.filter((s) => s.name === secret.name && s.isPRMRSecret);
 | 
											const isSecretFound = secrets.filter((s) => s.name === secret.name && s.isPRMRSecret);
 | 
				
			||||||
						if (isSecretFound.length > 0) {
 | 
											if (isSecretFound.length > 0) {
 | 
				
			||||||
 | 
					              if (isSecretFound[0].value.includes('\\n') || isSecretFound[0].value.includes("'")) {
 | 
				
			||||||
 | 
												envs.push(`${secret.name}=${isSecretFound[0].value}`);
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
							envs.push(`${secret.name}='${isSecretFound[0].value}'`);
 | 
												envs.push(`${secret.name}='${isSecretFound[0].value}'`);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
					              if (secret.value.includes('\\n')|| secret.value.includes("'")) {
 | 
				
			||||||
 | 
												envs.push(`${secret.name}=${secret.value}`);
 | 
				
			||||||
              } else {
 | 
					              } else {
 | 
				
			||||||
							envs.push(`${secret.name}='${secret.value}'`);
 | 
												envs.push(`${secret.name}='${secret.value}'`);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						if (!secret.isPRMRSecret) {
 | 
											if (!secret.isPRMRSecret) {
 | 
				
			||||||
 | 
					              if (secret.value.includes('\\n')|| secret.value.includes("'")) {
 | 
				
			||||||
 | 
												envs.push(`${secret.name}=${secret.value}`);
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
							envs.push(`${secret.name}='${secret.value}'`);
 | 
												envs.push(`${secret.name}='${secret.value}'`);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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": "3.12.2",
 | 
					  "version": "3.12.3",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
  "repository": "github:coollabsio/coolify",
 | 
					  "repository": "github:coollabsio/coolify",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user