diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a21ec10a..dabb5e10a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ # Welcome -First of all, thank you for considering to contribute to my project! It means a lot 💜. +First of all, thank you for considering contributing to my project! It means a lot 💜. # Technical skills required - Node.js / Javascript - Svelte / SvelteKit -- Prisma.io +- Prisma.io / SQL # Recommended Pull Request Guideline @@ -16,11 +16,13 @@ First of all, thank you for considering to contribute to my project! It means a - Push to your fork repo - Create a pull request: https://github.com/coollabsio/compare - Write a proper description -- Open the pull request to review +- Open the pull request to review against `next` branch + +--- # How to start after you set up your local fork? -This repository best with [pnpm](https://pnpm.io) due to the lock file. I recommend you should try and use `pnpm` as well, because it is cool and efficient! +Due to the lock file, this repository is best with [pnpm](https://pnpm.io). I recommend you try and use `pnpm` because it is cool and efficient! You need to have [Docker Engine](https://docs.docker.com/engine/install/) installed locally. @@ -41,4 +43,75 @@ If the schema is finalized, you need to create a migration file with `pnpm db:mi ## Tricky parts -- BullMQ, the queue system Coolify is using, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking of a different queue/scheduler library. I'm open for discussion! +- BullMQ, the queue system Coolify uses, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking for a different queue/scheduler library. I'm open to discussion! + +--- + +# How to add new services + +You can add any open-source and self-hostable software (service/application) to Coolify if the following statements are true: + +- Self-hostable (obviously) +- Open-source +- Maintained (I do not want to add software full of bugs) + +## Backend + +I use MinIO as an example. + +You need to add a new folder to [src/routes/services/[id]](src/routes/services/[id]) with the low-capital name of the service. It should have three files with the following properties: + +1. `index.json.ts`: A POST endpoint that updates Coolify's database about the service. + + Basic services only require updating the URL(fqdn) and the name of the service. + +2. `start.json.ts`: A start endpoint that setups the docker-compose file (for Local Docker Engines) and starts the service. + + - To start a service, you need to know Coolify supported images and tags of the service. For that you need to update `supportedServiceTypesAndVersions` function at [src/lib/components/common.ts](src/lib/components/common.ts). + + Example JSON: + + ```js + { + // Name used to identify the service in Coolify + name: 'minio', + // Fancier name to show to the user + fancyName: 'MinIO', + // Docker base image for the service + baseImage: 'minio/minio', + // Usable tags + versions: ['latest'], + // Which tag is the recommended + recommendedVersion: 'latest', + // Application's default port, MinIO listens on 9001 (and 9000, more details later on) + ports: { + main: 9001 + } + }, + ``` + + - You need to define a compose file as `const composeFile: ComposeFile` found in [src/routes/services/[id]/minio/start.json.ts](src/routes/services/[id]/minio/start.json.ts) + + **IMPORTANT:** It should contain `all the default environment variables` that are required for the service to function correctly and `all the volumes to persist data` in restarts. + + - You could also define an `HTTP` or `TCP` proxy for every other port that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions in [src/lib/haproxy/index.ts](src/lib/haproxy/index.ts)) + +3. `stop.json.ts` A stop endpoint that stops the service. + + It needs to stop all the services by their container name and proxies (if applicable). + +4. You need to add the automatically generated variables (passwords, users, etc.) for the new service at [src/lib/database/services.ts](src/lib/database/services.ts), `configureServiceType` function. + +## Frontend + +1. You need to add a custom logo at [src/lib/components/svg/services/](src/lib/components/svg/services/) as a svelte component. + + SVG is recommended, but you can use PNG as well. It should have the `isAbsolute` variable with the suitable CSS classes, primarily for sizing and positioning. + +2. You need to include it the logo at [src/routes/services/index.svelte](src/routes/services/index.svelte) with `isAbsolute` and [src/lib/components/ServiceLinks.svelte](src/lib/components/ServiceLinks.svelte) with a link to the docs/main site of the service. + +3. By default the URL and the name frontend forms are included in [src/routes/services/[id]/\_Services/\_Services.svelte](src/routes/services/[id]/_Services/_Services.svelte). + + If you need to show more details on the frontend, such as users/passwords, you need to add Svelte component to [src/routes/services/[id]/\_Services](src/routes/services/[id]/_Services) with an underscore. For example, see other files in that folder. + + You also need to add the new inputs to the `index.json.ts` file of the specific service, like for MinIO here: [src/routes/services/[id]/minio/index.json.ts](src/routes/services/[id]/minio/index.json.ts) diff --git a/README.md b/README.md index 2cb2d5bf6..d214d42b7 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you would like no questions during installation ### Git Sources -You can use the following Git Sources to be auto-deployed to your Coolifyt instance! (Self hosted versions also supported.) +You can use the following Git Sources to be auto-deployed to your Coolifyt instance! (Self-hosted versions are also supported.) - Github - GitLab @@ -38,7 +38,7 @@ You can deploy your applications to the following destinations: ### Applications -These are the predefined build packs, but with the Docker build pack, you can host basically anything that is hostable with a single Dockerfile. +These are the predefined build packs, but with the Docker build pack, you can host anything that is hostable with a single Dockerfile. - Static sites - NodeJS diff --git a/data/build-prisma-engine.sh b/data/build-prisma-engine.sh deleted file mode 100644 index 42c2af608..000000000 --- a/data/build-prisma-engine.sh +++ /dev/null @@ -1 +0,0 @@ -nohup docker build -t coollabsio/prisma-engine: --push . & \ No newline at end of file diff --git a/data/prisma/build-prisma-engine.sh b/data/prisma/build-prisma-engine.sh new file mode 100644 index 000000000..4c0757d39 --- /dev/null +++ b/data/prisma/build-prisma-engine.sh @@ -0,0 +1 @@ +docker build --platform linux/amd64,linux/arm64 -t coollabsio/prisma-engine -f prisma-engine.Dockerfile --push . \ No newline at end of file diff --git a/data/prisma-engine.Dockerfile b/data/prisma/prisma-engine.Dockerfile similarity index 87% rename from data/prisma-engine.Dockerfile rename to data/prisma/prisma-engine.Dockerfile index 086472e23..76d1204fb 100644 --- a/data/prisma-engine.Dockerfile +++ b/data/prisma/prisma-engine.Dockerfile @@ -2,7 +2,7 @@ FROM rust:1.58.1-alpine3.14 as prisma WORKDIR /prisma ENV RUSTFLAGS="-C target-feature=-crt-static" RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc -RUN git clone --depth=1 --branch=3.11.x https://github.com/prisma/prisma-engines.git /prisma +RUN git clone --depth=1 --branch=3.12.x https://github.com/prisma/prisma-engines.git /prisma RUN cargo build --release FROM alpine diff --git a/package.json b/package.json index bb3348d88..592bef339 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "2.4.11", + "version": "2.5.0", "license": "AGPL-3.0", "scripts": { "dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev --host 0.0.0.0", @@ -19,8 +19,10 @@ "db:migrate": "COOLIFY_DATABASE_URL=file:../db/migration.db prisma migrate dev --skip-seed --name", "release:production:all": "cross-var docker build --platform linux/amd64,linux/arm64 -t coollabsio/coolify:$npm_package_version -t coollabsio/coolify:latest --push .", "release:production:amd": "cross-var docker build --platform linux/amd64 -t coollabsio/coolify:$npm_package_version -t coollabsio/coolify:latest --push .", + "release:production:arm": "cross-var docker build --platform linux/arm64 -t coollabsio/coolify:$npm_package_version -t coollabsio/coolify:latest --push .", "release:staging:all": "cross-var docker build --platform linux/amd64,linux/arm64 -t coollabsio/coolify:$npm_package_version --push .", "release:staging:amd": "cross-var docker build --platform linux/amd64 -t coollabsio/coolify:$npm_package_version --push .", + "release:staging:arm": "cross-var docker build --platform linux/arm64 -t coollabsio/coolify:$npm_package_version --push .", "release:haproxy": "docker build --platform linux/amd64,linux/arm64 -t coollabsio/coolify-haproxy-alpine:latest -t coollabsio/coolify-haproxy-alpine:1.1.0 -f data/haproxy.Dockerfile --push .", "release:haproxy:tcp": "docker build --platform linux/amd64,linux/arm64 -t coollabsio/coolify-haproxy-tcp-alpine:latest -t coollabsio/coolify-haproxy-tcp-alpine:1.1.0 -f data/haproxy-tcp.Dockerfile --push .", "release:haproxy:http": "docker build --platform linux/amd64,linux/arm64 -t coollabsio/coolify-haproxy-http-alpine:latest -t coollabsio/coolify-haproxy-http-alpine:1.1.0 -f data/haproxy-http.Dockerfile --push .", @@ -28,10 +30,10 @@ }, "devDependencies": { "@sveltejs/adapter-node": "1.0.0-next.73", - "@sveltejs/kit": "1.0.0-next.310", + "@sveltejs/kit": "1.0.0-next.316", "@types/js-cookie": "3.0.1", "@types/js-yaml": "4.0.5", - "@types/node": "17.0.23", + "@types/node": "17.0.25", "@types/node-forge": "1.0.1", "@typescript-eslint/eslint-plugin": "4.31.1", "@typescript-eslint/parser": "4.31.1", @@ -43,17 +45,17 @@ "eslint-config-prettier": "8.5.0", "eslint-plugin-svelte3": "3.4.1", "husky": "7.0.4", - "lint-staged": "12.3.7", + "lint-staged": "12.4.0", "postcss": "8.4.12", "prettier": "2.6.2", "prettier-plugin-svelte": "2.7.0", - "prettier-plugin-tailwindcss": "0.1.8", + "prettier-plugin-tailwindcss": "0.1.10", "prisma": "3.11.1", "svelte": "3.47.0", - "svelte-check": "2.6.0", - "svelte-preprocess": "4.10.5", + "svelte-check": "2.7.0", + "svelte-preprocess": "4.10.6", "svelte-select": "4.4.7", - "tailwindcss": "3.0.23", + "tailwindcss": "3.0.24", "ts-node": "10.7.0", "tslib": "2.3.1", "typescript": "4.6.3" @@ -64,11 +66,11 @@ "@prisma/client": "3.11.1", "@sentry/node": "6.19.6", "bcryptjs": "2.4.3", - "bullmq": "1.80.0", + "bullmq": "1.80.4", "compare-versions": "4.1.3", - "cookie": "0.4.2", + "cookie": "0.5.0", "cuid": "2.1.8", - "dayjs": "1.11.0", + "dayjs": "1.11.1", "dockerode": "3.3.1", "dotenv-extended": "2.9.0", "generate-password": "1.7.0", @@ -80,7 +82,7 @@ "mustache": "4.2.0", "node-forge": "1.3.1", "p-limit": "4.0.0", - "svelte-kit-cookie-session": "2.1.2", + "svelte-kit-cookie-session": "2.1.3", "tailwindcss-scrollbar": "0.1.0", "unique-names-generator": "4.7.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 99b37c004..5ac48a0a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,23 +5,23 @@ specifiers: '@prisma/client': 3.11.1 '@sentry/node': 6.19.6 '@sveltejs/adapter-node': 1.0.0-next.73 - '@sveltejs/kit': 1.0.0-next.310 + '@sveltejs/kit': 1.0.0-next.316 '@types/js-cookie': 3.0.1 '@types/js-yaml': 4.0.5 - '@types/node': 17.0.23 + '@types/node': 17.0.25 '@types/node-forge': 1.0.1 '@typescript-eslint/eslint-plugin': 4.31.1 '@typescript-eslint/parser': 4.31.1 '@zerodevx/svelte-toast': 0.7.1 autoprefixer: 10.4.4 bcryptjs: 2.4.3 - bullmq: 1.80.0 + bullmq: 1.80.4 compare-versions: 4.1.3 - cookie: 0.4.2 + cookie: 0.5.0 cross-env: 7.0.3 cross-var: 1.1.0 cuid: 2.1.8 - dayjs: 1.11.0 + dayjs: 1.11.1 dockerode: 3.3.1 dotenv-extended: 2.9.0 eslint: 7.32.0 @@ -34,21 +34,21 @@ specifiers: js-cookie: 3.0.1 js-yaml: 4.1.0 jsonwebtoken: 8.5.1 - lint-staged: 12.3.7 + lint-staged: 12.4.0 mustache: 4.2.0 node-forge: 1.3.1 p-limit: 4.0.0 postcss: 8.4.12 prettier: 2.6.2 prettier-plugin-svelte: 2.7.0 - prettier-plugin-tailwindcss: 0.1.8 + prettier-plugin-tailwindcss: 0.1.10 prisma: 3.11.1 svelte: 3.47.0 - svelte-check: 2.6.0 - svelte-kit-cookie-session: 2.1.2 - svelte-preprocess: 4.10.5 + svelte-check: 2.7.0 + svelte-kit-cookie-session: 2.1.3 + svelte-preprocess: 4.10.6 svelte-select: 4.4.7 - tailwindcss: 3.0.23 + tailwindcss: 3.0.24 tailwindcss-scrollbar: 0.1.0 ts-node: 10.7.0 tslib: 2.3.1 @@ -60,11 +60,11 @@ dependencies: '@prisma/client': 3.11.1_prisma@3.11.1 '@sentry/node': 6.19.6 bcryptjs: 2.4.3 - bullmq: 1.80.0 + bullmq: 1.80.4 compare-versions: 4.1.3 - cookie: 0.4.2 + cookie: 0.5.0 cuid: 2.1.8 - dayjs: 1.11.0 + dayjs: 1.11.1 dockerode: 3.3.1 dotenv-extended: 2.9.0 generate-password: 1.7.0 @@ -76,16 +76,16 @@ dependencies: mustache: 4.2.0 node-forge: 1.3.1 p-limit: 4.0.0 - svelte-kit-cookie-session: 2.1.2 - tailwindcss-scrollbar: 0.1.0_tailwindcss@3.0.23 + svelte-kit-cookie-session: 2.1.3 + tailwindcss-scrollbar: 0.1.0_tailwindcss@3.0.24 unique-names-generator: 4.7.1 devDependencies: '@sveltejs/adapter-node': 1.0.0-next.73 - '@sveltejs/kit': 1.0.0-next.310_svelte@3.47.0 + '@sveltejs/kit': 1.0.0-next.316_svelte@3.47.0 '@types/js-cookie': 3.0.1 '@types/js-yaml': 4.0.5 - '@types/node': 17.0.23 + '@types/node': 17.0.25 '@types/node-forge': 1.0.1 '@typescript-eslint/eslint-plugin': 4.31.1_8ede7edd7694646e12d33c52460f622c '@typescript-eslint/parser': 4.31.1_eslint@7.32.0+typescript@4.6.3 @@ -97,18 +97,18 @@ devDependencies: eslint-config-prettier: 8.5.0_eslint@7.32.0 eslint-plugin-svelte3: 3.4.1_eslint@7.32.0+svelte@3.47.0 husky: 7.0.4 - lint-staged: 12.3.7 + lint-staged: 12.4.0 postcss: 8.4.12 prettier: 2.6.2 prettier-plugin-svelte: 2.7.0_prettier@2.6.2+svelte@3.47.0 - prettier-plugin-tailwindcss: 0.1.8_prettier@2.6.2 + prettier-plugin-tailwindcss: 0.1.10_prettier@2.6.2 prisma: 3.11.1 svelte: 3.47.0 - svelte-check: 2.6.0_postcss@8.4.12+svelte@3.47.0 - svelte-preprocess: 4.10.5_41810887ae6c6d59323116f47e33fa38 + svelte-check: 2.7.0_postcss@8.4.12+svelte@3.47.0 + svelte-preprocess: 4.10.6_41810887ae6c6d59323116f47e33fa38 svelte-select: 4.4.7 - tailwindcss: 3.0.23_b89136460714832cdda11d1e9d57d1ff - ts-node: 10.7.0_ee885bc7281b682b6adbed6ae09ee090 + tailwindcss: 3.0.24_ts-node@10.7.0 + ts-node: 10.7.0_de7c86b0cde507c63a0402da5b982bd3 tslib: 2.3.1 typescript: 4.6.3 @@ -374,10 +374,10 @@ packages: tiny-glob: 0.2.9 dev: true - /@sveltejs/kit/1.0.0-next.310_svelte@3.47.0: + /@sveltejs/kit/1.0.0-next.316_svelte@3.47.0: resolution: { - integrity: sha512-pTyMyaoyHS+V5cQZIQMfQXmLkhw1VaRwT9avOSgwDc0QBpnNw2LdzwoPYsUr96ca5B6cfT3SMUNolxErTNHmPQ== + integrity: sha512-oLjWOWzjriJD2t210r7ALuH/8ZADrJGsOODzRCRSJvRBCt0Q7VKVLqwKbM/RlZzD1k8Af2uRodQT11kP98hAIA== } engines: { node: '>=14.13' } hasBin: true @@ -468,7 +468,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.3 - '@types/node': 17.0.23 + '@types/node': 17.0.25 '@types/responselike': 1.0.0 dev: false @@ -506,7 +506,7 @@ packages: integrity: sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg== } dependencies: - '@types/node': 17.0.23 + '@types/node': 17.0.25 dev: false /@types/node-forge/1.0.1: @@ -515,22 +515,15 @@ packages: integrity: sha512-96ELNKv9tQJ19afdBUiM5iDw7OYEc53iUc51gAPR2aGaqRsO1DBROjqgZRjZa1tkPj7TnEOR0EnyAX6iryGkzA== } dependencies: - '@types/node': 17.0.23 + '@types/node': 17.0.25 dev: true - /@types/node/17.0.23: + /@types/node/17.0.25: resolution: { - integrity: sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + integrity: sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w== } - /@types/parse-json/4.0.0: - resolution: - { - integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - } - dev: true - /@types/pug/2.0.5: resolution: { @@ -544,7 +537,7 @@ packages: integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== } dependencies: - '@types/node': 17.0.23 + '@types/node': 17.0.25 dev: false /@types/sass/1.16.1: @@ -553,7 +546,7 @@ packages: integrity: sha512-iZUcRrGuz/Tbg3loODpW7vrQJkUtpY2fFSf4ELqqkApcS2TkZ1msk7ie8iZPB86lDOP8QOTTmuvWjc5S0R9OjQ== } dependencies: - '@types/node': 17.0.23 + '@types/node': 17.0.25 dev: true /@typescript-eslint/eslint-plugin/4.31.1_8ede7edd7694646e12d33c52460f622c: @@ -1669,16 +1662,16 @@ packages: ieee754: 1.2.1 dev: false - /bullmq/1.80.0: + /bullmq/1.80.4: resolution: { - integrity: sha512-oz7GZIg7gAGIIlLQ3KdpYSA5WSz5205pQHyGwOtQof9MmkOf+Kmo6sxqr+BiQrjhFOrB6JLSCqS3EGEbMA34MA== + integrity: sha512-j3PyjU16gqmb3Md9QjMInJdbMvxIlSJx7mojtoP06LV9MfhzW75DkDrpSuJlF0H+0+u6MViV4hhaGTxky5OJWw== } dependencies: cron-parser: 4.2.1 get-port: 5.1.1 glob: 7.2.0 - ioredis: 4.28.3 + ioredis: 4.28.5 lodash: 4.17.21 msgpackr: 1.4.7 semver: 6.3.0 @@ -1928,6 +1921,14 @@ packages: engines: { node: '>= 0.6' } dev: false + /cookie/0.5.0: + resolution: + { + integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + } + engines: { node: '>= 0.6' } + dev: false + /core-js/2.6.12: resolution: { @@ -1937,20 +1938,6 @@ packages: requiresBuild: true dev: true - /cosmiconfig/7.0.1: - resolution: - { - integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== - } - engines: { node: '>=10' } - dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: true - /cpu-features/0.0.2: resolution: { @@ -2037,10 +2024,10 @@ packages: } dev: false - /dayjs/1.11.0: + /dayjs/1.11.1: resolution: { - integrity: sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug== + integrity: sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA== } dev: false @@ -2296,15 +2283,6 @@ packages: ansi-colors: 4.1.1 dev: true - /error-ex/1.3.2: - resolution: - { - integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - } - dependencies: - is-arrayish: 0.2.1 - dev: true - /es6-promise/3.3.1: resolution: { integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM= } dev: true @@ -3216,16 +3194,6 @@ packages: engines: { node: '>= 4' } dev: true - /import-cwd/3.0.0: - resolution: - { - integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg== - } - engines: { node: '>=8' } - dependencies: - import-from: 3.0.0 - dev: true - /import-fresh/3.3.0: resolution: { @@ -3237,16 +3205,6 @@ packages: resolve-from: 4.0.0 dev: true - /import-from/3.0.0: - resolution: - { - integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== - } - engines: { node: '>=8' } - dependencies: - resolve-from: 5.0.0 - dev: true - /imurmurhash/0.1.4: resolution: { integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o= } engines: { node: '>=0.8.19' } @@ -3281,10 +3239,10 @@ packages: loose-envify: 1.4.0 dev: true - /ioredis/4.28.3: + /ioredis/4.28.5: resolution: { - integrity: sha512-9JOWVgBnuSxpIgfpjc1OeY1OLmA4t2KOWWURTDRXky+eWO0LZhI33pQNT9gYxANUXfh5p/zYephYni6GPRsksQ== + integrity: sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A== } engines: { node: '>=6' } dependencies: @@ -3303,10 +3261,6 @@ packages: - supports-color dev: false - /is-arrayish/0.2.1: - resolution: { integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= } - dev: true - /is-binary-path/2.1.0: resolution: { @@ -3441,13 +3395,6 @@ packages: } dev: false - /json-parse-even-better-errors/2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - } - dev: true - /json-schema-traverse/0.4.1: resolution: { @@ -3547,14 +3494,18 @@ packages: engines: { node: '>=10' } dev: true - /lines-and-columns/1.1.6: - resolution: { integrity: sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= } - dev: true - - /lint-staged/12.3.7: + /lilconfig/2.0.5: resolution: { - integrity: sha512-/S4D726e2GIsDVWIk1XGvheCaDm1SJRQp8efamZFWJxQMVEbOwSysp7xb49Oo73KYCdy97mIWinhlxcoNqIfIQ== + integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== + } + engines: { node: '>=10' } + dev: true + + /lint-staged/12.4.0: + resolution: + { + integrity: sha512-3X7MR0h9b7qf4iXf/1n7RlVAx+EzpAZXoCEMhVSpaBlgKDfH2ewf+QUm7BddFyq29v4dgPP+8+uYpWuSWx035A== } engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } hasBin: true @@ -3966,10 +3917,10 @@ packages: path-key: 3.1.1 dev: true - /object-hash/2.2.0: + /object-hash/3.0.0: resolution: { - integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== } engines: { node: '>= 6' } dev: true @@ -4067,19 +4018,6 @@ packages: callsites: 3.1.0 dev: true - /parse-json/5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - } - engines: { node: '>=8' } - dependencies: - '@babel/code-frame': 7.12.11 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.1.6 - dev: true - /path-is-absolute/1.0.1: resolution: { integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= } engines: { node: '>=0.10.0' } @@ -4143,21 +4081,24 @@ packages: postcss: 8.4.12 dev: true - /postcss-load-config/3.1.0_ts-node@10.7.0: + /postcss-load-config/3.1.4_postcss@8.4.12+ts-node@10.7.0: resolution: { - integrity: sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g== + integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== } engines: { node: '>= 10' } peerDependencies: + postcss: '>=8.0.9' ts-node: '>=9.0.0' peerDependenciesMeta: + postcss: + optional: true ts-node: optional: true dependencies: - import-cwd: 3.0.0 - lilconfig: 2.0.4 - ts-node: 10.7.0_ee885bc7281b682b6adbed6ae09ee090 + lilconfig: 2.0.5 + postcss: 8.4.12 + ts-node: 10.7.0_de7c86b0cde507c63a0402da5b982bd3 yaml: 1.10.2 dev: true @@ -4171,13 +4112,13 @@ packages: postcss: ^8.2.14 dependencies: postcss: 8.4.12 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.10 dev: true - /postcss-selector-parser/6.0.9: + /postcss-selector-parser/6.0.10: resolution: { - integrity: sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== } engines: { node: '>=4' } dependencies: @@ -4225,10 +4166,10 @@ packages: svelte: 3.47.0 dev: true - /prettier-plugin-tailwindcss/0.1.8_prettier@2.6.2: + /prettier-plugin-tailwindcss/0.1.10_prettier@2.6.2: resolution: { - integrity: sha512-hwarSBCswAXa+kqYtaAkFr3Vop9o04WOyZs0qo3NyvW8L7f1rif61wRyq0+ArmVThOuRBcJF5hjGXYk86cwemg== + integrity: sha512-ooDGNuXUjgCXfShliVYQ6+0iXqUFXn+zdNInPe0WZN9qINt9srbLGFGY5jeVL4MXtY20/4S8JaBcd8l6N6NfCQ== } engines: { node: '>=12.17.0' } peerDependencies: @@ -4437,14 +4378,6 @@ packages: engines: { node: '>=4' } dev: true - /resolve-from/5.0.0: - resolution: - { - integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - } - engines: { node: '>=8' } - dev: true - /resolve/1.22.0: resolution: { @@ -4903,10 +4836,10 @@ packages: engines: { node: '>= 0.4' } dev: true - /svelte-check/2.6.0_postcss@8.4.12+svelte@3.47.0: + /svelte-check/2.7.0_postcss@8.4.12+svelte@3.47.0: resolution: { - integrity: sha512-POL3IqLUuGqb9DdvuXQaSTNXYnw/odK4hqW86+2LwGcZTdbUPKBBln7pq74wXmcnRE+12bXMY1CvbcUNa2d5nw== + integrity: sha512-GrvG24j0+i8AOm0k0KyJ6Dqc+TAR2yzB7rtS4nljHStunVxCTr/1KYlv4EsOeoqtHLzeWMOd5D2O6nDdP/yw4A== } hasBin: true peerDependencies: @@ -4919,7 +4852,7 @@ packages: sade: 1.7.4 source-map: 0.7.3 svelte: 3.47.0 - svelte-preprocess: 4.10.5_41810887ae6c6d59323116f47e33fa38 + svelte-preprocess: 4.10.6_41810887ae6c6d59323116f47e33fa38 typescript: 4.6.3 transitivePeerDependencies: - '@babel/core' @@ -4945,17 +4878,17 @@ packages: svelte: 3.47.0 dev: true - /svelte-kit-cookie-session/2.1.2: + /svelte-kit-cookie-session/2.1.3: resolution: { - integrity: sha512-PfxIWDhiyYWu7iKlL0GHpmwDrdFh+rX/WmBzOuvctF25UqngIo9MCiegWBSBLE1RBwNs5UqaIeI8+vligmY07g== + integrity: sha512-7Xk3CNbpLAi1KodlsV5W5jULQ2NxQunaXtAYqAuzIEXIq2EwC4oDa25kdmHjNe33epV0t4r0WwxZOuSdJPsapg== } dev: false - /svelte-preprocess/4.10.5_41810887ae6c6d59323116f47e33fa38: + /svelte-preprocess/4.10.6_41810887ae6c6d59323116f47e33fa38: resolution: { - integrity: sha512-VKXPRScCzAZqeBZOGq4LLwtNrAu++mVn7XvQox3eFDV7Ciq0Lg70Q8QWjH9iXF7J+pMlXhPsSFwpCb2E+hoeyA== + integrity: sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ== } engines: { node: '>= 9.11.2' } requiresBuild: true @@ -5037,7 +4970,7 @@ packages: strip-ansi: 6.0.1 dev: true - /tailwindcss-scrollbar/0.1.0_tailwindcss@3.0.23: + /tailwindcss-scrollbar/0.1.0_tailwindcss@3.0.24: resolution: { integrity: sha512-egipxw4ooQDh94x02XQpPck0P0sfwazwoUGfA9SedPATIuYDR+6qe8d31Gl7YsSMRiOKDkkqfI0kBvEw9lT/Hg== @@ -5045,38 +4978,35 @@ packages: peerDependencies: tailwindcss: '>= 2.x.x' dependencies: - tailwindcss: 3.0.23_b89136460714832cdda11d1e9d57d1ff + tailwindcss: 3.0.24_ts-node@10.7.0 dev: false - /tailwindcss/3.0.23_b89136460714832cdda11d1e9d57d1ff: + /tailwindcss/3.0.24_ts-node@10.7.0: resolution: { - integrity: sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== + integrity: sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig== } engines: { node: '>=12.13.0' } hasBin: true - peerDependencies: - autoprefixer: ^10.0.2 dependencies: arg: 5.0.1 - autoprefixer: 10.4.4_postcss@8.4.12 - chalk: 4.1.2 chokidar: 3.5.3 color-name: 1.1.4 - cosmiconfig: 7.0.1 detective: 5.2.0 didyoumean: 1.2.2 dlv: 1.1.3 fast-glob: 3.2.11 glob-parent: 6.0.2 is-glob: 4.0.3 + lilconfig: 2.0.5 normalize-path: 3.0.0 - object-hash: 2.2.0 + object-hash: 3.0.0 + picocolors: 1.0.0 postcss: 8.4.12 postcss-js: 4.0.0_postcss@8.4.12 - postcss-load-config: 3.1.0_ts-node@10.7.0 + postcss-load-config: 3.1.4_postcss@8.4.12+ts-node@10.7.0 postcss-nested: 5.0.6_postcss@8.4.12 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.10 postcss-value-parser: 4.2.0 quick-lru: 5.1.1 resolve: 1.22.0 @@ -5148,7 +5078,7 @@ packages: engines: { node: '>=0.10.0' } dev: true - /ts-node/10.7.0_ee885bc7281b682b6adbed6ae09ee090: + /ts-node/10.7.0_de7c86b0cde507c63a0402da5b982bd3: resolution: { integrity: sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== @@ -5170,7 +5100,7 @@ packages: '@tsconfig/node12': 1.0.9 '@tsconfig/node14': 1.0.1 '@tsconfig/node16': 1.0.2 - '@types/node': 17.0.23 + '@types/node': 17.0.25 acorn: 8.5.0 acorn-walk: 8.2.0 arg: 4.1.3 diff --git a/prisma/migrations/20220420202031_deno_configurations/migration.sql b/prisma/migrations/20220420202031_deno_configurations/migration.sql new file mode 100644 index 000000000..9d0e832dc --- /dev/null +++ b/prisma/migrations/20220420202031_deno_configurations/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "Application" ADD COLUMN "denoMainFile" TEXT; +ALTER TABLE "Application" ADD COLUMN "denoOptions" TEXT; diff --git a/prisma/migrations/20220420210057_branch_for_builds/migration.sql b/prisma/migrations/20220420210057_branch_for_builds/migration.sql new file mode 100644 index 000000000..8cd8e653d --- /dev/null +++ b/prisma/migrations/20220420210057_branch_for_builds/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Build" ADD COLUMN "branch" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 668f4588a..abbfe24b2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -91,7 +91,9 @@ model Application { pythonWSGI String? pythonModule String? pythonVariable String? - dockerFileLocation String? + dockerFileLocation String? + denoMainFile String? + denoOptions String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt settings ApplicationSettings? @@ -181,6 +183,7 @@ model Build { githubAppId String? gitlabAppId String? commit String? + branch String? status String? @default("queued") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/src/lib/buildPacks/common.ts b/src/lib/buildPacks/common.ts index e6f62bd23..05313a3d2 100644 --- a/src/lib/buildPacks/common.ts +++ b/src/lib/buildPacks/common.ts @@ -92,7 +92,8 @@ export const setDefaultConfiguration = async (data) => { buildCommand, publishDirectory, baseDirectory, - dockerFileLocation + dockerFileLocation, + denoMainFile } = data; const template = scanningTemplates[buildPack]; if (!port) { @@ -103,9 +104,11 @@ export const setDefaultConfiguration = async (data) => { else if (buildPack === 'php') port = 80; else if (buildPack === 'python') port = 8000; } - if (!installCommand) installCommand = template?.installCommand || 'yarn install'; - if (!startCommand) startCommand = template?.startCommand || 'yarn start'; - if (!buildCommand) buildCommand = template?.buildCommand || null; + if (!installCommand && buildPack !== 'static') + installCommand = template?.installCommand || 'yarn install'; + if (!startCommand && buildPack !== 'static') + startCommand = template?.startCommand || 'yarn start'; + if (!buildCommand && buildPack !== 'static') buildCommand = template?.buildCommand || null; if (!publishDirectory) publishDirectory = template?.publishDirectory || null; if (baseDirectory) { if (!baseDirectory.startsWith('/')) baseDirectory = `/${baseDirectory}`; @@ -117,6 +120,9 @@ export const setDefaultConfiguration = async (data) => { } else { dockerFileLocation = '/Dockerfile'; } + if (!denoMainFile) { + denoMainFile = 'main.ts'; + } return { buildPack, @@ -126,7 +132,8 @@ export const setDefaultConfiguration = async (data) => { buildCommand, publishDirectory, baseDirectory, - dockerFileLocation + dockerFileLocation, + denoMainFile }; }; @@ -192,7 +199,11 @@ export async function copyBaseConfigurationFiles(buildPack, workdir, buildId, ap } ` ); - await saveBuildLog({ line: 'Copied default configuration file.', buildId, applicationId }); + await saveBuildLog({ + line: 'Copied default configuration file for Nginx.', + buildId, + applicationId + }); } } catch (error) { console.log(error); diff --git a/src/lib/buildPacks/deno.ts b/src/lib/buildPacks/deno.ts new file mode 100644 index 000000000..2e5569438 --- /dev/null +++ b/src/lib/buildPacks/deno.ts @@ -0,0 +1,54 @@ +import { buildImage } from '$lib/docker'; +import { promises as fs } from 'fs'; + +const createDockerfile = async (data, image): Promise => { + const { workdir, port, baseDirectory, secrets, pullmergeRequestId, denoMainFile, denoOptions } = + data; + const Dockerfile: Array = []; + + let depsFound = false; + try { + await fs.readFile(`${workdir}${baseDirectory || ''}/deps.ts`); + depsFound = true; + } catch (error) {} + + Dockerfile.push(`FROM ${image}`); + Dockerfile.push('WORKDIR /app'); + Dockerfile.push(`LABEL coolify.image=true`); + if (secrets.length > 0) { + secrets.forEach((secret) => { + if (secret.isBuildSecret) { + if (pullmergeRequestId) { + if (secret.isPRMRSecret) { + Dockerfile.push(`ARG ${secret.name}=${secret.value}`); + } + } else { + if (!secret.isPRMRSecret) { + Dockerfile.push(`ARG ${secret.name}=${secret.value}`); + } + } + } + }); + } + if (depsFound) { + Dockerfile.push(`COPY .${baseDirectory || ''}/deps.ts /app`); + Dockerfile.push(`RUN deno cache deps.ts`); + } + Dockerfile.push(`COPY ${denoMainFile} /app`); + Dockerfile.push(`RUN deno cache ${denoMainFile}`); + Dockerfile.push(`COPY .${baseDirectory || ''} ./`); + Dockerfile.push(`ENV NO_COLOR true`); + Dockerfile.push(`EXPOSE ${port}`); + Dockerfile.push(`CMD deno run ${denoOptions ? denoOptions.split(' ') : ''} ${denoMainFile}`); + await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n')); +}; + +export default async function (data) { + try { + const image = 'denoland/deno:latest'; + await createDockerfile(data, image); + await buildImage(data); + } catch (error) { + throw error; + } +} diff --git a/src/lib/buildPacks/index.ts b/src/lib/buildPacks/index.ts index babbe8f17..ac31afc16 100644 --- a/src/lib/buildPacks/index.ts +++ b/src/lib/buildPacks/index.ts @@ -13,6 +13,7 @@ import rust from './rust'; import astro from './static'; import eleventy from './static'; import python from './python'; +import deno from './deno'; export { node, @@ -29,5 +30,6 @@ export { rust, astro, eleventy, - python + python, + deno }; diff --git a/src/lib/components/common.ts b/src/lib/components/common.ts index 2bd962c4c..6bc60202d 100644 --- a/src/lib/components/common.ts +++ b/src/lib/components/common.ts @@ -19,7 +19,7 @@ export const staticDeployments = [ 'astro', 'eleventy' ]; -export const notNodeDeployments = ['php', 'docker', 'rust', 'python']; +export const notNodeDeployments = ['php', 'docker', 'rust', 'python', 'deno']; export function getDomain(domain) { return domain?.replace('https://', '').replace('http://', ''); diff --git a/src/lib/components/svg/applications/Deno.svelte b/src/lib/components/svg/applications/Deno.svelte new file mode 100644 index 000000000..4e1794226 --- /dev/null +++ b/src/lib/components/svg/applications/Deno.svelte @@ -0,0 +1,24 @@ + diff --git a/src/lib/components/templates.ts b/src/lib/components/templates.ts index b82b12f51..2336afb7d 100644 --- a/src/lib/components/templates.ts +++ b/src/lib/components/templates.ts @@ -153,6 +153,16 @@ export function findBuildPack(pack, packageManager = 'npm') { port: 8000 }; } + if (pack === 'deno') { + return { + ...metaData, + installCommand: null, + buildCommand: null, + startCommand: null, + publishDirectory: null, + port: 8000 + }; + } return { name: 'node', fancyName: 'Node.js', @@ -262,6 +272,12 @@ export const buildPacks = [ fancyName: 'Python', hoverColor: 'hover:bg-green-700', color: 'bg-green-700' + }, + { + name: 'deno', + fancyName: 'Deno', + hoverColor: 'hover:bg-green-700', + color: 'bg-green-700' } ]; export const scanningTemplates = { diff --git a/src/lib/database/applications.ts b/src/lib/database/applications.ts index 020b9ba75..d57e3f3e5 100644 --- a/src/lib/database/applications.ts +++ b/src/lib/database/applications.ts @@ -264,7 +264,9 @@ export async function configureApplication({ pythonWSGI, pythonModule, pythonVariable, - dockerFileLocation + dockerFileLocation, + denoMainFile, + denoOptions }: { id: string; buildPack: string; @@ -280,6 +282,8 @@ export async function configureApplication({ pythonModule: string; pythonVariable: string; dockerFileLocation: string; + denoMainFile: string; + denoOptions: string; }): Promise { return await prisma.application.update({ where: { id }, @@ -296,7 +300,9 @@ export async function configureApplication({ pythonWSGI, pythonModule, pythonVariable, - dockerFileLocation + dockerFileLocation, + denoMainFile, + denoOptions } }); } diff --git a/src/lib/docker.ts b/src/lib/docker.ts index c2642623f..d3c040c6a 100644 --- a/src/lib/docker.ts +++ b/src/lib/docker.ts @@ -109,6 +109,7 @@ export async function buildImage({ } ); await streamEvents({ stream, docker, buildId, applicationId, debug }); + await saveBuildLog({ line: `Building image successful!`, buildId, applicationId }); } export function dockerInstance({ destinationDocker }): { engine: Dockerode; network: string } { diff --git a/src/lib/haproxy/index.ts b/src/lib/haproxy/index.ts index 6770d5c93..5b713e343 100644 --- a/src/lib/haproxy/index.ts +++ b/src/lib/haproxy/index.ts @@ -126,8 +126,8 @@ export async function startTcpProxy( const host = getEngine(engine); const containerName = `haproxy-for-${publicPort}`; - const found = await checkContainer(engine, containerName); - const foundDependentContainer = await checkContainer(engine, id); + const found = await checkContainer(engine, containerName, true); + const foundDependentContainer = await checkContainer(engine, id, true); try { if (foundDependentContainer && !found) { @@ -161,8 +161,8 @@ export async function startHttpProxy( const host = getEngine(engine); const containerName = `haproxy-for-${publicPort}`; - const found = await checkContainer(engine, containerName); - const foundDependentContainer = await checkContainer(engine, id); + const found = await checkContainer(engine, containerName, true); + const foundDependentContainer = await checkContainer(engine, id, true); try { if (foundDependentContainer && !found) { @@ -186,7 +186,7 @@ export async function startHttpProxy( export async function startCoolifyProxy(engine: string): Promise { const host = getEngine(engine); - const found = await checkContainer(engine, 'coolify-haproxy'); + const found = await checkContainer(engine, 'coolify-haproxy', true); const { proxyPassword, proxyUser, id } = await db.listSettings(); if (!found) { const { stdout: Config } = await asyncExecShell( @@ -201,7 +201,25 @@ export async function startCoolifyProxy(engine: string): Promise { await configureNetworkCoolifyProxy(engine); } -export async function checkContainer(engine: string, container: string): Promise { +export async function isContainerExited(engine: string, containerName: string): Promise { + let isExited = false; + const host = getEngine(engine); + try { + const { stdout } = await asyncExecShell( + `DOCKER_HOST="${host}" docker inspect -f '{{.State.Status}}' ${containerName}` + ); + if (stdout.trim() === 'exited') { + isExited = true; + } + } catch (error) {} + + return isExited; +} +export async function checkContainer( + engine: string, + container: string, + remove: boolean = false +): Promise { const host = getEngine(engine); let containerFound = false; @@ -212,7 +230,10 @@ export async function checkContainer(engine: string, container: string): Promise const parsedStdout = JSON.parse(stdout); const status = parsedStdout.Status; const isRunning = status === 'running'; - if (status === 'exited' || status === 'created') { + if (status === 'created') { + await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`); + } + if (remove && status === 'exited') { await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`); } if (isRunning) { diff --git a/src/lib/queues/builder.ts b/src/lib/queues/builder.ts index bd66c05c6..8e1650106 100644 --- a/src/lib/queues/builder.ts +++ b/src/lib/queues/builder.ts @@ -46,7 +46,8 @@ export default async function (job: Job): Promise): Promise): Promise): Promise = writable(false); diff --git a/src/lib/types/builderJob.ts b/src/lib/types/builderJob.ts index 30a38bfd9..8b7cc3b9f 100644 --- a/src/lib/types/builderJob.ts +++ b/src/lib/types/builderJob.ts @@ -22,6 +22,8 @@ export type BuilderJob = { pythonModule: string; pythonVariable: string; dockerFileLocation: string; + denoMainFile: string; + denoOptions: string; createdAt: string; updatedAt: string; destinationDockerId: string; diff --git a/src/routes/applications/[id]/__layout.svelte b/src/routes/applications/[id]/__layout.svelte index 7b997fae4..b0384cf00 100644 --- a/src/routes/applications/[id]/__layout.svelte +++ b/src/routes/applications/[id]/__layout.svelte @@ -17,7 +17,7 @@ const endpoint = `/applications/${params.id}.json`; const res = await fetch(endpoint); if (res.ok) { - let { application, isRunning, appId, githubToken, gitlabToken } = await res.json(); + let { application, isRunning, isExited, appId, githubToken, gitlabToken } = await res.json(); if (!application || Object.entries(application).length === 0) { return { status: 302, @@ -46,6 +46,7 @@ props: { application, isRunning, + isExited, githubToken, gitlabToken }, @@ -67,21 +68,32 @@