116 lines
4.4 KiB
TypeScript
116 lines
4.4 KiB
TypeScript
import { promises as fs } from 'fs';
|
|
import { defaultComposeConfiguration, executeDockerCmd } from '../common';
|
|
import { buildImage, saveBuildLog } from './common';
|
|
import yaml from 'js-yaml';
|
|
|
|
export default async function (data) {
|
|
let {
|
|
applicationId,
|
|
debug,
|
|
buildId,
|
|
dockerId,
|
|
network,
|
|
volumes,
|
|
labels,
|
|
workdir,
|
|
baseDirectory,
|
|
secrets,
|
|
pullmergeRequestId,
|
|
port,
|
|
dockerComposeConfiguration
|
|
} = data
|
|
const fileYml = `${workdir}${baseDirectory}/docker-compose.yml`;
|
|
const fileYaml = `${workdir}${baseDirectory}/docker-compose.yaml`;
|
|
let dockerComposeRaw = null;
|
|
let isYml = false;
|
|
try {
|
|
dockerComposeRaw = await fs.readFile(`${fileYml}`, 'utf8')
|
|
isYml = true
|
|
} catch (error) { }
|
|
try {
|
|
dockerComposeRaw = await fs.readFile(`${fileYaml}`, 'utf8')
|
|
} catch (error) { }
|
|
|
|
if (!dockerComposeRaw) {
|
|
throw ('docker-compose.yml or docker-compose.yaml are not found!');
|
|
}
|
|
const dockerComposeYaml = yaml.load(dockerComposeRaw)
|
|
if (!dockerComposeYaml.services) {
|
|
throw 'No Services found in docker-compose file.'
|
|
}
|
|
const envs = [
|
|
`PORT=${port}`
|
|
];
|
|
if (secrets.length > 0) {
|
|
secrets.forEach((secret) => {
|
|
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 = volumes.map((volume) => {
|
|
return {
|
|
[`${volume.split(':')[0]}`]: {
|
|
name: volume.split(':')[0]
|
|
}
|
|
};
|
|
});
|
|
let networks = {}
|
|
for (let [key, value] of Object.entries(dockerComposeYaml.services)) {
|
|
value['container_name'] = `${applicationId}-${key}`
|
|
value['env_file'] = envFound ? [`${workdir}/.env`] : []
|
|
value['labels'] = labels
|
|
// TODO: If we support separated volume for each service, we need to add it here
|
|
if (value['volumes'].length > 0) {
|
|
value['volumes'] = value['volumes'].map((volume) => {
|
|
let [v, path] = volume.split(':');
|
|
v = `${applicationId}-${v}`
|
|
composeVolumes[v] = {
|
|
name: v
|
|
}
|
|
return `${v}:${path}`
|
|
})
|
|
}
|
|
if (volumes.length > 0) {
|
|
value['volumes'] = [...value['volumes'] || '', volumes]
|
|
}
|
|
if (dockerComposeConfiguration[key].port) {
|
|
value['expose'] = [dockerComposeConfiguration[key].port]
|
|
}
|
|
if (value['networks']?.length > 0) {
|
|
value['networks'].forEach((network) => {
|
|
networks[network] = {
|
|
name: network
|
|
}
|
|
})
|
|
}
|
|
value['networks'] = [...value['networks'] || '', network]
|
|
dockerComposeYaml.services[key] = { ...dockerComposeYaml.services[key], restart: defaultComposeConfiguration(network).restart, deploy: defaultComposeConfiguration(network).deploy }
|
|
}
|
|
if (Object.keys(composeVolumes).length > 0) {
|
|
dockerComposeYaml['volumes'] = {...composeVolumes}
|
|
}
|
|
dockerComposeYaml['networks'] = Object.assign({ ...networks }, { [network]: { external: true } })
|
|
await fs.writeFile(`${workdir}/docker-compose.${isYml ? 'yml' : 'yaml'}`, yaml.dump(dockerComposeYaml));
|
|
await executeDockerCmd({ debug, buildId, applicationId, dockerId, command: `docker compose --project-directory ${workdir} pull` })
|
|
await saveBuildLog({ line: 'Pulling images from Compose file.', buildId, applicationId });
|
|
await executeDockerCmd({ debug, buildId, applicationId, dockerId, command: `docker compose --project-directory ${workdir} build --progress plain` })
|
|
await saveBuildLog({ line: 'Building images from Compose file.', buildId, applicationId });
|
|
}
|