diff --git a/api/libs/applications/configuration.js b/api/libs/applications/configuration.js index 68d171df6..5ed8e73f3 100644 --- a/api/libs/applications/configuration.js +++ b/api/libs/applications/configuration.js @@ -50,15 +50,11 @@ function setDefaultConfiguration (configuration) { configuration.publish.port = 3000 } } - - if (configuration.build.pack === 'static') { - if (!configuration.build.command.installation) configuration.build.command.installation = 'yarn install' - if (!configuration.build.directory) configuration.build.directory = '/' + if (!configuration.build.directory) { + configuration.build.directory = '/' } - - if (configuration.build.pack === 'nodejs') { + if (configuration.build.pack === 'static' || configuration.build.pack === 'nodejs') { if (!configuration.build.command.installation) configuration.build.command.installation = 'yarn install' - if (!configuration.build.directory) configuration.build.directory = '/' } configuration.build.container.baseSHA = crypto.createHash('sha256').update(JSON.stringify(baseServiceConfiguration)).digest('hex') diff --git a/api/libs/applications/deploy/deploy.js b/api/libs/applications/deploy/deploy.js index 65fa7b685..1f9619a06 100644 --- a/api/libs/applications/deploy/deploy.js +++ b/api/libs/applications/deploy/deploy.js @@ -60,7 +60,6 @@ module.exports = async function (configuration, configChanged, imageChanged) { } } } - console.log(stack) await saveAppLog('### Publishing.', configuration) await fs.writeFile(`${configuration.general.workdir}/stack.yml`, yaml.dump(stack)) // TODO: Compare stack.yml with the currently running one to upgrade if something changes, like restart_policy diff --git a/api/packs/custom/index.js b/api/packs/custom/index.js new file mode 100644 index 000000000..7c6f60065 --- /dev/null +++ b/api/packs/custom/index.js @@ -0,0 +1,15 @@ +const fs = require('fs').promises +const { streamEvents, docker } = require('../../libs/docker') + +module.exports = async function (configuration) { + const path = `${configuration.general.workdir}/${configuration.build.directory ? configuration.build.directory : ''}` + if (fs.stat(`${path}/Dockerfile`)) { + const stream = await docker.engine.buildImage( + { src: ['.'], context: path }, + { t: `${configuration.build.container.name}:${configuration.build.container.tag}` } + ) + await streamEvents(stream, configuration) + } else { + throw { error: 'No custom dockerfile found.', type: 'app' } + } +} diff --git a/api/packs/helpers.js b/api/packs/helpers.js index 37ed07078..b46ed6478 100644 --- a/api/packs/helpers.js +++ b/api/packs/helpers.js @@ -1,21 +1,16 @@ const fs = require('fs').promises const { streamEvents, docker } = require('../libs/docker') - +const buildImageNodeDocker = (configuration) => { + return [ + 'FROM node:lts', + 'WORKDIR /usr/src/app', + `COPY ${configuration.build.directory} ./`, + configuration.build.command.installation && `RUN ${configuration.build.command.installation}`, + `RUN ${configuration.build.command.build}` + ].join('\n') +} async function buildImage (configuration) { - let dockerFile = ` - # build - FROM node:lts - WORKDIR /usr/src/app - COPY package*.json . - ` - if (configuration.build.command.installation) { - dockerFile += `RUN ${configuration.build.command.installation} - ` - } - dockerFile += `COPY . . - RUN ${configuration.build.command.build}` - - await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, dockerFile) + await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, buildImageNodeDocker(configuration)) const stream = await docker.engine.buildImage( { src: ['.'], context: configuration.general.workdir }, { t: `${configuration.build.container.name}:${configuration.build.container.tag}` } diff --git a/api/packs/index.js b/api/packs/index.js index 5f180272b..23fb82e34 100644 --- a/api/packs/index.js +++ b/api/packs/index.js @@ -1,5 +1,6 @@ const static = require('./static') const nodejs = require('./nodejs') const php = require('./php') +const custom = require('./custom') -module.exports = { static, nodejs, php } +module.exports = { static, nodejs, php, custom } diff --git a/api/packs/nodejs/index.js b/api/packs/nodejs/index.js index 6e2ff2535..97a24e971 100644 --- a/api/packs/nodejs/index.js +++ b/api/packs/nodejs/index.js @@ -2,32 +2,22 @@ const fs = require('fs').promises const { buildImage } = require('../helpers') const { streamEvents, docker } = require('../../libs/docker') +const publishNodejsDocker = (configuration) => { + return [ + 'FROM node:lts', + 'WORKDIR /usr/src/app', + configuration.build.command.build + ? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./` + : `COPY ${configuration.build.directory} ./`, + configuration.build.command.installation && `RUN ${configuration.build.command.installation}`, + `EXPOSE ${configuration.publish.port}`, + 'CMD [ "yarn", "start" ]' + ].join('\n') +} + module.exports = async function (configuration) { if (configuration.build.command.build) await buildImage(configuration) - - let dockerFile = `# production stage - FROM node:lts - WORKDIR /usr/src/app - ` - if (configuration.build.command.build) { - dockerFile += `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} /usr/src/app` - } else { - if (configuration.publish.directory) { - dockerFile += `COPY .${configuration.publish.directory} ./` - } else { - dockerFile += 'COPY ./' - } - } - if (configuration.build.command.installation) { - dockerFile += ` - RUN ${configuration.build.command.installation} - ` - } - dockerFile += ` - EXPOSE ${configuration.publish.port} - CMD [ "yarn", "start" ]` - - await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, dockerFile) + await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishNodejsDocker(configuration)) const stream = await docker.engine.buildImage( { src: ['.'], context: configuration.general.workdir }, { t: `${configuration.build.container.name}:${configuration.build.container.tag}` } diff --git a/api/packs/php/index.js b/api/packs/php/index.js index 1d02c5b08..0361b89f7 100644 --- a/api/packs/php/index.js +++ b/api/packs/php/index.js @@ -1,21 +1,18 @@ const fs = require('fs').promises const { streamEvents, docker } = require('../../libs/docker') +const publishPHPDocker = (configuration) => { + return [ + 'FROM php:apache', + 'WORKDIR /usr/src/app', + `COPY .${configuration.build.directory} /var/www/html`, + 'EXPOSE 80', + ' CMD ["apache2-foreground"]' + ].join('\n') +} + module.exports = async function (configuration) { - let dockerFile = `# production stage - FROM php:apache - ` - if (configuration.publish.directory) { - dockerFile += `COPY ${configuration.publish.directory} /var/www/html` - } else { - dockerFile += 'COPY . /var/www/html' - } - - dockerFile += ` - EXPOSE 80 - CMD ["apache2-foreground"]` - await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, dockerFile) - + await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishPHPDocker(configuration)) const stream = await docker.engine.buildImage( { src: ['.'], context: configuration.general.workdir }, { t: `${configuration.build.container.name}:${configuration.build.container.tag}` } diff --git a/api/packs/static/index.js b/api/packs/static/index.js index b5fd28bc6..a2dc497a6 100644 --- a/api/packs/static/index.js +++ b/api/packs/static/index.js @@ -2,27 +2,22 @@ const fs = require('fs').promises const { buildImage } = require('../helpers') const { streamEvents, docker } = require('../../libs/docker') +const publishStaticDocker = (configuration) => { + return [ + 'FROM nginx:stable-alpine', + 'COPY nginx.conf /etc/nginx/nginx.conf', + 'WORKDIR /usr/share/nginx/html', + configuration.build.command.build + ? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./` + : `COPY ${configuration.build.directory} ./`, + 'EXPOSE 80', + 'CMD ["nginx", "-g", "daemon off;"]' + ].join('\n') +} + module.exports = async function (configuration) { if (configuration.build.command.build) await buildImage(configuration) - - let dockerFile = `# production stage - FROM nginx:stable-alpine - COPY nginx.conf /etc/nginx/nginx.conf - ` - if (configuration.build.command.build) { - dockerFile += `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} /usr/share/nginx/html` - } else { - if (configuration.publish.directory) { - dockerFile += `COPY .${configuration.publish.directory} /usr/share/nginx/html` - } else { - dockerFile += 'COPY . /usr/share/nginx/html' - } - } - - dockerFile += ` - EXPOSE 80 - CMD ["nginx", "-g", "daemon off;"]` - await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, dockerFile) + await fs.writeFile(`${configuration.general.workdir}/Dockerfile`, publishStaticDocker(configuration)) const stream = await docker.engine.buildImage( { src: ['.'], context: configuration.general.workdir }, diff --git a/index.html b/index.html index ee903fc5c..3b3cf82f2 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ + diff --git a/package.json b/package.json index 298775de9..2f67456c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.", - "version": "1.0.3", + "version": "1.0.4", "license": "AGPL-3.0", "scripts": { "lint": "standard", @@ -36,6 +36,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^5.11.4", "shelljs": "^0.8.4", + "svelte-select": "^3.17.0", "unique-names-generator": "^4.4.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1565216b..6b6b4595f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,7 @@ dependencies: jsonwebtoken: 8.5.1 mongoose: 5.12.2 shelljs: 0.8.4 + svelte-select: 3.17.0 unique-names-generator: 4.4.0 devDependencies: mongodb-memory-server-core: 6.9.6 @@ -6042,6 +6043,10 @@ packages: requiresBuild: true resolution: integrity: sha512-SROWH0rB0DJ+0Ii264cprmNu/NJyZacs5wFD71ya93Cg/oA2lKHgQm4F6j0EWA4ktFMzeuJJm/eX6fka39hEHA== + /svelte-select/3.17.0: + dev: false + resolution: + integrity: sha512-ITmX/XUiSdkaILmsTviKRkZPaXckM5/FA7Y8BhiUPoamaZG/ZDyOo6ydjFu9fDVFTbwoAUGUi6HBjs+ZdK2AwA== /svelte/3.35.0: dev: true engines: @@ -6783,6 +6788,7 @@ specifiers: svelte: ^3.29.7 svelte-hmr: ^0.12.2 svelte-preprocess: ^4.6.1 + svelte-select: ^3.17.0 svite: 0.8.1 tailwindcss: compat unique-names-generator: ^4.4.0 diff --git a/src/App.svelte b/src/App.svelte index f3d16a5b8..f2d9444de 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -3,8 +3,8 @@ import { Router } from "@roxi/routify"; import { routes } from "../.routify/routes"; const options = { - duration: 2000, - dismissable: false + duration: 5000, + dismissable: true }; diff --git a/src/components/Application/Configuration/ActiveTab/BuildStep.svelte b/src/components/Application/Configuration/ActiveTab/BuildStep.svelte index 0bda88e6e..a1cc90034 100644 --- a/src/components/Application/Configuration/ActiveTab/BuildStep.svelte +++ b/src/components/Application/Configuration/ActiveTab/BuildStep.svelte @@ -1,29 +1,24 @@
- - + - - - +
diff --git a/src/components/Application/Configuration/ActiveTab/General.svelte b/src/components/Application/Configuration/ActiveTab/General.svelte index 83574968b..e26c38bad 100644 --- a/src/components/Application/Configuration/ActiveTab/General.svelte +++ b/src/components/Application/Configuration/ActiveTab/General.svelte @@ -1,16 +1,40 @@
- +
- +
- + {#if $application.build.pack === "nodejs" || $application.build.pack === "custom"} + - {#if $application.build.pack === "nodejs"} - - - {/if} + {/if} +
+
+ + +
+
+ + +
+
- \ No newline at end of file + diff --git a/src/components/Application/Configuration/Configuration.svelte b/src/components/Application/Configuration/Configuration.svelte index aeca0ad6a..ca122de84 100644 --- a/src/components/Application/Configuration/Configuration.svelte +++ b/src/components/Application/Configuration/Configuration.svelte @@ -147,13 +147,13 @@ {:else} {#await loadGithub()} - + {:then} {#if loading.github} - + {:else}
+ :global(.repository-select-search .listItem .item), + :global(.repository-select-search .empty) { + @apply text-sm py-3 font-bold bg-warmGray-800 text-white cursor-pointer border-none hover:bg-warmGray-700 !important; + } + + :global(.repository-select-search .listContainer) { + @apply bg-transparent !important; + } + + :global(.repository-select-search .clearSelect) { + @apply text-white cursor-pointer !important; + } + + :global(.repository-select-search .selectedItem) { + @apply text-white relative cursor-pointer font-bold text-sm flex items-center !important; + } + +
{#if repositories.length !== 0} -
- - - +
+