diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index 51fbb0a66..305ea3ad9 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -85,6 +85,6 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Create & publish manifest run: | - docker manifest create coollabsio/coolify:v3.9.1-rc.1 --amend coollabsio/coolify:v3.9.1-rc.1-amd64 --amend coollabsio/coolify:v3.9.1-rc.1-arm64 - docker manifest push coollabsio/coolify:v3.9.1-rc.1 + 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..61f488a8e 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 + 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/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 3b73e4266..902596459 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -26,140 +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 - }); + 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' + }, + } - return reply.status(200).sendFile('index.html'); + }; + + 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'); + }); + } + fastify.register(autoLoad, { + dir: join(__dirname, 'plugins') + }); + fastify.register(autoLoad, { + dir: join(__dirname, 'routes') }); -} -fastify.register(autoLoad, { - dir: join(__dirname, 'plugins') -}); -fastify.register(autoLoad, { - dir: join(__dirname, 'routes') -}); -fastify.register(cookie) -fastify.register(cors); -fastify.addHook('onRequest', async (request, reply) => { - let allowedList = ['coolify:3000']; - const { ipv4, ipv6, fqdn } = await prisma.setting.findFirst({}) + fastify.register(cookie) + fastify.register(cors); + fastify.addHook('onRequest', async (request, reply) => { + let allowedList = ['coolify:3000']; + const { ipv4, ipv6, fqdn } = await prisma.setting.findFirst({}) - ipv4 && allowedList.push(`${ipv4}:3000`); - ipv6 && allowedList.push(ipv6); - fqdn && allowedList.push(getDomain(fqdn)); + 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 (!allowedList.includes(request.headers.host)) { + // console.log('not allowed', request.headers.host) + } + }) + 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(); - const remotes = await prisma.destinationDocker.findMany({ where: { remoteEngine: true, remoteVerified: true } }) - if (remotes.length > 0) { - remotes.forEach(remote => { - allowedList.push(`${remote.remoteIpAddress}:3000`); - }) - } - if (!allowedList.includes(request.headers.host)) { - console.log('not allowed', request.headers.host) - } + const graceful = new Graceful({ brees: [scheduler] }); + graceful.listen(); + + setInterval(async () => { + if (!scheduler.workers.has('deployApplication')) { + scheduler.run('deployApplication'); + } + if (!scheduler.workers.has('infrastructure')) { + scheduler.run('infrastructure'); + } + }, 2000) + + // autoUpdater + setInterval(async () => { + scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:autoUpdater") + }, isDev ? 5000 : 60000 * 15) + + // 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(), + ]) + }); }) -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(); - const graceful = new Graceful({ brees: [scheduler] }); - graceful.listen(); - - setInterval(async () => { - if (!scheduler.workers.has('deployApplication')) { - scheduler.run('deployApplication'); - } - if (!scheduler.workers.has('infrastructure')) { - scheduler.run('infrastructure'); - } - }, 2000) - - // autoUpdater - setInterval(async () => { - scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:autoUpdater") - }, isDev ? 5000 : 60000 * 15) - - // 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(), - ]) -}); 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 8144e41bf..ca70fa512 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.1-rc.1'; +export const version = '3.9.1'; export const isDev = process.env.NODE_ENV === 'development'; const algorithm = 'aes-256-ctr'; 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/ui/src/routes/settings/global.svelte b/apps/ui/src/routes/settings/global.svelte index 219730d9a..98da276be 100644 --- a/apps/ui/src/routes/settings/global.svelte +++ b/apps/ui/src/routes/settings/global.svelte @@ -27,6 +27,7 @@ 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; @@ -75,8 +76,11 @@ if (name === 'isDNSCheckEnabled') { isDNSCheckEnabled = !isDNSCheckEnabled; } - + if (name === 'isAPIDebuggingEnabled') { + isAPIDebuggingEnabled = !isAPIDebuggingEnabled; + } await post(`/settings`, { + isAPIDebuggingEnabled, isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, @@ -310,6 +314,15 @@ on:click={() => changeSettings('isRegistrationEnabled')} /> +
+ changeSettings('isAPIDebuggingEnabled')} + /> +
{#if browser && $features.beta}