fix: update prisma
feat(beta): database branching
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@breejs/ts-worker": "2.0.0",
|
"@breejs/ts-worker": "2.0.0",
|
||||||
"@fastify/autoload": "5.2.0",
|
"@fastify/autoload": "5.3.1",
|
||||||
"@fastify/cookie": "8.1.0",
|
"@fastify/cookie": "8.1.0",
|
||||||
"@fastify/cors": "8.1.0",
|
"@fastify/cors": "8.1.0",
|
||||||
"@fastify/env": "4.1.0",
|
"@fastify/env": "4.1.0",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"@fastify/static": "6.5.0",
|
"@fastify/static": "6.5.0",
|
||||||
"@iarna/toml": "2.2.5",
|
"@iarna/toml": "2.2.5",
|
||||||
"@ladjs/graceful": "3.0.2",
|
"@ladjs/graceful": "3.0.2",
|
||||||
"@prisma/client": "3.15.2",
|
"@prisma/client": "4.3.1",
|
||||||
"axios": "0.27.2",
|
"axios": "0.27.2",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bree": "9.1.2",
|
"bree": "9.1.2",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
"fastify": "4.5.3",
|
"fastify": "4.5.3",
|
||||||
"fastify-plugin": "4.2.1",
|
"fastify-plugin": "4.2.1",
|
||||||
"generate-password": "1.7.0",
|
"generate-password": "1.7.0",
|
||||||
"got": "12.3.1",
|
"got": "12.4.1",
|
||||||
"is-ip": "5.0.0",
|
"is-ip": "5.0.0",
|
||||||
"is-port-reachable": "4.0.0",
|
"is-port-reachable": "4.0.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
@@ -52,20 +52,20 @@
|
|||||||
"unique-names-generator": "4.7.1"
|
"unique-names-generator": "4.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "18.7.13",
|
"@types/node": "18.7.15",
|
||||||
"@types/node-os-utils": "1.3.0",
|
"@types/node-os-utils": "1.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "5.35.1",
|
"@typescript-eslint/eslint-plugin": "5.36.1",
|
||||||
"@typescript-eslint/parser": "5.35.1",
|
"@typescript-eslint/parser": "5.36.1",
|
||||||
"esbuild": "0.15.5",
|
"esbuild": "0.15.7",
|
||||||
"eslint": "8.23.0",
|
"eslint": "8.23.0",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
"eslint-plugin-prettier": "4.2.1",
|
"eslint-plugin-prettier": "4.2.1",
|
||||||
"nodemon": "2.0.19",
|
"nodemon": "2.0.19",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
"prisma": "3.15.2",
|
"prisma": "4.3.1",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"tsconfig-paths": "4.1.0",
|
"tsconfig-paths": "4.1.0",
|
||||||
"typescript": "4.7.4"
|
"typescript": "4.8.2"
|
||||||
},
|
},
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "node prisma/seed.js"
|
"seed": "node prisma/seed.js"
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to alter the column `time` on the `BuildLog` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_BuildLog" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"applicationId" TEXT,
|
||||||
|
"buildId" TEXT NOT NULL,
|
||||||
|
"line" TEXT NOT NULL,
|
||||||
|
"time" BIGINT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_BuildLog" ("applicationId", "buildId", "id", "line", "time") SELECT "applicationId", "buildId", "id", "line", "time" FROM "BuildLog";
|
||||||
|
DROP TABLE "BuildLog";
|
||||||
|
ALTER TABLE "new_BuildLog" RENAME TO "BuildLog";
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
@@ -0,0 +1,20 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "ApplicationConnectedDatabase" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"applicationId" TEXT NOT NULL,
|
||||||
|
"databaseId" TEXT,
|
||||||
|
"hostedDatabaseType" TEXT,
|
||||||
|
"hostedDatabaseHost" TEXT,
|
||||||
|
"hostedDatabasePort" INTEGER,
|
||||||
|
"hostedDatabaseName" TEXT,
|
||||||
|
"hostedDatabaseUser" TEXT,
|
||||||
|
"hostedDatabasePassword" TEXT,
|
||||||
|
"hostedDatabaseDBName" TEXT,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
CONSTRAINT "ApplicationConnectedDatabase_databaseId_fkey" FOREIGN KEY ("databaseId") REFERENCES "Database" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT "ApplicationConnectedDatabase_applicationId_fkey" FOREIGN KEY ("applicationId") REFERENCES "Application" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "ApplicationConnectedDatabase_applicationId_key" ON "ApplicationConnectedDatabase"("applicationId");
|
@@ -117,6 +117,24 @@ model Application {
|
|||||||
settings ApplicationSettings?
|
settings ApplicationSettings?
|
||||||
secrets Secret[]
|
secrets Secret[]
|
||||||
teams Team[]
|
teams Team[]
|
||||||
|
connectedDatabase ApplicationConnectedDatabase?
|
||||||
|
}
|
||||||
|
|
||||||
|
model ApplicationConnectedDatabase {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
applicationId String @unique
|
||||||
|
databaseId String?
|
||||||
|
hostedDatabaseType String?
|
||||||
|
hostedDatabaseHost String?
|
||||||
|
hostedDatabasePort Int?
|
||||||
|
hostedDatabaseName String?
|
||||||
|
hostedDatabaseUser String?
|
||||||
|
hostedDatabasePassword String?
|
||||||
|
hostedDatabaseDBName String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
database Database? @relation(fields: [databaseId], references: [id])
|
||||||
|
application Application @relation(fields: [applicationId], references: [id])
|
||||||
}
|
}
|
||||||
|
|
||||||
model ApplicationSettings {
|
model ApplicationSettings {
|
||||||
@@ -187,7 +205,7 @@ model BuildLog {
|
|||||||
applicationId String?
|
applicationId String?
|
||||||
buildId String
|
buildId String
|
||||||
line String
|
line String
|
||||||
time Int
|
time BigInt
|
||||||
}
|
}
|
||||||
|
|
||||||
model Build {
|
model Build {
|
||||||
@@ -308,6 +326,7 @@ model Database {
|
|||||||
destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id])
|
destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id])
|
||||||
settings DatabaseSettings?
|
settings DatabaseSettings?
|
||||||
teams Team[]
|
teams Team[]
|
||||||
|
applicationConnectedDatabase ApplicationConnectedDatabase[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model DatabaseSettings {
|
model DatabaseSettings {
|
||||||
|
@@ -156,7 +156,8 @@ export async function getApplicationFromDB(id: string, teamId: string) {
|
|||||||
settings: true,
|
settings: true,
|
||||||
gitSource: { include: { githubApp: true, gitlabApp: true } },
|
gitSource: { include: { githubApp: true, gitlabApp: true } },
|
||||||
secrets: true,
|
secrets: true,
|
||||||
persistentStorage: true
|
persistentStorage: true,
|
||||||
|
connectedDatabase: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!application) {
|
if (!application) {
|
||||||
@@ -190,7 +191,8 @@ export async function getApplicationFromDBWebhook(projectId: number, branch: str
|
|||||||
settings: true,
|
settings: true,
|
||||||
gitSource: { include: { githubApp: true, gitlabApp: true } },
|
gitSource: { include: { githubApp: true, gitlabApp: true } },
|
||||||
secrets: true,
|
secrets: true,
|
||||||
persistentStorage: true
|
persistentStorage: true,
|
||||||
|
connectedDatabase: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (applications.length === 0) {
|
if (applications.length === 0) {
|
||||||
@@ -242,7 +244,8 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
|||||||
denoOptions,
|
denoOptions,
|
||||||
baseImage,
|
baseImage,
|
||||||
baseBuildImage,
|
baseBuildImage,
|
||||||
deploymentType
|
deploymentType,
|
||||||
|
baseDatabaseBranch
|
||||||
} = request.body
|
} = request.body
|
||||||
if (port) port = Number(port);
|
if (port) port = Number(port);
|
||||||
if (exposePort) {
|
if (exposePort) {
|
||||||
@@ -263,6 +266,25 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
|||||||
dockerFileLocation,
|
dockerFileLocation,
|
||||||
denoMainFile
|
denoMainFile
|
||||||
});
|
});
|
||||||
|
if (baseDatabaseBranch) {
|
||||||
|
await prisma.application.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
fqdn,
|
||||||
|
exposePort,
|
||||||
|
pythonWSGI,
|
||||||
|
pythonModule,
|
||||||
|
pythonVariable,
|
||||||
|
denoOptions,
|
||||||
|
baseImage,
|
||||||
|
baseBuildImage,
|
||||||
|
deploymentType,
|
||||||
|
...defaultConfiguration,
|
||||||
|
connectedDatabase: { update: { hostedDatabaseDBName: baseDatabaseBranch } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
@@ -279,6 +301,8 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
|||||||
...defaultConfiguration
|
...defaultConfiguration
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return reply.code(201).send();
|
return reply.code(201).send();
|
||||||
} catch ({ status, message }) {
|
} catch ({ status, message }) {
|
||||||
return errorHandler({ status, message })
|
return errorHandler({ status, message })
|
||||||
@@ -289,7 +313,7 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
|||||||
export async function saveApplicationSettings(request: FastifyRequest<SaveApplicationSettings>, reply: FastifyReply) {
|
export async function saveApplicationSettings(request: FastifyRequest<SaveApplicationSettings>, reply: FastifyReply) {
|
||||||
try {
|
try {
|
||||||
const { id } = request.params
|
const { id } = request.params
|
||||||
const { debug, previews, dualCerts, autodeploy, branch, projectId, isBot } = request.body
|
const { debug, previews, dualCerts, autodeploy, branch, projectId, isBot, isDBBranching } = request.body
|
||||||
// const isDouble = await checkDoubleBranch(branch, projectId);
|
// const isDouble = await checkDoubleBranch(branch, projectId);
|
||||||
// if (isDouble && autodeploy) {
|
// if (isDouble && autodeploy) {
|
||||||
// await prisma.applicationSettings.updateMany({ where: { application: { branch, projectId } }, data: { autodeploy: false } })
|
// await prisma.applicationSettings.updateMany({ where: { application: { branch, projectId } }, data: { autodeploy: false } })
|
||||||
@@ -297,7 +321,7 @@ export async function saveApplicationSettings(request: FastifyRequest<SaveApplic
|
|||||||
// }
|
// }
|
||||||
await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { fqdn: isBot ? null : undefined, settings: { update: { debug, previews, dualCerts, autodeploy, isBot } } },
|
data: { fqdn: isBot ? null : undefined, settings: { update: { debug, previews, dualCerts, autodeploy, isBot, isDBBranching } } },
|
||||||
include: { destinationDocker: true }
|
include: { destinationDocker: true }
|
||||||
});
|
});
|
||||||
return reply.code(201).send();
|
return reply.code(201).send();
|
||||||
@@ -478,6 +502,7 @@ export async function deleteApplication(request: FastifyRequest<DeleteApplicatio
|
|||||||
await prisma.build.deleteMany({ where: { applicationId: id } });
|
await prisma.build.deleteMany({ where: { applicationId: id } });
|
||||||
await prisma.secret.deleteMany({ where: { applicationId: id } });
|
await prisma.secret.deleteMany({ where: { applicationId: id } });
|
||||||
await prisma.applicationPersistentStorage.deleteMany({ where: { applicationId: id } });
|
await prisma.applicationPersistentStorage.deleteMany({ where: { applicationId: id } });
|
||||||
|
await prisma.applicationConnectedDatabase.deleteMany({ where: { applicationId: id } });
|
||||||
if (teamId === '0') {
|
if (teamId === '0') {
|
||||||
await prisma.application.deleteMany({ where: { id } });
|
await prisma.application.deleteMany({ where: { id } });
|
||||||
} else {
|
} else {
|
||||||
@@ -738,6 +763,17 @@ export async function saveBuildPack(request, reply) {
|
|||||||
return errorHandler({ status, message })
|
return errorHandler({ status, message })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export async function saveConnectedDatabase(request, reply) {
|
||||||
|
try {
|
||||||
|
const { id } = request.params
|
||||||
|
const { databaseId, type } = request.body
|
||||||
|
console.log({ databaseId, type })
|
||||||
|
await prisma.application.update({ where: { id }, data: { connectedDatabase: { upsert: { create: { database: { connect: { id: databaseId } }, hostedDatabaseType: type }, update: { database: { connect: { id: databaseId } }, hostedDatabaseType: type } } } } })
|
||||||
|
return reply.code(201).send()
|
||||||
|
} catch ({ status, message }) {
|
||||||
|
return errorHandler({ status, message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSecrets(request: FastifyRequest<OnlyId>) {
|
export async function getSecrets(request: FastifyRequest<OnlyId>) {
|
||||||
try {
|
try {
|
||||||
@@ -986,11 +1022,13 @@ export async function getBuildIdLogs(request: FastifyRequest<GetBuildIdLogs>) {
|
|||||||
where: { buildId, time: { gt: sequence } },
|
where: { buildId, time: { gt: sequence } },
|
||||||
orderBy: { time: 'asc' }
|
orderBy: { time: 'asc' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await prisma.build.findFirst({ where: { id: buildId } });
|
const data = await prisma.build.findFirst({ where: { id: buildId } });
|
||||||
const createdAt = day(data.createdAt).utc();
|
const createdAt = day(data.createdAt).utc();
|
||||||
return {
|
return {
|
||||||
logs,
|
logs: logs.map(log => {
|
||||||
|
log.time = Number(log.time)
|
||||||
|
return log
|
||||||
|
}),
|
||||||
took: day().diff(createdAt) / 1000,
|
took: day().diff(createdAt) / 1000,
|
||||||
status: data?.status || 'queued'
|
status: data?.status || 'queued'
|
||||||
}
|
}
|
||||||
@@ -1067,3 +1105,58 @@ export async function cancelDeployment(request: FastifyRequest<CancelDeployment>
|
|||||||
return errorHandler({ status, message })
|
return errorHandler({ status, message })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function createdBranchDatabase(database: any, baseDatabaseBranch: string, pullmergeRequestId: string) {
|
||||||
|
try {
|
||||||
|
if (!baseDatabaseBranch) return
|
||||||
|
const { id, type, destinationDockerId, rootUser, rootUserPassword, dbUser } = database;
|
||||||
|
if (destinationDockerId) {
|
||||||
|
if (type === 'postgresql') {
|
||||||
|
const decryptedRootUserPassword = decrypt(rootUserPassword);
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} pg_dump -d "postgresql://postgres:${decryptedRootUserPassword}@${id}:5432/${baseDatabaseBranch}" --encoding=UTF8 --schema-only -f /tmp/${baseDatabaseBranch}.dump`
|
||||||
|
})
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "CREATE DATABASE branch_${pullmergeRequestId}"`
|
||||||
|
})
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} psql -d "postgresql://postgres:${decryptedRootUserPassword}@${id}:5432/branch_${pullmergeRequestId}" -f /tmp/${baseDatabaseBranch}.dump`
|
||||||
|
})
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "ALTER DATABASE branch_${pullmergeRequestId} OWNER TO ${dbUser}"`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch ({ status, message }) {
|
||||||
|
return errorHandler({ status, message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function removeBranchDatabase(database: any, pullmergeRequestId: string) {
|
||||||
|
try {
|
||||||
|
const { id, type, destinationDockerId, rootUser, rootUserPassword } = database;
|
||||||
|
if (destinationDockerId) {
|
||||||
|
if (type === 'postgresql') {
|
||||||
|
const decryptedRootUserPassword = decrypt(rootUserPassword);
|
||||||
|
// Terminate all connections to the database
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'branch_${pullmergeRequestId}' AND pid <> pg_backend_pid();"`
|
||||||
|
})
|
||||||
|
|
||||||
|
await executeDockerCmd({
|
||||||
|
dockerId: destinationDockerId,
|
||||||
|
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "DROP DATABASE branch_${pullmergeRequestId}"`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch ({ status, message }) {
|
||||||
|
return errorHandler({ status, message })
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
import { FastifyPluginAsync } from 'fastify';
|
import { FastifyPluginAsync } from 'fastify';
|
||||||
import { OnlyId } from '../../../../types';
|
import { OnlyId } from '../../../../types';
|
||||||
import { cancelDeployment, checkDNS, checkDomain, checkRepository, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildLogs, getBuildPack, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getSecrets, getStorages, getUsage, listApplications, newApplication, restartApplication, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication } from './handlers';
|
import { cancelDeployment, checkDNS, checkDomain, checkRepository, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildLogs, getBuildPack, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getSecrets, getStorages, getUsage, listApplications, newApplication, restartApplication, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveConnectedDatabase, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication } from './handlers';
|
||||||
|
|
||||||
import type { CancelDeployment, CheckDNS, CheckDomain, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, DeployApplication, GetApplicationLogs, GetBuildIdLogs, GetBuildLogs, GetImages, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage, StopPreviewApplication } from './types';
|
import type { CancelDeployment, CheckDNS, CheckDomain, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, DeployApplication, GetApplicationLogs, GetBuildIdLogs, GetBuildLogs, GetImages, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage, StopPreviewApplication } from './types';
|
||||||
|
|
||||||
@@ -55,6 +55,8 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
|||||||
fastify.get('/:id/configuration/buildpack', async (request) => await getBuildPack(request));
|
fastify.get('/:id/configuration/buildpack', async (request) => await getBuildPack(request));
|
||||||
fastify.post('/:id/configuration/buildpack', async (request, reply) => await saveBuildPack(request, reply));
|
fastify.post('/:id/configuration/buildpack', async (request, reply) => await saveBuildPack(request, reply));
|
||||||
|
|
||||||
|
fastify.post('/:id/configuration/database', async (request, reply) => await saveConnectedDatabase(request, reply));
|
||||||
|
|
||||||
fastify.get<OnlyId>('/:id/configuration/sshkey', async (request) => await getGitLabSSHKey(request));
|
fastify.get<OnlyId>('/:id/configuration/sshkey', async (request) => await getGitLabSSHKey(request));
|
||||||
fastify.post<OnlyId>('/:id/configuration/sshkey', async (request, reply) => await saveGitLabSSHKey(request, reply));
|
fastify.post<OnlyId>('/:id/configuration/sshkey', async (request, reply) => await saveGitLabSSHKey(request, reply));
|
||||||
|
|
||||||
|
@@ -20,12 +20,13 @@ export interface SaveApplication extends OnlyId {
|
|||||||
denoOptions: string,
|
denoOptions: string,
|
||||||
baseImage: string,
|
baseImage: string,
|
||||||
baseBuildImage: string,
|
baseBuildImage: string,
|
||||||
deploymentType: string
|
deploymentType: string,
|
||||||
|
baseDatabaseBranch: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export interface SaveApplicationSettings extends OnlyId {
|
export interface SaveApplicationSettings extends OnlyId {
|
||||||
Querystring: { domain: string; };
|
Querystring: { domain: string; };
|
||||||
Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; isBot: boolean; };
|
Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; isBot: boolean; isDBBranching: boolean };
|
||||||
}
|
}
|
||||||
export interface DeleteApplication extends OnlyId {
|
export interface DeleteApplication extends OnlyId {
|
||||||
Querystring: { domain: string; };
|
Querystring: { domain: string; };
|
||||||
|
@@ -3,8 +3,7 @@ import cuid from "cuid";
|
|||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import { encrypt, errorHandler, getUIUrl, isDev, prisma } from "../../../lib/common";
|
import { encrypt, errorHandler, getUIUrl, isDev, prisma } from "../../../lib/common";
|
||||||
import { checkContainer, removeContainer } from "../../../lib/docker";
|
import { checkContainer, removeContainer } from "../../../lib/docker";
|
||||||
import { scheduler } from "../../../lib/scheduler";
|
import { createdBranchDatabase, getApplicationFromDBWebhook, removeBranchDatabase } from "../../api/v1/applications/handlers";
|
||||||
import { getApplicationFromDBWebhook } from "../../api/v1/applications/handlers";
|
|
||||||
|
|
||||||
import type { FastifyReply, FastifyRequest } from "fastify";
|
import type { FastifyReply, FastifyRequest } from "fastify";
|
||||||
import type { GitHubEvents, InstallGithub } from "./types";
|
import type { GitHubEvents, InstallGithub } from "./types";
|
||||||
@@ -67,7 +66,6 @@ export async function configureGitHubApp(request, reply) {
|
|||||||
}
|
}
|
||||||
export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promise<any> {
|
export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promise<any> {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const allowedGithubEvents = ['push', 'pull_request'];
|
const allowedGithubEvents = ['push', 'pull_request'];
|
||||||
const allowedActions = ['opened', 'reopened', 'synchronize', 'closed'];
|
const allowedActions = ['opened', 'reopened', 'synchronize', 'closed'];
|
||||||
const githubEvent = request.headers['x-github-event']?.toString().toLowerCase();
|
const githubEvent = request.headers['x-github-event']?.toString().toLowerCase();
|
||||||
@@ -133,8 +131,6 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi
|
|||||||
where: { id: application.id },
|
where: { id: application.id },
|
||||||
data: { updatedAt: new Date() }
|
data: { updatedAt: new Date() }
|
||||||
});
|
});
|
||||||
console.log(application.id)
|
|
||||||
|
|
||||||
await prisma.build.create({
|
await prisma.build.create({
|
||||||
data: {
|
data: {
|
||||||
id: buildId,
|
id: buildId,
|
||||||
@@ -178,6 +174,16 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi
|
|||||||
where: { id: application.id },
|
where: { id: application.id },
|
||||||
data: { updatedAt: new Date() }
|
data: { updatedAt: new Date() }
|
||||||
});
|
});
|
||||||
|
if (application.connectedDatabase && pullmergeRequestAction === 'opened' || pullmergeRequestAction === 'reopened') {
|
||||||
|
// Coolify hosted database
|
||||||
|
if (application.connectedDatabase.databaseId) {
|
||||||
|
const databaseId = application.connectedDatabase.databaseId;
|
||||||
|
const database = await prisma.database.findUnique({ where: { id: databaseId } });
|
||||||
|
if (database) {
|
||||||
|
await createdBranchDatabase(database, application.connectedDatabase.hostedDatabaseDBName, pullmergeRequestId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
await prisma.build.create({
|
await prisma.build.create({
|
||||||
data: {
|
data: {
|
||||||
id: buildId,
|
id: buildId,
|
||||||
@@ -197,9 +203,17 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi
|
|||||||
} else if (pullmergeRequestAction === 'closed') {
|
} else if (pullmergeRequestAction === 'closed') {
|
||||||
if (application.destinationDockerId) {
|
if (application.destinationDockerId) {
|
||||||
const id = `${application.id}-${pullmergeRequestId}`;
|
const id = `${application.id}-${pullmergeRequestId}`;
|
||||||
|
try {
|
||||||
await removeContainer({ id, dockerId: application.destinationDocker.id });
|
await removeContainer({ id, dockerId: application.destinationDocker.id });
|
||||||
|
} catch (error) { }
|
||||||
|
}
|
||||||
|
if (application.connectedDatabase.databaseId) {
|
||||||
|
const databaseId = application.connectedDatabase.databaseId;
|
||||||
|
const database = await prisma.database.findUnique({ where: { id: databaseId } });
|
||||||
|
if (database) {
|
||||||
|
await removeBranchDatabase(database, pullmergeRequestId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,11 @@
|
|||||||
"@popperjs/core": "2.11.6",
|
"@popperjs/core": "2.11.6",
|
||||||
"@sveltejs/kit": "1.0.0-next.405",
|
"@sveltejs/kit": "1.0.0-next.405",
|
||||||
"@types/js-cookie": "3.0.2",
|
"@types/js-cookie": "3.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "5.35.1",
|
"@typescript-eslint/eslint-plugin": "5.36.1",
|
||||||
"@typescript-eslint/parser": "5.35.1",
|
"@typescript-eslint/parser": "5.36.1",
|
||||||
"autoprefixer": "10.4.8",
|
"autoprefixer": "10.4.8",
|
||||||
"classnames": "2.3.1",
|
"classnames": "2.3.1",
|
||||||
"eslint": "8.22.0",
|
"eslint": "8.23.0",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
"eslint-plugin-svelte3": "4.0.0",
|
"eslint-plugin-svelte3": "4.0.0",
|
||||||
"flowbite": "1.5.2",
|
"flowbite": "1.5.2",
|
||||||
@@ -31,21 +31,21 @@
|
|||||||
"postcss": "8.4.16",
|
"postcss": "8.4.16",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
"prettier-plugin-svelte": "2.7.0",
|
"prettier-plugin-svelte": "2.7.0",
|
||||||
"svelte": "3.49.0",
|
"svelte": "3.50.0",
|
||||||
"svelte-check": "2.8.1",
|
"svelte-check": "2.9.0",
|
||||||
"svelte-preprocess": "4.10.7",
|
"svelte-preprocess": "4.10.7",
|
||||||
"tailwindcss": "3.1.8",
|
"tailwindcss": "3.1.8",
|
||||||
"tailwindcss-scrollbar": "0.1.0",
|
"tailwindcss-scrollbar": "0.1.0",
|
||||||
"tslib": "2.4.0",
|
"tslib": "2.4.0",
|
||||||
"typescript": "4.7.4",
|
"typescript": "4.8.2",
|
||||||
"vite": "3.0.5"
|
"vite": "3.1.0"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-static": "1.0.0-next.39",
|
"@sveltejs/adapter-static": "1.0.0-next.39",
|
||||||
"@tailwindcss/typography": "^0.5.4",
|
"@tailwindcss/typography": "^0.5.7",
|
||||||
"cuid": "2.1.8",
|
"cuid": "2.1.8",
|
||||||
"daisyui": "2.24.0",
|
"daisyui": "2.24.2",
|
||||||
"js-cookie": "3.0.1",
|
"js-cookie": "3.0.1",
|
||||||
"p-limit": "4.0.0",
|
"p-limit": "4.0.0",
|
||||||
"svelte-select": "4.4.7",
|
"svelte-select": "4.4.7",
|
||||||
|
@@ -0,0 +1,162 @@
|
|||||||
|
<script context="module" lang="ts">
|
||||||
|
import type { Load } from '@sveltejs/kit';
|
||||||
|
export const load: Load = async () => {
|
||||||
|
try {
|
||||||
|
const response = await get(`/databases`);
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...response
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
return {
|
||||||
|
status: 500,
|
||||||
|
error: new Error(error)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export let databases: any = [];
|
||||||
|
import { get, post } from '$lib/api';
|
||||||
|
import { t } from '$lib/translations';
|
||||||
|
import { appSession } from '$lib/store';
|
||||||
|
import DatabaseIcons from '$lib/components/svg/databases/DatabaseIcons.svelte';
|
||||||
|
import { errorNotification } from '$lib/common';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
|
const from = $page.url.searchParams.get('from');
|
||||||
|
|
||||||
|
let remoteDatabase = {
|
||||||
|
name: null,
|
||||||
|
type: null,
|
||||||
|
host: null,
|
||||||
|
port: null,
|
||||||
|
user: null,
|
||||||
|
password: null,
|
||||||
|
database: null
|
||||||
|
};
|
||||||
|
|
||||||
|
const ownDatabases = databases.filter((database: any) => {
|
||||||
|
if (database.teams[0].id === $appSession.teamId) {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const otherDatabases = databases.filter((database: any) => {
|
||||||
|
if (database.teams[0].id !== $appSession.teamId) {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function addCoolifyDatabase(database: any) {
|
||||||
|
try {
|
||||||
|
await post(`/applications/${$page.params.id}/configuration/database`, {
|
||||||
|
databaseId: database.id,
|
||||||
|
type: database.type
|
||||||
|
});
|
||||||
|
return window.location.assign(from || `/applications/${$page.params.id}/`);
|
||||||
|
} catch (error) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex space-x-1 p-6 font-bold">
|
||||||
|
<div class="mr-4 text-2xl tracking-tight">Select a Database</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-col justify-center mt-10 pb-12 sm:pb-16">
|
||||||
|
{#if !databases || ownDatabases.length === 0}
|
||||||
|
<div class="flex-col">
|
||||||
|
<div class="text-center text-xl font-bold">{$t('database.no_databases_found')}</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if ownDatabases.length > 0 || otherDatabases.length > 0}
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex flex-col flex-wrap justify-center px-2 md:flex-row">
|
||||||
|
{#each ownDatabases as database}
|
||||||
|
<button on:click={() => addCoolifyDatabase(database)} class="p-2 no-underline">
|
||||||
|
<div class="box-selection group relative hover:bg-purple-600">
|
||||||
|
<DatabaseIcons type={database.type} isAbsolute={true} />
|
||||||
|
<div class="truncate text-center text-xl font-bold">
|
||||||
|
{database.name}
|
||||||
|
</div>
|
||||||
|
{#if $appSession.teamId === '0' && otherDatabases.length > 0}
|
||||||
|
<div class="truncate text-center">{database.teams[0].name}</div>
|
||||||
|
{/if}
|
||||||
|
{#if database.destinationDocker?.name}
|
||||||
|
<div class="truncate text-center">{database.destinationDocker.name}</div>
|
||||||
|
{/if}
|
||||||
|
{#if !database.type}
|
||||||
|
<div class="truncate text-center font-bold text-red-500 group-hover:text-white">
|
||||||
|
{$t('application.configuration.configuration_missing')}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{#if otherDatabases.length > 0 && $appSession.teamId === '0'}
|
||||||
|
<div class="px-6 pb-5 pt-10 text-2xl font-bold text-center">Other Databases</div>
|
||||||
|
<div class="flex flex-col flex-wrap justify-center px-2 md:flex-row">
|
||||||
|
{#each otherDatabases as database}
|
||||||
|
<a href="/databases/{database.id}" class="p-2 no-underline">
|
||||||
|
<div class="box-selection group relative hover:bg-purple-600">
|
||||||
|
<DatabaseIcons type={database.type} isAbsolute={true} />
|
||||||
|
<div class="truncate text-center text-xl font-bold">
|
||||||
|
{database.name}
|
||||||
|
</div>
|
||||||
|
{#if $appSession.teamId === '0'}
|
||||||
|
<div class="truncate text-center">{database.teams[0].name}</div>
|
||||||
|
{/if}
|
||||||
|
{#if !database.type}
|
||||||
|
<div class="truncate text-center font-bold text-red-500 group-hover:text-white">
|
||||||
|
Configuration missing
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="text-center truncate">{database.type}</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="mx-auto max-w-4xl p-6">
|
||||||
|
<div class="grid grid-flow-row gap-2 px-10">
|
||||||
|
<div class="font-bold text-xl tracking-tight">Connect a Hosted / Remote Database</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="name" class="text-base font-bold text-stone-100">Name</label>
|
||||||
|
<input name="name" id="name" required bind:value={remoteDatabase.name} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="type" class="text-base font-bold text-stone-100">Type</label>
|
||||||
|
<input name="type" id="type" required bind:value={remoteDatabase.type} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="host" class="text-base font-bold text-stone-100">Host</label>
|
||||||
|
<input name="host" id="host" required bind:value={remoteDatabase.host} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="port" class="text-base font-bold text-stone-100">Port</label>
|
||||||
|
<input name="port" id="port" required bind:value={remoteDatabase.port} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="user" class="text-base font-bold text-stone-100">User</label>
|
||||||
|
<input name="user" id="user" required bind:value={remoteDatabase.user} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="password" class="text-base font-bold text-stone-100">Password</label>
|
||||||
|
<input name="password" id="password" required bind:value={remoteDatabase.password} />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-4">
|
||||||
|
<label for="database" class="text-base font-bold text-stone-100">Database Name</label>
|
||||||
|
<input name="database" id="database" required bind:value={remoteDatabase.database} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -31,7 +31,6 @@
|
|||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import Select from 'svelte-select';
|
import Select from 'svelte-select';
|
||||||
|
|
||||||
import { get, post } from '$lib/api';
|
import { get, post } from '$lib/api';
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
import {
|
import {
|
||||||
@@ -40,13 +39,15 @@
|
|||||||
checkIfDeploymentEnabledApplications,
|
checkIfDeploymentEnabledApplications,
|
||||||
setLocation,
|
setLocation,
|
||||||
status,
|
status,
|
||||||
isDeploymentEnabled
|
isDeploymentEnabled,
|
||||||
|
features
|
||||||
} from '$lib/store';
|
} from '$lib/store';
|
||||||
import { t } from '$lib/translations';
|
import { t } from '$lib/translations';
|
||||||
import { errorNotification, getDomain, notNodeDeployments, staticDeployments } from '$lib/common';
|
import { errorNotification, getDomain, notNodeDeployments, staticDeployments } from '$lib/common';
|
||||||
import Setting from '$lib/components/Setting.svelte';
|
import Setting from '$lib/components/Setting.svelte';
|
||||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||||
import Explainer from '$lib/components/Explainer.svelte';
|
import Explainer from '$lib/components/Explainer.svelte';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
let isBot = application.settings.isBot;
|
let isBot = application.settings.isBot;
|
||||||
let isDBBranching = application.settings.isDBBranching;
|
let isDBBranching = application.settings.isDBBranching;
|
||||||
|
|
||||||
|
let baseDatabaseBranch: any = application?.connectedDatabase?.hostedDatabaseDBName || null;
|
||||||
let nonWWWDomain = application.fqdn && getDomain(application.fqdn).replace(/^www\./, '');
|
let nonWWWDomain = application.fqdn && getDomain(application.fqdn).replace(/^www\./, '');
|
||||||
let isNonWWWDomainOK = false;
|
let isNonWWWDomainOK = false;
|
||||||
let isWWWDomainOK = false;
|
let isWWWDomainOK = false;
|
||||||
@@ -172,7 +174,6 @@
|
|||||||
}
|
}
|
||||||
if (name === 'isDBBranching') {
|
if (name === 'isDBBranching') {
|
||||||
isDBBranching = !isDBBranching;
|
isDBBranching = !isDBBranching;
|
||||||
application.settings.isDBBranching = isDBBranching;
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await post(`/applications/${id}/settings`, {
|
await post(`/applications/${id}/settings`, {
|
||||||
@@ -181,6 +182,7 @@
|
|||||||
dualCerts,
|
dualCerts,
|
||||||
isBot,
|
isBot,
|
||||||
autodeploy,
|
autodeploy,
|
||||||
|
isDBBranching,
|
||||||
branch: application.branch,
|
branch: application.branch,
|
||||||
projectId: application.projectId
|
projectId: application.projectId
|
||||||
});
|
});
|
||||||
@@ -204,6 +206,9 @@
|
|||||||
if (name === 'isBot') {
|
if (name === 'isBot') {
|
||||||
isBot = !isBot;
|
isBot = !isBot;
|
||||||
}
|
}
|
||||||
|
if (name === 'isDBBranching') {
|
||||||
|
isDBBranching = !isDBBranching;
|
||||||
|
}
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
||||||
@@ -223,7 +228,7 @@
|
|||||||
dualCerts,
|
dualCerts,
|
||||||
exposePort: application.exposePort
|
exposePort: application.exposePort
|
||||||
}));
|
}));
|
||||||
await post(`/applications/${id}`, { ...application });
|
await post(`/applications/${id}`, { ...application, baseDatabaseBranch });
|
||||||
setLocation(application, settings);
|
setLocation(application, settings);
|
||||||
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
||||||
|
|
||||||
@@ -525,6 +530,46 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $features.beta}
|
||||||
|
{#if !application.settings.isBot && !application.settings.isPublicRepository}
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<Setting
|
||||||
|
id="isDBBranching"
|
||||||
|
isCenter={false}
|
||||||
|
bind:setting={isDBBranching}
|
||||||
|
on:click={() => changeSettings('isDBBranching')}
|
||||||
|
title="Enable DB Branching"
|
||||||
|
description="Enable DB Branching"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{#if isDBBranching}
|
||||||
|
<button
|
||||||
|
on:click|stopPropagation|preventDefault={() =>
|
||||||
|
goto(`/applications/${id}/configuration/database`)}
|
||||||
|
class="btn btn-sm">Configure Connected Database</button
|
||||||
|
>
|
||||||
|
{#if application.connectedDatabase}
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<label for="baseImage" class="text-base font-bold text-stone-100"
|
||||||
|
>Base Database
|
||||||
|
<Explainer
|
||||||
|
explanation={'The name of the database that will be used as base when branching.'}
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
name="baseDatabaseBranch"
|
||||||
|
required
|
||||||
|
id="baseDatabaseBranch"
|
||||||
|
bind:value={baseDatabaseBranch}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="text-center bg-green-600 rounded">
|
||||||
|
Connected to {application.connectedDatabase.databaseId}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-1 py-5 font-bold">
|
<div class="flex space-x-1 py-5 font-bold">
|
||||||
<div class="title">{$t('application.application')}</div>
|
<div class="title">{$t('application.application')}</div>
|
||||||
@@ -846,16 +891,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="grid grid-cols-2 items-center">
|
|
||||||
<Setting
|
|
||||||
id="isDBBranching"
|
|
||||||
isCenter={false}
|
|
||||||
bind:setting={isDBBranching}
|
|
||||||
on:click={() => changeSettings('isDBBranching')}
|
|
||||||
title="Enable DB Branching"
|
|
||||||
description="Enable DB Branching"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-2 items-center">
|
<div class="grid grid-cols-2 items-center">
|
||||||
<Setting
|
<Setting
|
||||||
id="debug"
|
id="debug"
|
||||||
|
864
pnpm-lock.yaml
generated
864
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user