diff --git a/package.json b/package.json index 4071ffb20..a5bb1cae1 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@sveltejs/kit": "1.0.0-next.288", "@types/bcrypt": "5.0.0", "@types/js-cookie": "3.0.1", + "@types/js-yaml": "^4.0.5", "@types/node": "17.0.21", "@types/node-forge": "1.0.0", "@typescript-eslint/eslint-plugin": "4.31.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0382aae5a..f9f51fc15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,7 @@ specifiers: '@sveltejs/kit': 1.0.0-next.288 '@types/bcrypt': 5.0.0 '@types/js-cookie': 3.0.1 + '@types/js-yaml': ^4.0.5 '@types/node': 17.0.21 '@types/node-forge': 1.0.0 '@typescript-eslint/eslint-plugin': 4.31.1 @@ -84,6 +85,7 @@ devDependencies: '@sveltejs/kit': 1.0.0-next.288_svelte@3.46.4 '@types/bcrypt': 5.0.0 '@types/js-cookie': 3.0.1 + '@types/js-yaml': 4.0.5 '@types/node': 17.0.21 '@types/node-forge': 1.0.0 '@typescript-eslint/eslint-plugin': 4.31.1_386b67ad67ef29c6a0ccaf3e9b60f945 @@ -537,6 +539,13 @@ packages: } dev: true + /@types/js-yaml/4.0.5: + resolution: + { + integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== + } + dev: true + /@types/json-schema/7.0.9: resolution: { diff --git a/src/app.d.ts b/src/app.d.ts index 63734a3af..40f503598 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -9,6 +9,7 @@ declare namespace App { interface Session extends SessionData {} interface Stuff { application: any; + isRunning: boolean; } } diff --git a/src/lib/buildPacks/common.ts b/src/lib/buildPacks/common.ts index 3214f7adf..3f8b4b43e 100644 --- a/src/lib/buildPacks/common.ts +++ b/src/lib/buildPacks/common.ts @@ -29,10 +29,10 @@ export function makeLabelForStandaloneApplication({ fqdn = `${protocol}://${pullmergeRequestId}.${domain}`; } return [ - '--label coolify.managed=true', - `--label coolify.version=${version}`, - `--label coolify.type=standalone-application`, - `--label coolify.configuration=${base64Encode( + 'coolify.managed=true', + `coolify.version=${version}`, + `coolify.type=standalone-application`, + `coolify.configuration=${base64Encode( JSON.stringify({ applicationId, fqdn, diff --git a/src/lib/buildPacks/php.ts b/src/lib/buildPacks/php.ts index 3ac7b4670..abec33b3d 100644 --- a/src/lib/buildPacks/php.ts +++ b/src/lib/buildPacks/php.ts @@ -6,13 +6,6 @@ const createDockerfile = async (data, image): Promise => { const Dockerfile: Array = []; Dockerfile.push(`FROM ${image}`); Dockerfile.push(`LABEL coolify.image=true`); - if (data.phpModules?.length > 0) { - Dockerfile.push( - `ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/` - ); - Dockerfile.push(`RUN chmod +x /usr/local/bin/install-php-extensions`); - Dockerfile.push(`RUN /usr/local/bin/install-php-extensions ${data.phpModules.join(' ')}`); - } Dockerfile.push('WORKDIR /app'); Dockerfile.push(`COPY .${baseDirectory || ''} /app`); Dockerfile.push(`COPY /.htaccess .`); diff --git a/src/lib/components/common.ts b/src/lib/components/common.ts index 687819c6d..890338597 100644 --- a/src/lib/components/common.ts +++ b/src/lib/components/common.ts @@ -9,7 +9,16 @@ export const dateOptions: DateTimeFormatOptions = { hour12: false }; -export const staticDeployments = ['react', 'vuejs', 'static', 'svelte', 'gatsby', 'php']; +export const staticDeployments = [ + 'react', + 'vuejs', + 'static', + 'svelte', + 'gatsby', + 'php', + 'astro', + 'eleventy' +]; export const notNodeDeployments = ['php', 'docker', 'rust']; export function getDomain(domain) { diff --git a/src/lib/database/applications.ts b/src/lib/database/applications.ts index 1ee24a567..317793e9a 100644 --- a/src/lib/database/applications.ts +++ b/src/lib/database/applications.ts @@ -66,6 +66,7 @@ export async function removeApplication({ id, teamId }) { await prisma.buildLog.deleteMany({ where: { applicationId: id } }); await prisma.build.deleteMany({ where: { applicationId: id } }); await prisma.secret.deleteMany({ where: { applicationId: id } }); + await prisma.applicationPersistentStorage.deleteMany({ where: { applicationId: id } }); await prisma.application.deleteMany({ where: { id, teams: { some: { id: teamId } } } }); } @@ -157,9 +158,6 @@ export async function getApplication({ id, teamId }) { return s; }); } - if (body?.phpModules) { - body.phpModules = body.phpModules.split(','); - } return { ...body }; } @@ -215,8 +213,7 @@ export async function configureApplication({ buildCommand, startCommand, baseDirectory, - publishDirectory, - phpModules + publishDirectory }) { return await prisma.application.update({ where: { id }, @@ -229,8 +226,7 @@ export async function configureApplication({ startCommand, baseDirectory, publishDirectory, - name, - phpModules + name } }); } diff --git a/src/lib/queues/builder.ts b/src/lib/queues/builder.ts index dba65899b..d5f782d5b 100644 --- a/src/lib/queues/builder.ts +++ b/src/lib/queues/builder.ts @@ -19,6 +19,7 @@ import { makeLabelForStandaloneApplication, setDefaultConfiguration } from '$lib/buildPacks/common'; +import yaml from 'js-yaml'; export default async function (job) { /* @@ -71,7 +72,7 @@ export default async function (job) { let volumes = persistentStorage?.map((storage) => { return `${applicationId}${storage.path.replace(/\//gi, '-')}:${ - type !== 'docker' ? '/app/' : '' + type !== 'docker' ? '/app' : '' }${storage.path}`; }) || []; // Previews, we need to get the source branch and set subdomain @@ -261,23 +262,53 @@ export default async function (job) { } try { saveBuildLog({ line: 'Deployment started.', buildId, applicationId }); - for await (const volume of volumes) { - const id = volume.split(':')[0]; - try { - await asyncExecShell(`DOCKER_HOST=${host} docker volume inspect ${id}`); - } catch (error) { - await asyncExecShell(`DOCKER_HOST=${host} docker volume create ${id}`); - } - } - volumes = volumes.map((volume) => `-v ${volume} `).join(); - const { stderr } = await asyncExecShell( - `DOCKER_HOST=${host} docker run ${envFound && `--env-file=${workdir}/.env`} ${labels.join( - ' ' - )} --name ${imageId} --network ${docker.network} --restart always ${ - volumes.length > 0 ? volumes : '' - } -d ${applicationId}:${tag}` + // for await (const volume of volumes) { + // const id = volume.split(':')[0]; + // try { + // await asyncExecShell(`DOCKER_HOST=${host} docker volume inspect ${id}`); + // } catch (error) { + // await asyncExecShell(`DOCKER_HOST=${host} docker volume create ${id}`); + // } + // } + const composeVolumes = volumes.map((volume) => { + return { + [`${volume.split(':')[0]}`]: { + name: volume.split(':')[0] + } + }; + }); + const compose = { + version: '3.8', + services: { + [imageId]: { + image: `${applicationId}:${tag}`, + container_name: imageId, + volumes, + env_file: envFound ? [`${workdir}/.env`] : [], + networks: [docker.network], + labels: labels, + depends_on: [], + restart: 'always' + } + }, + networks: { + [docker.network]: { + external: true + } + }, + volumes: Object.assign({}, ...composeVolumes) + }; + await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(compose)); + await asyncExecShell( + `DOCKER_HOST=${host} docker compose --project-directory ${workdir} up -d` ); - if (stderr) console.log(stderr); + + // const { stderr } = await asyncExecShell( + // `DOCKER_HOST=${host} docker run ${envFound && `--env-file=${workdir}/.env`} ${labels.join( + // ' ' + // )} --name ${imageId} --network ${docker.network} --restart always ${volumes.length > 0 ? volumes : '' + // } -d ${applicationId}:${tag}` + // ); saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); } catch (error) { saveBuildLog({ line: error, buildId, applicationId }); diff --git a/src/routes/applications/[id]/index.json.ts b/src/routes/applications/[id]/index.json.ts index 47fc9e2ae..3b4405706 100644 --- a/src/routes/applications/[id]/index.json.ts +++ b/src/routes/applications/[id]/index.json.ts @@ -52,8 +52,7 @@ export const post: RequestHandler = async (event) => { buildCommand, startCommand, baseDirectory, - publishDirectory, - phpModules + publishDirectory } = await event.request.json(); if (port) port = Number(port); @@ -69,8 +68,7 @@ export const post: RequestHandler = async (event) => { buildCommand, startCommand, baseDirectory, - publishDirectory, - phpModules + publishDirectory }); return { status: 201 }; } catch (error) { diff --git a/src/routes/applications/[id]/index.svelte b/src/routes/applications/[id]/index.svelte index bcadb5f5b..49f800975 100644 --- a/src/routes/applications/[id]/index.svelte +++ b/src/routes/applications/[id]/index.svelte @@ -47,125 +47,7 @@ import { post } from '$lib/api'; import cuid from 'cuid'; import { browser } from '$app/env'; - import Select from 'svelte-select'; const { id } = $page.params; - let collection = [ - 'amqp', - 'apcu', - 'apcu_bc', - 'ast', - 'bcmath', - 'blackfire', - 'bz2', - 'calendar', - 'cmark', - 'csv', - 'dba', - 'decimal', - 'ds', - 'enchant', - 'ev', - 'event', - 'excimer', - 'exif', - 'ffi', - 'gd', - 'gearman', - 'geoip', - 'geospatial', - 'gettext', - 'gmagick', - 'gmp', - 'gnupg', - 'grpc', - 'http', - 'igbinary', - 'imagick', - 'imap', - 'inotify', - 'interbase', - 'intl', - 'ioncube_loader', - 'jsmin', - 'json_post', - 'ldap', - 'lzf', - 'mailparse', - 'maxminddb', - 'mcrypt', - 'memcache', - 'memcached', - 'mongo', - 'mongodb', - 'mosquitto', - 'msgpack', - 'mssql', - 'mysqli', - 'oauth', - 'oci8', - 'odbc', - 'opcache', - 'opencensus', - 'openswoole', - 'parallel', - 'pcntl', - 'pcov', - 'pdo_dblib', - 'pdo_firebird', - 'pdo_mysql', - 'pdo_oci', - 'pdo_odbc', - 'pdo_pgsql', - 'pdo_sqlsrv', - 'pgsql', - 'propro', - 'protobuf', - 'pspell', - 'pthreads', - 'raphf', - 'rdkafka', - 'recode', - 'redis', - 'seaslog', - 'shmop', - 'smbclient', - 'snmp', - 'snuffleupagus', - 'soap', - 'sockets', - 'solr', - 'sourceguardian', - 'spx', - 'sqlsrv', - 'ssh2', - 'stomp', - 'swoole', - 'sybase_ct', - 'sysvmsg', - 'sysvsem', - 'sysvshm', - 'tensor', - 'tidy', - 'timezonedb', - 'uopz', - 'uploadprogress', - 'uuid', - 'vips', - 'wddx', - 'xdebug', - 'xhprof', - 'xlswriter', - 'xmldiff', - 'xmlrpc', - 'xsl', - 'yac', - 'yaml', - 'yar', - 'zephir_parser', - 'zip', - 'zookeeper', - 'zstd' - ]; let domainEl: HTMLInputElement; @@ -225,9 +107,8 @@ async function handleSubmit() { loading = true; try { - const tempPhpModules = application.phpModules?.map((module) => module.value).toString() || ''; await post(`/applications/${id}/check.json`, { fqdn: application.fqdn, forceSave }); - await post(`/applications/${id}.json`, { ...application, phpModules: tempPhpModules }); + await post(`/applications/${id}.json`, { ...application }); return window.location.reload(); } catch ({ error }) { if (error.startsWith('DNS not set')) { @@ -481,19 +362,6 @@ /> {/if} -