fix: escape env vars
This commit is contained in:
parent
4261147fe8
commit
bd7d756254
@ -3,8 +3,25 @@ import crypto from 'crypto';
|
|||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
import { copyBaseConfigurationFiles, makeLabelForSimpleDockerfile, makeLabelForStandaloneApplication, saveBuildLog, saveDockerRegistryCredentials, setDefaultConfiguration } from '../lib/buildPacks/common';
|
import {
|
||||||
import { createDirectories, decrypt, defaultComposeConfiguration, getDomain, prisma, decryptApplication, isDev, pushToRegistry, executeCommand } from '../lib/common';
|
copyBaseConfigurationFiles,
|
||||||
|
makeLabelForSimpleDockerfile,
|
||||||
|
makeLabelForStandaloneApplication,
|
||||||
|
saveBuildLog,
|
||||||
|
saveDockerRegistryCredentials,
|
||||||
|
setDefaultConfiguration
|
||||||
|
} from '../lib/buildPacks/common';
|
||||||
|
import {
|
||||||
|
createDirectories,
|
||||||
|
decrypt,
|
||||||
|
defaultComposeConfiguration,
|
||||||
|
getDomain,
|
||||||
|
prisma,
|
||||||
|
decryptApplication,
|
||||||
|
isDev,
|
||||||
|
pushToRegistry,
|
||||||
|
executeCommand
|
||||||
|
} 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';
|
||||||
|
|
||||||
@ -14,33 +31,56 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
if (message === 'error') throw new Error('oops');
|
if (message === 'error') throw new Error('oops');
|
||||||
if (message === 'cancel') {
|
if (message === 'cancel') {
|
||||||
parentPort.postMessage('cancelled');
|
parentPort.postMessage('cancelled');
|
||||||
await prisma.$disconnect()
|
await prisma.$disconnect();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const pThrottle = await import('p-throttle')
|
const pThrottle = await import('p-throttle');
|
||||||
const throttle = pThrottle.default({
|
const throttle = pThrottle.default({
|
||||||
limit: 1,
|
limit: 1,
|
||||||
interval: 2000
|
interval: 2000
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const th = throttle(async () => {
|
const th = throttle(async () => {
|
||||||
try {
|
try {
|
||||||
const queuedBuilds = await prisma.build.findMany({ where: { status: { in: ['queued', 'running'] } }, orderBy: { createdAt: 'asc' } });
|
const queuedBuilds = await prisma.build.findMany({
|
||||||
const { concurrentBuilds } = await prisma.setting.findFirst({})
|
where: { status: { in: ['queued', 'running'] } },
|
||||||
|
orderBy: { createdAt: 'asc' }
|
||||||
|
});
|
||||||
|
const { concurrentBuilds } = await prisma.setting.findFirst({});
|
||||||
if (queuedBuilds.length > 0) {
|
if (queuedBuilds.length > 0) {
|
||||||
parentPort.postMessage({ deploying: true });
|
parentPort.postMessage({ deploying: true });
|
||||||
const concurrency = concurrentBuilds;
|
const concurrency = concurrentBuilds;
|
||||||
const pAll = await import('p-all');
|
const pAll = await import('p-all');
|
||||||
const actions = []
|
const actions = [];
|
||||||
|
|
||||||
for (const queueBuild of queuedBuilds) {
|
for (const queueBuild of queuedBuilds) {
|
||||||
actions.push(async () => {
|
actions.push(async () => {
|
||||||
let application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { dockerRegistry: true, destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } })
|
const { default: escapeStringRegexp } = await import('escape-string-regexp');
|
||||||
|
let application = await prisma.application.findUnique({
|
||||||
|
where: { id: queueBuild.applicationId },
|
||||||
|
include: {
|
||||||
|
dockerRegistry: true,
|
||||||
|
destinationDocker: true,
|
||||||
|
gitSource: { include: { githubApp: true, gitlabApp: true } },
|
||||||
|
persistentStorage: true,
|
||||||
|
secrets: true,
|
||||||
|
settings: true,
|
||||||
|
teams: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let { id: buildId, type, gitSourceId, sourceBranch = null, pullmergeRequestId = null, previewApplicationId = null, forceRebuild, sourceRepository = null } = queueBuild
|
let {
|
||||||
application = decryptApplication(application)
|
id: buildId,
|
||||||
|
type,
|
||||||
|
gitSourceId,
|
||||||
|
sourceBranch = null,
|
||||||
|
pullmergeRequestId = null,
|
||||||
|
previewApplicationId = null,
|
||||||
|
forceRebuild,
|
||||||
|
sourceRepository = null
|
||||||
|
} = queueBuild;
|
||||||
|
application = decryptApplication(application);
|
||||||
|
|
||||||
if (!gitSourceId && application.simpleDockerfile) {
|
if (!gitSourceId && application.simpleDockerfile) {
|
||||||
const {
|
const {
|
||||||
@ -53,54 +93,81 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
exposePort,
|
exposePort,
|
||||||
simpleDockerfile,
|
simpleDockerfile,
|
||||||
dockerRegistry
|
dockerRegistry
|
||||||
} = application
|
} = application;
|
||||||
const { workdir } = await createDirectories({ repository: applicationId, buildId });
|
const { workdir } = await createDirectories({ repository: applicationId, buildId });
|
||||||
try {
|
try {
|
||||||
if (queueBuild.status === 'running') {
|
if (queueBuild.status === 'running') {
|
||||||
await saveBuildLog({ line: 'Building halted, restarting...', buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
|
line: 'Building halted, restarting...',
|
||||||
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const volumes =
|
const volumes =
|
||||||
persistentStorage?.map((storage) => {
|
persistentStorage?.map((storage) => {
|
||||||
if (storage.oldPath) {
|
if (storage.oldPath) {
|
||||||
return `${applicationId}${storage.path.replace(/\//gi, '-').replace('-app', '')}:${storage.path}`;
|
return `${applicationId}${storage.path
|
||||||
|
.replace(/\//gi, '-')
|
||||||
|
.replace('-app', '')}:${storage.path}`;
|
||||||
}
|
}
|
||||||
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${storage.path}`;
|
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${storage.path}`;
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'running' } });
|
await prisma.build.update({
|
||||||
|
where: { id: buildId },
|
||||||
|
data: { status: 'running' }
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
const { stdout: containers } = await executeCommand({
|
const { stdout: containers } = await executeCommand({
|
||||||
dockerId: destinationDockerId,
|
dockerId: destinationDockerId,
|
||||||
command: `docker ps -a --filter 'label=com.docker.compose.service=${applicationId}' --format {{.ID}}`
|
command: `docker ps -a --filter 'label=com.docker.compose.service=${applicationId}' --format {{.ID}}`
|
||||||
})
|
});
|
||||||
if (containers) {
|
if (containers) {
|
||||||
const containerArray = containers.split('\n');
|
const containerArray = containers.split('\n');
|
||||||
if (containerArray.length > 0) {
|
if (containerArray.length > 0) {
|
||||||
for (const container of containerArray) {
|
for (const container of containerArray) {
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker stop -t 0 ${container}` })
|
await executeCommand({
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker rm --force ${container}` })
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker stop -t 0 ${container}`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker rm --force ${container}`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
const envs = [
|
const envs = [`PORT=${port}`];
|
||||||
`PORT=${port}`
|
|
||||||
];
|
|
||||||
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) {
|
||||||
envs.push(`${secret.name}=${isSecretFound[0].value}`);
|
envs.push(
|
||||||
|
`${secret.name}="${escapeStringRegexp(
|
||||||
|
isSecretFound[0].value.replace(/[\\$'"]/g, '\\$&')
|
||||||
|
)}"`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
envs.push(`${secret.name}=${secret.value}`);
|
envs.push(
|
||||||
|
`${secret.name}="${escapeStringRegexp(
|
||||||
|
secret.value.replace(/[\\$'"]/g, '\\$&')
|
||||||
|
)}"`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!secret.isPRMRSecret) {
|
if (!secret.isPRMRSecret) {
|
||||||
envs.push(`${secret.name}=${secret.value}`);
|
envs.push(
|
||||||
|
`${secret.name}="${escapeStringRegexp(
|
||||||
|
secret.value.replace(/[\\$'"]/g, '\\$&')
|
||||||
|
)}"`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -115,14 +182,14 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
|
|
||||||
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;
|
||||||
await saveDockerRegistryCredentials({ url, username, password, workdir })
|
await saveDockerRegistryCredentials({ url, username, password, workdir });
|
||||||
}
|
}
|
||||||
|
|
||||||
const labels = makeLabelForSimpleDockerfile({
|
const labels = makeLabelForSimpleDockerfile({
|
||||||
applicationId,
|
applicationId,
|
||||||
type,
|
type,
|
||||||
port: exposePort ? `${exposePort}:${port}` : port,
|
port: exposePort ? `${exposePort}:${port}` : port
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
const composeVolumes = volumes.map((volume) => {
|
const composeVolumes = volumes.map((volume) => {
|
||||||
@ -137,7 +204,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
services: {
|
services: {
|
||||||
[applicationId]: {
|
[applicationId]: {
|
||||||
build: {
|
build: {
|
||||||
context: workdir,
|
context: workdir
|
||||||
},
|
},
|
||||||
image: `${applicationId}:${buildId}`,
|
image: `${applicationId}:${buildId}`,
|
||||||
container_name: applicationId,
|
container_name: applicationId,
|
||||||
@ -147,7 +214,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
depends_on: [],
|
depends_on: [],
|
||||||
expose: [port],
|
expose: [port],
|
||||||
...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
|
...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
|
||||||
...defaultComposeConfiguration(destinationDocker.network),
|
...defaultComposeConfiguration(destinationDocker.network)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
networks: {
|
networks: {
|
||||||
@ -158,11 +225,15 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
volumes: Object.assign({}, ...composeVolumes)
|
volumes: Object.assign({}, ...composeVolumes)
|
||||||
};
|
};
|
||||||
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
||||||
await executeCommand({ debug: true, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` })
|
await executeCommand({
|
||||||
|
debug: true,
|
||||||
|
dockerId: destinationDocker.id,
|
||||||
|
command: `docker compose --project-directory ${workdir} up -d`
|
||||||
|
});
|
||||||
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await saveBuildLog({ line: error, buildId, applicationId });
|
await saveBuildLog({ line: error, buildId, applicationId });
|
||||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } });
|
||||||
if (foundBuild) {
|
if (foundBuild) {
|
||||||
await prisma.build.update({
|
await prisma.build.update({
|
||||||
where: { id: buildId },
|
where: { id: buildId },
|
||||||
@ -173,10 +244,9 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
}
|
}
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } });
|
||||||
if (foundBuild) {
|
if (foundBuild) {
|
||||||
await prisma.build.update({
|
await prisma.build.update({
|
||||||
where: { id: buildId },
|
where: { id: buildId },
|
||||||
@ -189,7 +259,11 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
||||||
}
|
}
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
await saveBuildLog({ line: error.message, buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
|
line: error.message,
|
||||||
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await fs.rm(workdir, { recursive: true, force: true });
|
await fs.rm(workdir, { recursive: true, force: true });
|
||||||
return;
|
return;
|
||||||
@ -198,9 +272,13 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
if (application.dockerRegistryImageName) {
|
if (application.dockerRegistryImageName) {
|
||||||
const customTag = application.dockerRegistryImageName.split(':')[1] || buildId;
|
const customTag = application.dockerRegistryImageName.split(':')[1] || buildId;
|
||||||
const imageName = application.dockerRegistryImageName.split(':')[0];
|
const imageName = application.dockerRegistryImageName.split(':')[0];
|
||||||
await saveBuildLog({ line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`, buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
await pushToRegistry(application, workdir, buildId, imageName, customTag)
|
line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`,
|
||||||
await saveBuildLog({ line: "Success", buildId, applicationId: application.id });
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
|
await pushToRegistry(application, workdir, buildId, imageName, customTag);
|
||||||
|
await saveBuildLog({ line: 'Success', buildId, applicationId: application.id });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.stdout) {
|
if (error.stdout) {
|
||||||
@ -211,12 +289,15 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
await fs.rm(workdir, { recursive: true, force: true });
|
await fs.rm(workdir, { recursive: true, force: true });
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
await prisma.build.update({
|
||||||
|
where: { id: buildId },
|
||||||
|
data: { status: 'success' }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalApplicationId = application.id
|
const originalApplicationId = application.id;
|
||||||
const {
|
const {
|
||||||
id: applicationId,
|
id: applicationId,
|
||||||
name,
|
name,
|
||||||
@ -240,7 +321,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
deploymentType,
|
deploymentType,
|
||||||
gitCommitHash,
|
gitCommitHash,
|
||||||
dockerRegistry
|
dockerRegistry
|
||||||
} = application
|
} = application;
|
||||||
|
|
||||||
let {
|
let {
|
||||||
branch,
|
branch,
|
||||||
@ -256,7 +337,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
dockerComposeFileLocation,
|
dockerComposeFileLocation,
|
||||||
dockerComposeConfiguration,
|
dockerComposeConfiguration,
|
||||||
denoMainFile
|
denoMainFile
|
||||||
} = application
|
} = application;
|
||||||
|
|
||||||
let imageId = applicationId;
|
let imageId = applicationId;
|
||||||
let domain = getDomain(fqdn);
|
let domain = getDomain(fqdn);
|
||||||
@ -271,9 +352,11 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
let imageFoundRemotely = false;
|
let imageFoundRemotely = false;
|
||||||
|
|
||||||
if (pullmergeRequestId) {
|
if (pullmergeRequestId) {
|
||||||
const previewApplications = await prisma.previewApplication.findMany({ where: { applicationId: originalApplicationId, pullmergeRequestId } })
|
const previewApplications = await prisma.previewApplication.findMany({
|
||||||
|
where: { applicationId: originalApplicationId, pullmergeRequestId }
|
||||||
|
});
|
||||||
if (previewApplications.length > 0) {
|
if (previewApplications.length > 0) {
|
||||||
previewApplicationId = previewApplications[0].id
|
previewApplicationId = previewApplications[0].id;
|
||||||
}
|
}
|
||||||
// Previews, we need to get the source branch and set subdomain
|
// Previews, we need to get the source branch and set subdomain
|
||||||
branch = sourceBranch;
|
branch = sourceBranch;
|
||||||
@ -284,7 +367,11 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
const { workdir, repodir } = await createDirectories({ repository, buildId });
|
const { workdir, repodir } = await createDirectories({ repository, buildId });
|
||||||
try {
|
try {
|
||||||
if (queueBuild.status === 'running') {
|
if (queueBuild.status === 'running') {
|
||||||
await saveBuildLog({ line: 'Building halted, restarting...', buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
|
line: 'Building halted, restarting...',
|
||||||
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentHash = crypto
|
const currentHash = crypto
|
||||||
@ -322,15 +409,16 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
const volumes =
|
const volumes =
|
||||||
persistentStorage?.map((storage) => {
|
persistentStorage?.map((storage) => {
|
||||||
if (storage.oldPath) {
|
if (storage.oldPath) {
|
||||||
return `${applicationId}${storage.path.replace(/\//gi, '-').replace('-app', '')}:${storage.path}`;
|
return `${applicationId}${storage.path
|
||||||
|
.replace(/\//gi, '-')
|
||||||
|
.replace('-app', '')}:${storage.path}`;
|
||||||
}
|
}
|
||||||
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${storage.path}`;
|
return `${applicationId}${storage.path.replace(/\//gi, '-')}:${storage.path}`;
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dockerComposeConfiguration = JSON.parse(dockerComposeConfiguration)
|
dockerComposeConfiguration = JSON.parse(dockerComposeConfiguration);
|
||||||
} catch (error) { }
|
} catch (error) {}
|
||||||
let deployNeeded = true;
|
let deployNeeded = true;
|
||||||
let destinationType;
|
let destinationType;
|
||||||
|
|
||||||
@ -338,7 +426,10 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
destinationType = 'docker';
|
destinationType = 'docker';
|
||||||
}
|
}
|
||||||
if (destinationType === 'docker') {
|
if (destinationType === 'docker') {
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'running' } });
|
await prisma.build.update({
|
||||||
|
where: { id: buildId },
|
||||||
|
data: { status: 'running' }
|
||||||
|
});
|
||||||
|
|
||||||
const configuration = await setDefaultConfiguration(application);
|
const configuration = await setDefaultConfiguration(application);
|
||||||
|
|
||||||
@ -380,10 +471,10 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`;
|
tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`;
|
||||||
}
|
}
|
||||||
if (application.dockerRegistryImageName) {
|
if (application.dockerRegistryImageName) {
|
||||||
imageName = application.dockerRegistryImageName.split(':')[0]
|
imageName = application.dockerRegistryImageName.split(':')[0];
|
||||||
customTag = application.dockerRegistryImageName.split(':')[1] || tag
|
customTag = application.dockerRegistryImageName.split(':')[1] || tag;
|
||||||
} else {
|
} else {
|
||||||
customTag = tag
|
customTag = tag;
|
||||||
imageName = applicationId;
|
imageName = applicationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,13 +484,17 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { commit } });
|
await prisma.build.update({ where: { id: buildId }, data: { commit } });
|
||||||
} catch (err) { }
|
} catch (err) {}
|
||||||
|
|
||||||
if (!pullmergeRequestId) {
|
if (!pullmergeRequestId) {
|
||||||
if (configHash !== currentHash) {
|
if (configHash !== currentHash) {
|
||||||
deployNeeded = true;
|
deployNeeded = true;
|
||||||
if (configHash) {
|
if (configHash) {
|
||||||
await saveBuildLog({ line: 'Configuration changed', buildId, applicationId });
|
await saveBuildLog({
|
||||||
|
line: 'Configuration changed',
|
||||||
|
buildId,
|
||||||
|
applicationId
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
deployNeeded = false;
|
deployNeeded = false;
|
||||||
@ -412,31 +507,44 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
await executeCommand({
|
await executeCommand({
|
||||||
dockerId: destinationDocker.id,
|
dockerId: destinationDocker.id,
|
||||||
command: `docker image inspect ${applicationId}:${tag}`
|
command: `docker image inspect ${applicationId}:${tag}`
|
||||||
})
|
});
|
||||||
imageFoundLocally = true;
|
imageFoundLocally = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
if (dockerRegistry) {
|
if (dockerRegistry) {
|
||||||
const { url, username, password } = dockerRegistry
|
const { url, username, password } = dockerRegistry;
|
||||||
location = await saveDockerRegistryCredentials({ url, username, password, workdir })
|
location = await saveDockerRegistryCredentials({
|
||||||
|
url,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
workdir
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await executeCommand({
|
await executeCommand({
|
||||||
dockerId: destinationDocker.id,
|
dockerId: destinationDocker.id,
|
||||||
command: `docker ${location ? `--config ${location}` : ''} pull ${imageName}:${customTag}`
|
command: `docker ${
|
||||||
})
|
location ? `--config ${location}` : ''
|
||||||
|
} pull ${imageName}:${customTag}`
|
||||||
|
});
|
||||||
imageFoundRemotely = true;
|
imageFoundRemotely = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
let imageFound = `${applicationId}:${tag}`
|
let imageFound = `${applicationId}:${tag}`;
|
||||||
if (imageFoundRemotely) {
|
if (imageFoundRemotely) {
|
||||||
imageFound = `${imageName}:${customTag}`
|
imageFound = `${imageName}:${customTag}`;
|
||||||
}
|
}
|
||||||
await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId, baseImage);
|
await copyBaseConfigurationFiles(
|
||||||
console.log({secrets})
|
buildPack,
|
||||||
|
workdir,
|
||||||
|
buildId,
|
||||||
|
applicationId,
|
||||||
|
baseImage
|
||||||
|
);
|
||||||
|
console.log({ secrets });
|
||||||
const labels = makeLabelForStandaloneApplication({
|
const labels = makeLabelForStandaloneApplication({
|
||||||
applicationId,
|
applicationId,
|
||||||
fqdn,
|
fqdn,
|
||||||
@ -455,7 +563,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
baseDirectory,
|
baseDirectory,
|
||||||
publishDirectory
|
publishDirectory
|
||||||
});
|
});
|
||||||
if (forceRebuild) deployNeeded = true
|
if (forceRebuild) deployNeeded = true;
|
||||||
if ((!imageFoundLocally && !imageFoundRemotely) || deployNeeded) {
|
if ((!imageFoundLocally && !imageFoundRemotely) || deployNeeded) {
|
||||||
if (buildpacks[buildPack])
|
if (buildpacks[buildPack])
|
||||||
await buildpacks[buildPack]({
|
await buildpacks[buildPack]({
|
||||||
@ -495,18 +603,30 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage,
|
baseImage,
|
||||||
baseBuildImage,
|
baseBuildImage,
|
||||||
deploymentType,
|
deploymentType
|
||||||
});
|
});
|
||||||
else {
|
else {
|
||||||
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });
|
await saveBuildLog({
|
||||||
|
line: `Build pack ${buildPack} not found`,
|
||||||
|
buildId,
|
||||||
|
applicationId
|
||||||
|
});
|
||||||
throw new Error(`Build pack ${buildPack} not found.`);
|
throw new Error(`Build pack ${buildPack} not found.`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (imageFoundRemotely || deployNeeded) {
|
if (imageFoundRemotely || deployNeeded) {
|
||||||
await saveBuildLog({ line: `Container image ${imageFound} found in Docker Registry - reuising it`, buildId, applicationId });
|
await saveBuildLog({
|
||||||
|
line: `Container image ${imageFound} found in Docker Registry - reuising it`,
|
||||||
|
buildId,
|
||||||
|
applicationId
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (imageFoundLocally || deployNeeded) {
|
if (imageFoundLocally || deployNeeded) {
|
||||||
await saveBuildLog({ line: `Container image ${imageFound} found locally - reuising it`, buildId, applicationId });
|
await saveBuildLog({
|
||||||
|
line: `Container image ${imageFound} found locally - reuising it`,
|
||||||
|
buildId,
|
||||||
|
applicationId
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,13 +636,19 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
const { stdout: containers } = await executeCommand({
|
const { stdout: containers } = await executeCommand({
|
||||||
dockerId: destinationDockerId,
|
dockerId: destinationDockerId,
|
||||||
command: `docker ps -a --filter 'label=coolify.applicationId=${applicationId}' --format {{.ID}}`
|
command: `docker ps -a --filter 'label=coolify.applicationId=${applicationId}' --format {{.ID}}`
|
||||||
})
|
});
|
||||||
if (containers) {
|
if (containers) {
|
||||||
const containerArray = containers.split('\n');
|
const containerArray = containers.split('\n');
|
||||||
if (containerArray.length > 0) {
|
if (containerArray.length > 0) {
|
||||||
for (const container of containerArray) {
|
for (const container of containerArray) {
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker stop -t 0 ${container}` })
|
await executeCommand({
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker rm --force ${container}` })
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker stop -t 0 ${container}`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker rm --force ${container}`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,16 +656,25 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await executeCommand({ debug, buildId, applicationId, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` })
|
await executeCommand({
|
||||||
|
debug,
|
||||||
|
buildId,
|
||||||
|
applicationId,
|
||||||
|
dockerId: destinationDocker.id,
|
||||||
|
command: `docker compose --project-directory ${workdir} up -d`
|
||||||
|
});
|
||||||
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
await prisma.build.update({
|
||||||
|
where: { id: buildId },
|
||||||
|
data: { status: 'success' }
|
||||||
|
});
|
||||||
await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id: applicationId },
|
where: { id: applicationId },
|
||||||
data: { configHash: currentHash }
|
data: { configHash: currentHash }
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await saveBuildLog({ line: error, buildId, applicationId });
|
await saveBuildLog({ line: error, buildId, applicationId });
|
||||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } });
|
||||||
if (foundBuild) {
|
if (foundBuild) {
|
||||||
await prisma.build.update({
|
await prisma.build.update({
|
||||||
where: { id: buildId },
|
where: { id: buildId },
|
||||||
@ -550,32 +685,39 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
}
|
}
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const { stdout: containers } = await executeCommand({
|
const { stdout: containers } = await executeCommand({
|
||||||
dockerId: destinationDockerId,
|
dockerId: destinationDockerId,
|
||||||
command: `docker ps -a --filter 'label=com.docker.compose.service=${pullmergeRequestId ? imageId : applicationId}' --format {{.ID}}`
|
command: `docker ps -a --filter 'label=com.docker.compose.service=${
|
||||||
})
|
pullmergeRequestId ? imageId : applicationId
|
||||||
|
}' --format {{.ID}}`
|
||||||
|
});
|
||||||
if (containers) {
|
if (containers) {
|
||||||
const containerArray = containers.split('\n');
|
const containerArray = containers.split('\n');
|
||||||
if (containerArray.length > 0) {
|
if (containerArray.length > 0) {
|
||||||
for (const container of containerArray) {
|
for (const container of containerArray) {
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker stop -t 0 ${container}` })
|
await executeCommand({
|
||||||
await executeCommand({ dockerId: destinationDockerId, command: `docker rm --force ${container}` })
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker stop -t 0 ${container}`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker rm --force ${container}`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
const envs = [
|
const envs = [`PORT=${port}`];
|
||||||
`PORT=${port}`
|
|
||||||
];
|
|
||||||
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) {
|
||||||
envs.push(`${secret.name}=${isSecretFound[0].value}`);
|
envs.push(`${secret.name}=${isSecretFound[0].value}`);
|
||||||
} else {
|
} else {
|
||||||
@ -588,11 +730,11 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log({envs})
|
console.log({ envs });
|
||||||
await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
|
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;
|
let envFound = false;
|
||||||
@ -621,7 +763,7 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
depends_on: [],
|
depends_on: [],
|
||||||
expose: [port],
|
expose: [port],
|
||||||
...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
|
...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
|
||||||
...defaultComposeConfiguration(destinationDocker.network),
|
...defaultComposeConfiguration(destinationDocker.network)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
networks: {
|
networks: {
|
||||||
@ -632,11 +774,15 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
volumes: Object.assign({}, ...composeVolumes)
|
volumes: Object.assign({}, ...composeVolumes)
|
||||||
};
|
};
|
||||||
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
||||||
await executeCommand({ debug, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` })
|
await executeCommand({
|
||||||
|
debug,
|
||||||
|
dockerId: destinationDocker.id,
|
||||||
|
command: `docker compose --project-directory ${workdir} up -d`
|
||||||
|
});
|
||||||
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await saveBuildLog({ line: error, buildId, applicationId });
|
await saveBuildLog({ line: error, buildId, applicationId });
|
||||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } });
|
||||||
if (foundBuild) {
|
if (foundBuild) {
|
||||||
await prisma.build.update({
|
await prisma.build.update({
|
||||||
where: { id: buildId },
|
where: { id: buildId },
|
||||||
@ -648,14 +794,15 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pullmergeRequestId) await prisma.application.update({
|
if (!pullmergeRequestId)
|
||||||
where: { id: applicationId },
|
await prisma.application.update({
|
||||||
data: { configHash: currentHash }
|
where: { id: applicationId },
|
||||||
});
|
data: { configHash: currentHash }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } });
|
||||||
if (foundBuild) {
|
if (foundBuild) {
|
||||||
await prisma.build.update({
|
await prisma.build.update({
|
||||||
where: { id: buildId },
|
where: { id: buildId },
|
||||||
@ -668,16 +815,24 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
||||||
}
|
}
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
await saveBuildLog({ line: error.message, buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
|
line: error.message,
|
||||||
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await fs.rm(workdir, { recursive: true, force: true });
|
await fs.rm(workdir, { recursive: true, force: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (application.dockerRegistryImageName && (!imageFoundRemotely || forceRebuild)) {
|
if (application.dockerRegistryImageName && (!imageFoundRemotely || forceRebuild)) {
|
||||||
await saveBuildLog({ line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`, buildId, applicationId: application.id });
|
await saveBuildLog({
|
||||||
await pushToRegistry(application, workdir, tag, imageName, customTag)
|
line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`,
|
||||||
await saveBuildLog({ line: "Success", buildId, applicationId: application.id });
|
buildId,
|
||||||
|
applicationId: application.id
|
||||||
|
});
|
||||||
|
await pushToRegistry(application, workdir, tag, imageName, customTag);
|
||||||
|
await saveBuildLog({ line: 'Success', buildId, applicationId: application.id });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.stdout) {
|
if (error.stdout) {
|
||||||
@ -686,21 +841,20 @@ import * as buildpacks from '../lib/buildPacks';
|
|||||||
if (error.stderr) {
|
if (error.stderr) {
|
||||||
await saveBuildLog({ line: error.stderr, buildId, applicationId });
|
await saveBuildLog({ line: error.stderr, buildId, applicationId });
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
await fs.rm(workdir, { recursive: true, force: true });
|
await fs.rm(workdir, { recursive: true, force: true });
|
||||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await pAll.default(actions, { concurrency })
|
await pAll.default(actions, { concurrency });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
while (true) {
|
while (true) {
|
||||||
await th()
|
await th();
|
||||||
}
|
}
|
||||||
} else process.exit(0);
|
} else process.exit(0);
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user