Merge pull request #361 from coollabsio/next

v2.5.0
This commit is contained in:
Andras Bacsai 2022-04-20 23:14:54 +02:00 committed by GitHub
commit e9b852a30e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 718 additions and 463 deletions

View File

@ -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 @@ # Recommended Pull Request Guideline
- 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 @@ ## Database migrations
## 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)

View File

@ -22,7 +22,7 @@ ## Features
### 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 @@ ### 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

View File

@ -1 +0,0 @@
nohup docker build -t coollabsio/prisma-engine:<arm64/amd64> --push . &

View File

@ -0,0 +1 @@
docker build --platform linux/amd64,linux/arm64 -t coollabsio/prisma-engine -f prisma-engine.Dockerfile --push .

View File

@ -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

View File

@ -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"
},

View File

@ -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

View File

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "Application" ADD COLUMN "denoMainFile" TEXT;
ALTER TABLE "Application" ADD COLUMN "denoOptions" TEXT;

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Build" ADD COLUMN "branch" TEXT;

View File

@ -92,6 +92,8 @@ model Application {
pythonModule String?
pythonVariable 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

View File

@ -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);

View File

@ -0,0 +1,54 @@
import { buildImage } from '$lib/docker';
import { promises as fs } from 'fs';
const createDockerfile = async (data, image): Promise<void> => {
const { workdir, port, baseDirectory, secrets, pullmergeRequestId, denoMainFile, denoOptions } =
data;
const Dockerfile: Array<string> = [];
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;
}
}

View File

@ -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
};

View File

@ -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://', '');

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -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 = {

View File

@ -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<Application> {
return await prisma.application.update({
where: { id },
@ -296,7 +300,9 @@ export async function configureApplication({
pythonWSGI,
pythonModule,
pythonVariable,
dockerFileLocation
dockerFileLocation,
denoMainFile,
denoOptions
}
});
}

View File

@ -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 } {

View File

@ -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<void> {
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<void> {
await configureNetworkCoolifyProxy(engine);
}
export async function checkContainer(engine: string, container: string): Promise<boolean> {
export async function isContainerExited(engine: string, containerName: string): Promise<boolean> {
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<boolean> {
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) {

View File

@ -46,7 +46,8 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
persistentStorage,
pythonWSGI,
pythonModule,
pythonVariable
pythonVariable,
denoOptions
} = job.data;
let {
branch,
@ -57,7 +58,8 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
startCommand,
baseDirectory,
publishDirectory,
dockerFileLocation
dockerFileLocation,
denoMainFile
} = job.data;
const { debug } = settings;
@ -109,6 +111,7 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
publishDirectory = configuration.publishDirectory;
baseDirectory = configuration.baseDirectory;
dockerFileLocation = configuration.dockerFileLocation;
denoMainFile = configuration.denoMainFile;
const commit = await importers[gitSource.type]({
applicationId,
@ -212,7 +215,9 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
pythonWSGI,
pythonModule,
pythonVariable,
dockerFileLocation
dockerFileLocation,
denoMainFile,
denoOptions
});
else {
await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId });

View File

@ -5,3 +5,4 @@ export const gitTokens: Writable<{ githubToken: string | null; gitlabToken: stri
githubToken: null,
gitlabToken: null
});
export const disabledButton: Writable<boolean> = writable(false);

View File

@ -22,6 +22,8 @@ export type BuilderJob = {
pythonModule: string;
pythonVariable: string;
dockerFileLocation: string;
denoMainFile: string;
denoOptions: string;
createdAt: string;
updatedAt: string;
destinationDockerId: string;

View File

@ -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 @@
<script lang="ts">
export let application;
export let isRunning;
export let isExited;
export let githubToken;
export let gitlabToken;
import { page, session } from '$app/stores';
import { errorNotification } from '$lib/form';
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
import Loading from '$lib/components/Loading.svelte';
import { del, post } from '$lib/api';
import { del, get, post } from '$lib/api';
import { goto } from '$app/navigation';
import { gitTokens } from '$lib/store';
import { toast } from '@zerodevx/svelte-toast';
import { disabledButton } from '$lib/store';
import { onDestroy, onMount } from 'svelte';
if (githubToken) $gitTokens.githubToken = githubToken;
if (gitlabToken) $gitTokens.gitlabToken = gitlabToken;
let loading = false;
let statusInterval;
$disabledButton =
!$session.isAdmin ||
!application.fqdn ||
!application.gitSource ||
!application.repository ||
!application.destinationDocker ||
!application.buildPack;
const { id } = $page.params;
async function handleDeploySubmit() {
@ -121,142 +133,86 @@
return errorNotification(error);
}
}
async function getStatus() {
statusInterval = setInterval(async () => {
const data = await get(`/applications/${id}.json`);
isRunning = data.isRunning;
isExited = data.isExited;
}, 1000);
}
onDestroy(() => {
clearInterval(statusInterval);
});
onMount(async () => {
await getStatus();
});
</script>
<nav class="nav-side">
{#if loading}
<Loading fullscreen cover />
{:else}
{#if application.fqdn && application.gitSource && application.repository && application.destinationDocker && application.buildPack}
{#if isRunning}
{#if isExited}
<a
href={!$disabledButton ? `/applications/${id}/logs` : null}
class=" icons bg-transparent tooltip-bottom text-sm flex items-center text-red-500 tooltip-red-500"
data-tooltip="Application exited with an error!"
sveltekit:prefetch
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentcolor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M8.7 3h6.6c.3 0 .5 .1 .7 .3l4.7 4.7c.2 .2 .3 .4 .3 .7v6.6c0 .3 -.1 .5 -.3 .7l-4.7 4.7c-.2 .2 -.4 .3 -.7 .3h-6.6c-.3 0 -.5 -.1 -.7 -.3l-4.7 -4.7c-.2 -.2 -.3 -.4 -.3 -.7v-6.6c0 -.3 .1 -.5 .3 -.7l4.7 -4.7c.2 -.2 .4 -.3 .7 -.3z"
/>
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
</a>
{/if}
{#if isRunning}
<button
on:click={stopApplication}
title="Stop application"
type="submit"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
data-tooltip={$session.isAdmin
? 'Stop application'
: 'You do not have permission to stop the application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="6" y="5" width="4" height="14" rx="1" />
<rect x="14" y="5" width="4" height="14" rx="1" />
</svg>
</button>
<form on:submit|preventDefault={handleDeploySubmit}>
<button
on:click={stopApplication}
title="Stop application"
title="Rebuild application"
type="submit"
disabled={!$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:text-green-500"
data-tooltip={$session.isAdmin
? 'Stop application'
: 'You do not have permission to stop the application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="6" y="5" width="4" height="14" rx="1" />
<rect x="14" y="5" width="4" height="14" rx="1" />
</svg>
</button>
<form on:submit|preventDefault={handleDeploySubmit}>
<button
title="Rebuild application"
type="submit"
disabled={!$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:text-green-500"
data-tooltip={$session.isAdmin
? 'Rebuild application'
: 'You do not have permission to rebuild application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M16.3 5h.7a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h5l-2.82 -2.82m0 5.64l2.82 -2.82"
transform="rotate(-45 12 12)"
/>
</svg>
</button>
</form>
{:else}
<form on:submit|preventDefault={handleDeploySubmit}>
<button
title="Build and start application"
type="submit"
disabled={!$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
data-tooltip={$session.isAdmin
? 'Build and start application'
: 'You do not have permission to Build and start application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 4v16l13 -8z" />
</svg>
</button>
</form>
{/if}
<div class="border border-stone-700 h-8" />
<a
href="/applications/{id}"
sveltekit:prefetch
class="hover:text-yellow-500 rounded"
class:text-yellow-500={$page.url.pathname === `/applications/${id}`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}`}
>
<button
title="Configurations"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Configurations"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="4" y="8" width="4" height="4" />
<line x1="6" y1="4" x2="6" y2="8" />
<line x1="6" y1="12" x2="6" y2="20" />
<rect x="10" y="14" width="4" height="4" />
<line x1="12" y1="4" x2="12" y2="14" />
<line x1="12" y1="18" x2="12" y2="20" />
<rect x="16" y="5" width="4" height="4" />
<line x1="18" y1="4" x2="18" y2="5" />
<line x1="18" y1="9" x2="18" y2="20" />
</svg></button
></a
>
<a
href="/applications/{id}/secrets"
sveltekit:prefetch
class="hover:text-pink-500 rounded"
class:text-pink-500={$page.url.pathname === `/applications/${id}/secrets`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/secrets`}
>
<button
title="Secret"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Secret"
? 'Rebuild application'
: 'You do not have permission to rebuild application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -270,24 +226,22 @@
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1 -8.5 15a12 12 0 0 1 -8.5 -15a12 12 0 0 0 8.5 -3"
d="M16.3 5h.7a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h5l-2.82 -2.82m0 5.64l2.82 -2.82"
transform="rotate(-45 12 12)"
/>
<circle cx="12" cy="11" r="1" />
<line x1="12" y1="12" x2="12" y2="14.5" />
</svg></button
></a
>
<a
href="/applications/{id}/storage"
sveltekit:prefetch
class="hover:text-pink-500 rounded"
class:text-pink-500={$page.url.pathname === `/applications/${id}/storage`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/storage`}
>
</svg>
</button>
</form>
{:else}
<form on:submit|preventDefault={handleDeploySubmit}>
<button
title="Persistent Storage"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Persistent Storage"
title="Build and start application"
type="submit"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
data-tooltip={$session.isAdmin
? 'Build and start application'
: 'You do not have permission to Build and start application.'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -300,112 +254,213 @@
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<ellipse cx="12" cy="6" rx="8" ry="3" />
<path d="M4 6v6a8 3 0 0 0 16 0v-6" />
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
<path d="M7 4v16l13 -8z" />
</svg>
</button></a
>
<a
href="/applications/{id}/previews"
sveltekit:prefetch
class="hover:text-orange-500 rounded"
class:text-orange-500={$page.url.pathname === `/applications/${id}/previews`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/previews`}
>
<button
title="Previews"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Previews"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="7" cy="18" r="2" />
<circle cx="7" cy="6" r="2" />
<circle cx="17" cy="12" r="2" />
<line x1="7" y1="8" x2="7" y2="16" />
<path d="M7 8a4 4 0 0 0 4 4h4" />
</svg></button
></a
>
<div class="border border-stone-700 h-8" />
<a
href="/applications/{id}/logs"
sveltekit:prefetch
class="hover:text-sky-500 rounded"
class:text-sky-500={$page.url.pathname === `/applications/${id}/logs`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/logs`}
>
<button
title="Application Logs"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500 "
data-tooltip="Application Logs"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3 19a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
<path d="M3 6a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
<line x1="3" y1="6" x2="3" y2="19" />
<line x1="12" y1="6" x2="12" y2="19" />
<line x1="21" y1="6" x2="21" y2="19" />
</svg>
</button></a
>
<a
href="/applications/{id}/logs/build"
sveltekit:prefetch
class="hover:text-red-500 rounded"
class:text-red-500={$page.url.pathname === `/applications/${id}/logs/build`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/logs/build`}
>
<button
title="Build Logs"
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500 "
data-tooltip="Build Logs"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="19" cy="13" r="2" />
<circle cx="4" cy="17" r="2" />
<circle cx="13" cy="17" r="2" />
<line x1="13" y1="19" x2="4" y2="19" />
<line x1="4" y1="15" x2="13" y2="15" />
<path d="M8 12v-5h2a3 3 0 0 1 3 3v5" />
<path d="M5 15v-2a1 1 0 0 1 1 -1h7" />
<path d="M19 11v-7l-6 7" />
</svg>
</button></a
>
<div class="border border-stone-700 h-8" />
</button>
</form>
{/if}
<div class="border border-coolgray-500 h-8" />
<a
href={!$disabledButton ? `/applications/${id}` : null}
sveltekit:prefetch
class="hover:text-yellow-500 rounded"
class:text-yellow-500={$page.url.pathname === `/applications/${id}`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}`}
>
<button
title="Configurations"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Configurations"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="4" y="8" width="4" height="4" />
<line x1="6" y1="4" x2="6" y2="8" />
<line x1="6" y1="12" x2="6" y2="20" />
<rect x="10" y="14" width="4" height="4" />
<line x1="12" y1="4" x2="12" y2="14" />
<line x1="12" y1="18" x2="12" y2="20" />
<rect x="16" y="5" width="4" height="4" />
<line x1="18" y1="4" x2="18" y2="5" />
<line x1="18" y1="9" x2="18" y2="20" />
</svg></button
></a
>
<a
href={!$disabledButton ? `/applications/${id}/secrets` : null}
sveltekit:prefetch
class="hover:text-pink-500 rounded"
class:text-pink-500={$page.url.pathname === `/applications/${id}/secrets`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/secrets`}
>
<button
title="Secret"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Secret"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1 -8.5 15a12 12 0 0 1 -8.5 -15a12 12 0 0 0 8.5 -3"
/>
<circle cx="12" cy="11" r="1" />
<line x1="12" y1="12" x2="12" y2="14.5" />
</svg></button
></a
>
<a
href={!$disabledButton ? `/applications/${id}/storage` : null}
sveltekit:prefetch
class="hover:text-pink-500 rounded"
class:text-pink-500={$page.url.pathname === `/applications/${id}/storage`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/storage`}
>
<button
title="Persistent Storage"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Persistent Storage"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<ellipse cx="12" cy="6" rx="8" ry="3" />
<path d="M4 6v6a8 3 0 0 0 16 0v-6" />
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
</svg>
</button></a
>
<a
href={!$disabledButton ? `/applications/${id}/previews` : null}
sveltekit:prefetch
class="hover:text-orange-500 rounded"
class:text-orange-500={$page.url.pathname === `/applications/${id}/previews`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/previews`}
>
<button
title="Previews"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Previews"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="7" cy="18" r="2" />
<circle cx="7" cy="6" r="2" />
<circle cx="17" cy="12" r="2" />
<line x1="7" y1="8" x2="7" y2="16" />
<path d="M7 8a4 4 0 0 0 4 4h4" />
</svg></button
></a
>
<div class="border border-coolgray-500 h-8" />
<a
href={!$disabledButton ? `/applications/${id}/logs` : null}
sveltekit:prefetch
class="hover:text-sky-500 rounded"
class:text-sky-500={$page.url.pathname === `/applications/${id}/logs`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/logs`}
>
<button
title="Application Logs"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Application Logs"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3 19a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
<path d="M3 6a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
<line x1="3" y1="6" x2="3" y2="19" />
<line x1="12" y1="6" x2="12" y2="19" />
<line x1="21" y1="6" x2="21" y2="19" />
</svg>
</button></a
>
<a
href={!$disabledButton ? `/applications/${id}/logs/build` : null}
sveltekit:prefetch
class="hover:text-red-500 rounded"
class:text-red-500={$page.url.pathname === `/applications/${id}/logs/build`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}/logs/build`}
>
<button
title="Build Logs"
disabled={$disabledButton}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip="Build Logs"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="19" cy="13" r="2" />
<circle cx="4" cy="17" r="2" />
<circle cx="13" cy="17" r="2" />
<line x1="13" y1="19" x2="4" y2="19" />
<line x1="4" y1="15" x2="13" y2="15" />
<path d="M8 12v-5h2a3 3 0 0 1 3 3v5" />
<path d="M5 15v-2a1 1 0 0 1 1 -1h7" />
<path d="M19 11v-7l-6 7" />
</svg>
</button></a
>
<div class="border border-coolgray-500 h-8" />
<button
on:click={() => deleteApplication(application.name)}
title="Delete application"

View File

@ -19,13 +19,14 @@
const tempBuildPack = JSON.parse(
JSON.stringify(findBuildPack(buildPack.name, packageManager))
);
delete tempBuildPack.name;
delete tempBuildPack.fancyName;
delete tempBuildPack.color;
delete tempBuildPack.hoverColor;
if (foundConfig.buildPack !== name) {
await post(`/applications/${id}.json`, { ...tempBuildPack });
await post(`/applications/${id}.json`, { ...tempBuildPack, buildPack: name });
}
await post(`/applications/${id}/configuration/buildpack.json`, { buildPack: name });
return await goto(from || `/applications/${id}`);

View File

@ -31,7 +31,7 @@
import { buildPacks, findBuildPack, scanningTemplates } from '$lib/components/templates';
import BuildPack from './_BuildPack.svelte';
import { page, session } from '$app/stores';
import { page } from '$app/stores';
import { get } from '$lib/api';
import { errorNotification } from '$lib/form';
import { gitTokens } from '$lib/store';
@ -221,7 +221,7 @@
<div class="max-w-7xl mx-auto flex flex-wrap justify-center">
{#each buildPacks as buildPack}
<div class="p-2">
<BuildPack {buildPack} {scanning} {packageManager} bind:foundConfig />
<BuildPack {buildPack} {scanning} bind:foundConfig />
</div>
{/each}
</div>

View File

@ -35,6 +35,7 @@ export const post: RequestHandler = async (event) => {
data: {
id: buildId,
applicationId: id,
branch: applicationFound.branch,
destinationDockerId: applicationFound.destinationDocker.id,
gitSourceId: applicationFound.gitSource.id,
githubAppId: applicationFound.gitSource.githubApp?.id,

View File

@ -1,7 +1,7 @@
import { getUserDetails } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import { checkContainer } from '$lib/haproxy';
import { checkContainer, isContainerExited } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit';
import jsonwebtoken from 'jsonwebtoken';
import { get as getRequest } from '$lib/api';
@ -15,17 +15,20 @@ export const get: RequestHandler = async (event) => {
const appId = process.env['COOLIFY_APP_ID'];
let isRunning = false;
let isExited = false;
let githubToken = event.locals.cookies?.githubToken || null;
let gitlabToken = event.locals.cookies?.gitlabToken || null;
try {
const application = await db.getApplication({ id, teamId });
if (application.destinationDockerId) {
isRunning = await checkContainer(application.destinationDocker.engine, id);
isExited = await isContainerExited(application.destinationDocker.engine, id);
}
return {
status: 200,
body: {
isRunning,
isExited,
application,
appId,
githubToken,
@ -57,9 +60,12 @@ export const post: RequestHandler = async (event) => {
pythonWSGI,
pythonModule,
pythonVariable,
dockerFileLocation
dockerFileLocation,
denoMainFile,
denoOptions
} = await event.request.json();
if (port) port = Number(port);
if (denoOptions) denoOptions = denoOptions.trim();
try {
const defaultConfiguration = await setDefaultConfiguration({
@ -70,7 +76,8 @@ export const post: RequestHandler = async (event) => {
buildCommand,
publishDirectory,
baseDirectory,
dockerFileLocation
dockerFileLocation,
denoMainFile
});
await db.configureApplication({
id,
@ -87,6 +94,8 @@ export const post: RequestHandler = async (event) => {
pythonModule,
pythonVariable,
dockerFileLocation,
denoMainFile,
denoOptions,
...defaultConfiguration
});
return { status: 201 };

View File

@ -48,6 +48,7 @@
import { post } from '$lib/api';
import cuid from 'cuid';
import { browser } from '$app/env';
import { disabledButton } from '$lib/store';
const { id } = $page.params;
let domainEl: HTMLInputElement;
@ -122,7 +123,8 @@
try {
await post(`/applications/${id}/check.json`, { fqdn: application.fqdn, forceSave });
await post(`/applications/${id}.json`, { ...application });
return window.location.reload();
$disabledButton = false;
return toast.push('Configurations saved.');
} catch ({ error }) {
if (error?.startsWith('DNS not set')) {
forceSave = true;
@ -432,6 +434,31 @@
/>
</div>
{/if}
{#if application.buildPack === 'deno'}
<div class="grid grid-cols-2 items-center">
<label for="denoMainFile" class="text-base font-bold text-stone-100">Main File</label>
<input
readonly={!$session.isAdmin}
name="denoMainFile"
id="denoMainFile"
bind:value={application.denoMainFile}
placeholder="default: main.ts"
/>
</div>
<div class="grid grid-cols-2 items-center">
<label for="denoOptions" class="text-base font-bold text-stone-100">Arguments</label>
<input
readonly={!$session.isAdmin}
name="denoOptions"
id="denoOptions"
bind:value={application.denoOptions}
placeholder="eg: --allow-net --allow-hrtime --config path/to/file.json"
/>
<Explainer
text="List of arguments to pass to <span class='text-green-500 font-bold'>deno run</span> command. Could include permissions, configurations files, etc."
/>
</div>
{/if}
<div class="grid grid-cols-2 items-center">
<div class="flex-col">
<label for="baseDirectory" class="pt-2 text-base font-bold text-stone-100"

View File

@ -21,12 +21,11 @@
<script lang="ts">
import { page } from '$app/stores';
import { changeQueryParams, dateOptions, getDomain } from '$lib/components/common';
import { changeQueryParams, dateOptions } from '$lib/components/common';
import BuildLog from './_BuildLog.svelte';
import { get } from '$lib/api';
import { errorNotification } from '$lib/form';
import { goto } from '$app/navigation';
export let builds;
export let application;
@ -174,7 +173,7 @@
>
<div class="flex-col px-2">
<div class="text-sm font-bold">
{application.branch}
{build.branch || application.branch}
</div>
<div class="text-xs">
{build.type}

View File

@ -22,7 +22,9 @@ export const get: RequestHandler = async (event) => {
if (container) {
return {
body: {
logs: (await container.logs({ stdout: true, stderr: true, timestamps: true }))
logs: (
await container.logs({ stdout: true, stderr: true, timestamps: true, tail: 5000 })
)
.toString()
.split('\n')
.map((l) => l.slice(8))

View File

@ -19,6 +19,7 @@
import Docker from '$lib/components/svg/applications/Docker.svelte';
import Astro from '$lib/components/svg/applications/Astro.svelte';
import Eleventy from '$lib/components/svg/applications/Eleventy.svelte';
import Deno from '$lib/components/svg/applications/Deno.svelte';
import { getDomain } from '$lib/components/common';
async function newApplication() {
@ -100,6 +101,8 @@
<Astro />
{:else if application.buildPack.toLowerCase() === 'eleventy'}
<Eleventy />
{:else if application.buildPack.toLowerCase() === 'deno'}
<Deno />
{/if}
{/if}
@ -156,6 +159,8 @@
<Astro />
{:else if application.buildPack.toLowerCase() === 'eleventy'}
<Eleventy />
{:else if application.buildPack.toLowerCase() === 'deno'}
<Deno />
{/if}
{/if}

View File

@ -119,7 +119,7 @@ .add-icon {
}
.icons {
@apply rounded p-2 transition duration-200 hover:bg-coolgray-500 disabled:bg-coolblack !important;
@apply rounded p-2 transition duration-200 hover:bg-coolgray-500 disabled:bg-coolblack disabled:text-coolgray-500 !important;
}
.arrow-right-applications {