diff --git a/.github/workflows/production-release.yml b/.github/workflows/production-release.yml index baf574184..961e1f18f 100644 --- a/.github/workflows/production-release.yml +++ b/.github/workflows/production-release.yml @@ -5,11 +5,11 @@ on: types: [released] jobs: - making-something-cool: - runs-on: ubuntu-latest + arm64-build: + runs-on: [self-hosted, arm64] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx @@ -26,11 +26,56 @@ jobs: uses: docker/build-push-action@v2 with: context: . - platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 push: true - tags: coollabsio/coolify:latest,coollabsio/coolify:${{steps.package-version.outputs.current-version}} - cache-from: type=registry,ref=coollabsio/coolify:buildcache - cache-to: type=registry,ref=coollabsio/coolify:buildcache,mode=max + tags: coollabsio/coolify:${{steps.package-version.outputs.current-version}}-arm64 + cache-from: type=registry,ref=coollabsio/coolify:buildcache-arm64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-arm64,mode=max + amd64-build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Get current package version + uses: martinbeentjes/npm-get-version-action@v1.2.3 + id: package-version + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64 + push: true + tags: coollabsio/coolify:${{steps.package-version.outputs.current-version}}-amd64 + cache-from: type=registry,ref=coollabsio/coolify:buildcache-amd64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-amd64,mode=max + merge-manifest: + runs-on: ubuntu-latest + needs: [amd64-build, arm64-build] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Create & publish manifest + run: | + docker manifest create coollabsio/coolify:${{steps.package-version.outputs.current-version}} --amend coollabsio/coolify:${{steps.package-version.outputs.current-version}}-amd64 --amend coollabsio/coolify:${{steps.package-version.outputs.current-version}}-arm64 + docker manifest push coollabsio/coolify:${{steps.package-version.outputs.current-version}} - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index ba1de9b08..305ea3ad9 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -1,17 +1,16 @@ name: release-candidate - on: release: types: [prereleased] jobs: - making-something-cool: - runs-on: ubuntu-latest + arm64-making-something-cool: + runs-on: [self-hosted, arm64] steps: - name: Checkout uses: actions/checkout@v3 with: - ref: 'next' + ref: "next" - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx @@ -28,12 +27,64 @@ jobs: uses: docker/build-push-action@v2 with: context: . - platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 push: true - tags: coollabsio/coolify:${{github.event.release.name}} - cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc - cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc,mode=max + tags: coollabsio/coolify:${{github.event.release.name}}-arm64 + cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc-arm64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc-arm64,mode=max - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} + amd64-making-something-cool: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: "next" + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Get current package version + uses: martinbeentjes/npm-get-version-action@v1.2.3 + id: package-version + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64 + push: true + tags: coollabsio/coolify:${{github.event.release.name}}-amd64 + cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc-amd64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc-amd64,mode=max + - uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} + merge-manifest-to-be-cool: + runs-on: ubuntu-latest + needs: [arm64-making-something-cool, amd64-making-something-cool] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Create & publish manifest + run: | + docker manifest create coollabsio/coolify:${{github.event.release.name}} --amend coollabsio/coolify:${{github.event.release.name}}-amd64 --amend coollabsio/coolify:${{github.event.release.name}}-arm64 + docker manifest push coollabsio/coolify:${{github.event.release.name}} + diff --git a/.github/workflows/staging-release.yml b/.github/workflows/staging-release.yml index 86fed13ff..7a5e5474f 100644 --- a/.github/workflows/staging-release.yml +++ b/.github/workflows/staging-release.yml @@ -6,11 +6,13 @@ on: - next jobs: - staging-release: - runs-on: ubuntu-latest + arm64-making-something-cool: + runs-on: [self-hosted, arm64] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + ref: "next" - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx @@ -20,15 +22,65 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Get current package version + uses: martinbeentjes/npm-get-version-action@v1.2.3 + id: package-version - name: Build and push uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/arm64 + push: true + tags: coollabsio/coolify:next-arm64 + cache-from: type=registry,ref=coollabsio/coolify:buildcache-next-arm64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-next-arm64,mode=max + amd64-making-something-cool: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: "next" + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Get current package version + uses: martinbeentjes/npm-get-version-action@v1.2.3 + id: package-version + - name: Build and push + uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64 push: true - tags: coollabsio/coolify:next - cache-from: type=registry,ref=coollabsio/coolify:buildcache-next - cache-to: type=registry,ref=coollabsio/coolify:buildcache-next,mode=max + tags: coollabsio/coolify:next-amd64,coollabsio/coolify:next-test + cache-from: type=registry,ref=coollabsio/coolify:buildcache-next-amd64 + cache-to: type=registry,ref=coollabsio/coolify:buildcache-next-amd64,mode=max + merge-manifest-to-be-cool: + runs-on: ubuntu-latest + needs: [arm64-making-something-cool, amd64-making-something-cool] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Create & publish manifest + run: | + docker manifest create coollabsio/coolify:next --amend coollabsio/coolify:next-amd64 --amend coollabsio/coolify:next-arm64 + docker manifest push coollabsio/coolify:next - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/Dockerfile b/Dockerfile index 938346439..675fe5b5b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,11 @@ +ARG PNPM_VERSION=7.11.0 +ARG NPM_VERSION=8.19.1 + FROM node:18-slim as build WORKDIR /app RUN apt update && apt -y install curl -RUN curl -sL https://unpkg.com/@pnpm/self-installer | node +RUN npm --no-update-notifier --no-fund --global install pnpm@${PNPM_VERSION} COPY . . RUN pnpm install @@ -14,8 +17,10 @@ WORKDIR /app ENV NODE_ENV production ARG TARGETPLATFORM -RUN apt update && apt -y install git git-lfs openssh-client curl jq cmake sqlite3 openssl psmisc python3 && apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ -RUN curl -sL https://unpkg.com/@pnpm/self-installer | node +RUN apt update && apt -y install --no-install-recommends ca-certificates git git-lfs openssh-client curl jq cmake sqlite3 openssl psmisc python3 +RUN apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ +RUN npm --no-update-notifier --no-fund --global install pnpm@${PNPM_VERSION} +RUN npm install -g npm@${PNPM_VERSION} RUN mkdir -p ~/.docker/cli-plugins/ # https://download.docker.com/linux/static/stable/ diff --git a/apps/api/prisma/migrations/20220906120112_enable_api_debug_logging/migration.sql b/apps/api/prisma/migrations/20220906120112_enable_api_debug_logging/migration.sql new file mode 100644 index 000000000..05fb3e285 --- /dev/null +++ b/apps/api/prisma/migrations/20220906120112_enable_api_debug_logging/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Setting" ADD COLUMN "isAPIDebuggingEnabled" BOOLEAN DEFAULT false; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 64657e887..681293b53 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -11,6 +11,7 @@ datasource db { model Setting { id String @id @default(cuid()) fqdn String? @unique + isAPIDebuggingEnabled Boolean? @default(false) isRegistrationEnabled Boolean @default(false) dualCerts Boolean @default(false) minPort Int @default(9000) diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 4b3b3998f..902596459 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -5,7 +5,7 @@ import env from '@fastify/env'; import cookie from '@fastify/cookie'; import path, { join } from 'path'; import autoLoad from '@fastify/autoload'; -import { asyncExecShell, createRemoteEngineConfiguration, isDev, listSettings, prisma, version } from './lib/common'; +import { asyncExecShell, createRemoteEngineConfiguration, getDomain, isDev, listSettings, prisma, version } from './lib/common'; import { scheduler } from './lib/scheduler'; import { compareVersions } from 'compare-versions'; import Graceful from '@ladjs/graceful' @@ -26,122 +26,143 @@ declare module 'fastify' { const port = isDev ? 3001 : 3000; const host = '0.0.0.0'; -const fastify = Fastify({ - logger: false, - trustProxy: true -}); -const schema = { - type: 'object', - required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'], - properties: { - COOLIFY_APP_ID: { - type: 'string', - }, - COOLIFY_SECRET_KEY: { - type: 'string', - }, - COOLIFY_DATABASE_URL: { - type: 'string', - default: 'file:../db/dev.db' - }, - COOLIFY_SENTRY_DSN: { - type: 'string', - default: null - }, - COOLIFY_IS_ON: { - type: 'string', - default: 'docker' - }, - COOLIFY_WHITE_LABELED: { - type: 'string', - default: 'false' - }, - COOLIFY_WHITE_LABELED_ICON: { - type: 'string', - default: null - }, - COOLIFY_AUTO_UPDATE: { - type: 'string', - default: 'false' - }, - - } -}; - -const options = { - schema, - dotenv: true -}; -fastify.register(env, options); -if (!isDev) { - fastify.register(serve, { - root: path.join(__dirname, './public'), - preCompressed: true +prisma.setting.findFirst().then(async (settings) => { + const fastify = Fastify({ + logger: settings?.isAPIDebuggingEnabled || false, + trustProxy: true }); - fastify.setNotFoundHandler(async function (request, reply) { - if (request.raw.url && request.raw.url.startsWith('/api')) { - return reply.status(404).send({ - success: false - }); - } - return reply.status(200).sendFile('index.html'); - }); -} -fastify.register(autoLoad, { - dir: join(__dirname, 'plugins') -}); -fastify.register(autoLoad, { - dir: join(__dirname, 'routes') -}); + const schema = { + type: 'object', + required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'], + properties: { + COOLIFY_APP_ID: { + type: 'string', + }, + COOLIFY_SECRET_KEY: { + type: 'string', + }, + COOLIFY_DATABASE_URL: { + type: 'string', + default: 'file:../db/dev.db' + }, + COOLIFY_SENTRY_DSN: { + type: 'string', + default: null + }, + COOLIFY_IS_ON: { + type: 'string', + default: 'docker' + }, + COOLIFY_WHITE_LABELED: { + type: 'string', + default: 'false' + }, + COOLIFY_WHITE_LABELED_ICON: { + type: 'string', + default: null + }, + COOLIFY_AUTO_UPDATE: { + type: 'string', + default: 'false' + }, -fastify.register(cookie) -fastify.register(cors); -fastify.listen({ port, host }, async (err: any, address: any) => { - if (err) { - console.error(err); - process.exit(1); + } + }; + + const options = { + schema, + dotenv: true + }; + fastify.register(env, options); + if (!isDev) { + fastify.register(serve, { + root: path.join(__dirname, './public'), + preCompressed: true + }); + fastify.setNotFoundHandler(async function (request, reply) { + if (request.raw.url && request.raw.url.startsWith('/api')) { + return reply.status(404).send({ + success: false + }); + } + return reply.status(200).sendFile('index.html'); + }); } - console.log(`Coolify's API is listening on ${host}:${port}`); - await initServer(); + fastify.register(autoLoad, { + dir: join(__dirname, 'plugins') + }); + fastify.register(autoLoad, { + dir: join(__dirname, 'routes') + }); - const graceful = new Graceful({ brees: [scheduler] }); - graceful.listen(); + fastify.register(cookie) + fastify.register(cors); + fastify.addHook('onRequest', async (request, reply) => { + let allowedList = ['coolify:3000']; + const { ipv4, ipv6, fqdn } = await prisma.setting.findFirst({}) - setInterval(async () => { - if (!scheduler.workers.has('deployApplication')) { - scheduler.run('deployApplication'); + ipv4 && allowedList.push(`${ipv4}:3000`); + ipv6 && allowedList.push(ipv6); + fqdn && allowedList.push(getDomain(fqdn)); + isDev && allowedList.push('localhost:3000') && allowedList.push('localhost:3001') && allowedList.push('host.docker.internal:3001'); + const remotes = await prisma.destinationDocker.findMany({ where: { remoteEngine: true, remoteVerified: true } }) + if (remotes.length > 0) { + remotes.forEach(remote => { + allowedList.push(`${remote.remoteIpAddress}:3000`); + }) } - if (!scheduler.workers.has('infrastructure')) { - scheduler.run('infrastructure'); + if (!allowedList.includes(request.headers.host)) { + // console.log('not allowed', request.headers.host) } - }, 2000) + }) + fastify.listen({ port, host }, async (err: any, address: any) => { + if (err) { + console.error(err); + process.exit(1); + } + console.log(`Coolify's API is listening on ${host}:${port}`); + await initServer(); - // autoUpdater - setInterval(async () => { - scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:autoUpdater") - }, isDev ? 5000 : 60000 * 15) + const graceful = new Graceful({ brees: [scheduler] }); + graceful.listen(); - // cleanupStorage - setInterval(async () => { - scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupStorage") - }, isDev ? 6000 : 60000 * 10) + setInterval(async () => { + if (!scheduler.workers.has('deployApplication')) { + scheduler.run('deployApplication'); + } + if (!scheduler.workers.has('infrastructure')) { + scheduler.run('infrastructure'); + } + }, 2000) - // checkProxies - setInterval(async () => { - scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:checkProxies") - }, 10000) + // autoUpdater + setInterval(async () => { + scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:autoUpdater") + }, isDev ? 5000 : 60000 * 15) - // cleanupPrismaEngines - // setInterval(async () => { - // scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupPrismaEngines") - // }, 60000) + // cleanupStorage + setInterval(async () => { + scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupStorage") + }, isDev ? 6000 : 60000 * 10) + + // checkProxies + setInterval(async () => { + scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:checkProxies") + }, 10000) + + // cleanupPrismaEngines + // setInterval(async () => { + // scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupPrismaEngines") + // }, 60000) + + await Promise.all([ + getArch(), + getIPAddress(), + configureRemoteDockers(), + ]) + }); +}) - await Promise.all([ - getArch(), - getIPAddress(), - // configureRemoteDockers(), - ]) -}); async function getIPAddress() { const { publicIpv4, publicIpv6 } = await import('public-ip') try { diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index 7ec322f63..945883bb2 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -357,21 +357,15 @@ import * as buildpacks from '../lib/buildPacks'; await saveBuildLog({ line: error, buildId, applicationId: application.id }); } }); - } - await pAll.default(actions, { concurrency }) } } catch (error) { console.log(error) - } finally { } }) - while (true) { await th() } - - } else process.exit(0); })(); diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 90b35cd12..7d1ca3a9b 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -21,7 +21,7 @@ import { scheduler } from './scheduler'; import { supportedServiceTypesAndVersions } from './services/supportedVersions'; import { includeServices } from './services/common'; -export const version = '3.9.0'; +export const version = '3.9.1'; export const isDev = process.env.NODE_ENV === 'development'; const algorithm = 'aes-256-ctr'; @@ -974,9 +974,14 @@ export const createDirectories = async ({ }): Promise<{ workdir: string; repodir: string }> => { const repodir = `/tmp/build-sources/${repository}/`; const workdir = `/tmp/build-sources/${repository}/${buildId}`; - + let workdirFound = false; + try { + workdirFound = !!(await fs.stat(workdir)); + } catch (error) { } + if (workdirFound) { + await asyncExecShell(`rm -fr ${workdir}`); + } await asyncExecShell(`mkdir -p ${workdir}`); - return { workdir, repodir diff --git a/apps/api/src/routes/api/v1/settings/handlers.ts b/apps/api/src/routes/api/v1/settings/handlers.ts index 068d2c97e..e9d91dd8c 100644 --- a/apps/api/src/routes/api/v1/settings/handlers.ts +++ b/apps/api/src/routes/api/v1/settings/handlers.ts @@ -28,6 +28,7 @@ export async function saveSettings(request: FastifyRequest, reply: try { const { fqdn, + isAPIDebuggingEnabled, isRegistrationEnabled, dualCerts, minPort, @@ -39,7 +40,7 @@ export async function saveSettings(request: FastifyRequest, reply: const { id } = await listSettings(); await prisma.setting.update({ where: { id }, - data: { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers } + data: { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers, isAPIDebuggingEnabled } }); if (fqdn) { await prisma.setting.update({ where: { id }, data: { fqdn } }); diff --git a/apps/api/src/routes/api/v1/settings/types.ts b/apps/api/src/routes/api/v1/settings/types.ts index d8fcf816d..956c58b5c 100644 --- a/apps/api/src/routes/api/v1/settings/types.ts +++ b/apps/api/src/routes/api/v1/settings/types.ts @@ -3,6 +3,7 @@ import { OnlyId } from "../../../../types" export interface SaveSettings { Body: { fqdn: string, + isAPIDebuggingEnabled: boolean, isRegistrationEnabled: boolean, dualCerts: boolean, minPort: number, diff --git a/apps/api/src/routes/webhooks/traefik/index.ts b/apps/api/src/routes/webhooks/traefik/index.ts index f9c7ff4b8..3769c8eb3 100644 --- a/apps/api/src/routes/webhooks/traefik/index.ts +++ b/apps/api/src/routes/webhooks/traefik/index.ts @@ -1,4 +1,5 @@ import { FastifyPluginAsync } from 'fastify'; +import { OnlyId } from '../../../types'; import { remoteTraefikConfiguration, traefikConfiguration, traefikOtherConfiguration } from './handlers'; import { TraefikOtherConfiguration } from './types'; @@ -6,7 +7,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/main.json', async (request, reply) => traefikConfiguration(request, reply)); fastify.get('/other.json', async (request, reply) => traefikOtherConfiguration(request)); - fastify.get('/remote/:id', async (request) => remoteTraefikConfiguration(request)); + fastify.get('/remote/:id', async (request) => remoteTraefikConfiguration(request)); }; export default root; diff --git a/apps/ui/src/lib/components/Usage.svelte b/apps/ui/src/lib/components/Usage.svelte index e5437a1d5..a5128c6b6 100644 --- a/apps/ui/src/lib/components/Usage.svelte +++ b/apps/ui/src/lib/components/Usage.svelte @@ -20,13 +20,12 @@ let usageInterval: any; let loading = { usage: false, - cleanup: false, - restart: false + cleanup: false }; import { addToast, appSession } from '$lib/store'; import { onDestroy, onMount } from 'svelte'; import { get, post } from '$lib/api'; - import { asyncSleep, errorNotification } from '$lib/common'; + import { errorNotification } from '$lib/common'; async function getStatus() { if (loading.usage) return; loading.usage = true; @@ -34,45 +33,7 @@ usage = data.usage; loading.usage = false; } - async function restartCoolify() { - const sure = confirm( - 'Are you sure you would like to restart Coolify? Currently running deployments will be stopped and restarted.' - ); - if (sure) { - loading.restart = true; - try { - await post(`/internal/restart`, {}); - await asyncSleep(10000); - let reachable = false; - let tries = 0; - do { - await asyncSleep(4000); - try { - await get(`/undead`); - reachable = true; - } catch (error) { - reachable = false; - } - if (reachable) break; - tries++; - } while (!reachable || tries < 120); - addToast({ - message: 'New version reachable. Reloading...', - type: 'success' - }); - await asyncSleep(3000); - return window.location.reload(); - addToast({ - type: 'success', - message: 'Coolify restarted successfully. It will take a moment.' - }); - } catch (error) { - return errorNotification(error); - } finally { - loading.restart = false; - } - } - } + onDestroy(() => { clearInterval(usageInterval); }); @@ -112,11 +73,6 @@ - {/if} diff --git a/apps/ui/src/routes/settings/global.svelte b/apps/ui/src/routes/settings/global.svelte index 219730d9a..ee64d908e 100644 --- a/apps/ui/src/routes/settings/global.svelte +++ b/apps/ui/src/routes/settings/global.svelte @@ -23,10 +23,11 @@ import { browser } from '$app/env'; import { t } from '$lib/translations'; import { addToast, appSession, features } from '$lib/store'; - import { errorNotification, getDomain } from '$lib/common'; + import { asyncSleep, errorNotification, getDomain } from '$lib/common'; import Menu from './_Menu.svelte'; import Explainer from '$lib/components/Explainer.svelte'; + let isAPIDebuggingEnabled = settings.isAPIDebuggingEnabled; let isRegistrationEnabled = settings.isRegistrationEnabled; let dualCerts = settings.dualCerts; let isAutoUpdateEnabled = settings.isAutoUpdateEnabled; @@ -44,7 +45,8 @@ let loading = { save: false, remove: false, - proxyMigration: false + proxyMigration: false, + restart: false }; async function removeFqdn() { @@ -75,8 +77,11 @@ if (name === 'isDNSCheckEnabled') { isDNSCheckEnabled = !isDNSCheckEnabled; } - + if (name === 'isAPIDebuggingEnabled') { + isAPIDebuggingEnabled = !isAPIDebuggingEnabled; + } await post(`/settings`, { + isAPIDebuggingEnabled, isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, @@ -152,6 +157,41 @@ function resetView() { forceSave = false; } + async function restartCoolify() { + const sure = confirm( + 'Are you sure you would like to restart Coolify? Currently running deployments will be stopped and restarted.' + ); + if (sure) { + loading.restart = true; + try { + await post(`/internal/restart`, {}); + await asyncSleep(10000); + let reachable = false; + let tries = 0; + do { + await asyncSleep(4000); + try { + await get(`/undead`); + reachable = true; + } catch (error) { + reachable = false; + } + if (reachable) break; + tries++; + } while (!reachable || tries < 120); + addToast({ + message: 'New version reachable. Reloading...', + type: 'success' + }); + await asyncSleep(3000); + return window.location.reload(); + } catch (error) { + return errorNotification(error); + } finally { + loading.restart = false; + } + } + }
@@ -182,11 +222,14 @@ on:click|preventDefault={removeFqdn} disabled={loading.remove} class="btn btn-sm" - class:bg-red-600={!loading.remove} - class:hover:bg-red-500={!loading.remove} >{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')} {/if} +
@@ -310,6 +353,15 @@ on:click={() => changeSettings('isRegistrationEnabled')} />
+
+ changeSettings('isAPIDebuggingEnabled')} + /> +
{#if browser && $features.beta}