v1.0.16 (#51)
This commit is contained in:
		| @@ -306,7 +306,7 @@ | ||||
| 				> | ||||
| 			{:else} | ||||
| 				<button | ||||
| 					class="opacity-50 tracking-tight font-bold text-xs rounded px-2  cursor-not-allowed" | ||||
| 					class="opacity-50 tracking-tight font-bold text-xs rounded px-2 cursor-not-allowed" | ||||
| 					disabled={upgradeDisabled}>Upgrading. It could take a while, please wait...</button | ||||
| 				> | ||||
| 			{/if} | ||||
|   | ||||
| @@ -1,32 +1,18 @@ | ||||
| import { setDefaultConfiguration } from '$lib/api/applications/configuration'; | ||||
| import { saveServerLog } from '$lib/api/applications/logging'; | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import Configuration from '$models/Configuration'; | ||||
| import type { Request } from '@sveltejs/kit'; | ||||
|  | ||||
| export async function post(request: Request) { | ||||
| 	try { | ||||
| 		const { DOMAIN } = process.env; | ||||
| 		const configuration = setDefaultConfiguration(request.body); | ||||
|  | ||||
| 		const services = (await docker.engine.listServices()).filter( | ||||
| 			(r) => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application' | ||||
| 		); | ||||
| 		let foundDomain = false; | ||||
|  | ||||
| 		for (const service of services) { | ||||
| 			const running = JSON.parse(service.Spec.Labels.configuration); | ||||
| 			if (running) { | ||||
| 				if ( | ||||
| 					running.publish.domain === configuration.publish.domain && | ||||
| 					running.repository.id !== configuration.repository.id && | ||||
| 					running.publish.path === configuration.publish.path | ||||
| 				) { | ||||
| 					foundDomain = true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (DOMAIN === configuration.publish.domain) foundDomain = true; | ||||
| 		if (foundDomain) { | ||||
| 		const configurationFound = await Configuration.find({ | ||||
| 			'repository.id': { '$ne': configuration.repository.id }, | ||||
| 			'publish.domain': configuration.publish.domain | ||||
| 		}).select('-_id -__v -createdAt -updatedAt') | ||||
| 		if (configurationFound.length > 0 || configuration.publish.domain === DOMAIN) { | ||||
| 			return { | ||||
| 				status: 200, | ||||
| 				body: { | ||||
| @@ -38,7 +24,7 @@ export async function post(request: Request) { | ||||
| 		return { | ||||
| 			status: 200, | ||||
| 			body: { success: true, message: 'OK' } | ||||
| 		}; | ||||
| 		} | ||||
| 	} catch (error) { | ||||
| 		await saveServerLog(error); | ||||
| 		return { | ||||
|   | ||||
| @@ -5,17 +5,17 @@ import type { Request } from '@sveltejs/kit'; | ||||
| export async function post(request: Request) { | ||||
| 	const { name, organization, branch }: any = request.body || {}; | ||||
| 	if (name && organization && branch) { | ||||
| 		const configurationFound = await Configuration.findOne({ | ||||
| 		const configurationFound = await Configuration.find({ | ||||
| 			'repository.name': name, | ||||
| 			'repository.organization': organization, | ||||
| 			'repository.branch': branch, | ||||
| 		}).lean() | ||||
| 			'repository.branch': branch | ||||
| 		}).select('-_id -__v -createdAt -updatedAt') | ||||
| 
 | ||||
| 		if (configurationFound) { | ||||
| 			return { | ||||
| 				status: 200, | ||||
| 				body: { | ||||
| 					success: true, | ||||
| 					...configurationFound | ||||
| 					configuration: [...configurationFound] | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| @@ -46,6 +46,7 @@ export async function post(request: Request) { | ||||
| 			} | ||||
| 			return null; | ||||
| 		}); | ||||
| 
 | ||||
| 		if (found) { | ||||
| 			return { | ||||
| 				status: 200, | ||||
							
								
								
									
										62
									
								
								src/routes/api/v1/application/config/previewDeployment.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/routes/api/v1/application/config/previewDeployment.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| import { updateServiceLabels } from '$lib/api/applications/configuration'; | ||||
| import { execShellAsync } from '$lib/api/common'; | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import ApplicationLog from '$models/ApplicationLog'; | ||||
| import Configuration from '$models/Configuration'; | ||||
| import Deployment from '$models/Deployment'; | ||||
| import type { Request } from '@sveltejs/kit'; | ||||
|  | ||||
| export async function post(request: Request) { | ||||
| 	const { name, organization, branch, isPreviewDeploymentEnabled }: any = request.body || {}; | ||||
| 	if (name && organization && branch) { | ||||
| 		const configuration = await Configuration.findOneAndUpdate({ | ||||
| 			'repository.name': name, | ||||
| 			'repository.organization': organization, | ||||
| 			'repository.branch': branch | ||||
| 		}, { $set: { 'general.isPreviewDeploymentEnabled': isPreviewDeploymentEnabled, 'general.pullRequest': 0 } }, { new: true }).select('-_id -__v -createdAt -updatedAt') | ||||
| 		if (!isPreviewDeploymentEnabled) { | ||||
| 			const found = await Configuration.find({ | ||||
| 				'repository.name': name, | ||||
| 				'repository.organization': organization, | ||||
| 				'repository.branch': branch, | ||||
| 				'general.pullRequest': { '$ne': 0 } | ||||
| 			}) | ||||
| 			for (const prDeployment of found) { | ||||
| 				await Configuration.findOneAndRemove({ | ||||
| 					'repository.name': name, | ||||
| 					'repository.organization': organization, | ||||
| 					'repository.branch': branch, | ||||
| 					'publish.domain': prDeployment.publish.domain | ||||
| 				}) | ||||
| 				const deploys = await Deployment.find({ organization, branch, name, domain: prDeployment.publish.domain }); | ||||
| 				for (const deploy of deploys) { | ||||
| 					await ApplicationLog.deleteMany({ deployId: deploy.deployId }); | ||||
| 					await Deployment.deleteMany({ deployId: deploy.deployId }); | ||||
| 				} | ||||
| 				await execShellAsync(`docker stack rm ${prDeployment.build.container.name}`); | ||||
| 			} | ||||
| 			return { | ||||
| 				status: 200, | ||||
| 				body: { | ||||
| 					organization, | ||||
| 					name, | ||||
| 					branch | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| 		updateServiceLabels(configuration); | ||||
| 		return { | ||||
| 			status: 200, | ||||
| 			body: { | ||||
| 				success: true | ||||
| 			} | ||||
| 		}; | ||||
|  | ||||
| 	} | ||||
| 	return { | ||||
| 		status: 500, | ||||
| 		body: { | ||||
| 			error: 'Cannot save.' | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
| @@ -1,32 +1,24 @@ | ||||
| import type { Request } from '@sveltejs/kit'; | ||||
| import Deployment from '$models/Deployment'; | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import { precheckDeployment, setDefaultConfiguration } from '$lib/api/applications/configuration'; | ||||
| import cloneRepository from '$lib/api/applications/cloneRepository'; | ||||
| import { cleanupTmp } from '$lib/api/common'; | ||||
| import queueAndBuild from '$lib/api/applications/queueAndBuild'; | ||||
| import Configuration from '$models/Configuration'; | ||||
| export async function post(request: Request) { | ||||
| 	let configuration; | ||||
| 	try { | ||||
| 		const services = (await docker.engine.listServices()).filter( | ||||
| 			(r) => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application' | ||||
| 		); | ||||
| 		configuration = setDefaultConfiguration(request.body); | ||||
|  | ||||
| 		if (!configuration) { | ||||
| 			return { | ||||
| 				status: 500, | ||||
| 				body: { | ||||
| 					error: 'Whaaat?' | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| export async function post(request: Request) { | ||||
| 	const configuration = setDefaultConfiguration(request.body); | ||||
| 	if (!configuration) { | ||||
| 		return { | ||||
| 			status: 500, | ||||
| 			body: { | ||||
| 				error: 'Whaaat?' | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
| 	try { | ||||
| 		await cloneRepository(configuration); | ||||
| 		const { foundService, imageChanged, configChanged, forceUpdate } = await precheckDeployment({ | ||||
| 			services, | ||||
| 			configuration | ||||
| 		}); | ||||
| 		const { foundService, imageChanged, configChanged, forceUpdate } = await precheckDeployment(configuration); | ||||
| 		if (foundService && !forceUpdate && !imageChanged && !configChanged) { | ||||
| 			cleanupTmp(configuration.general.workdir); | ||||
| 			return { | ||||
| @@ -56,7 +48,8 @@ export async function post(request: Request) { | ||||
| 		} | ||||
| 		const { id, organization, name, branch } = configuration.repository; | ||||
| 		const { domain } = configuration.publish; | ||||
| 		const { deployId, nickname } = configuration.general; | ||||
| 		const { deployId, nickname, pullRequest } = configuration.general; | ||||
|  | ||||
| 		await new Deployment({ | ||||
| 			repoId: id, | ||||
| 			branch, | ||||
| @@ -66,11 +59,13 @@ export async function post(request: Request) { | ||||
| 			name, | ||||
| 			nickname | ||||
| 		}).save(); | ||||
|  | ||||
| 		await Configuration.findOneAndUpdate({ | ||||
| 			'repository.id': id, | ||||
| 			'repository.organization': organization, | ||||
| 			'repository.name': name, | ||||
| 			'repository.branch': branch, | ||||
| 			'general.pullRequest': 0, | ||||
| 		}, | ||||
| 			{ ...configuration }, | ||||
| 			{ upsert: true, new: true }) | ||||
| @@ -86,6 +81,7 @@ export async function post(request: Request) { | ||||
| 			} | ||||
| 		}; | ||||
| 	} catch (error) { | ||||
| 		console.log(error) | ||||
| 		await Deployment.findOneAndUpdate( | ||||
| 			{ | ||||
| 				repoId: configuration.repository.id, | ||||
|   | ||||
| @@ -12,8 +12,6 @@ export async function get(request: Request) { | ||||
|  | ||||
| 		const deploy: any = await Deployment.findOne({ deployId }) | ||||
| 			.select('-_id -__v') | ||||
| 			.sort({ createdAt: 'desc' }); | ||||
|  | ||||
| 		const finalLogs: any = {}; | ||||
| 		finalLogs.progress = deploy.progress; | ||||
| 		finalLogs.events = logs.map((log) => log.event); | ||||
|   | ||||
| @@ -16,12 +16,12 @@ export async function get(request: Request) { | ||||
| 			.select('-_id -__v -repoId') | ||||
| 			.sort({ createdAt: 'desc' }) | ||||
| 			.limit(show); | ||||
|  | ||||
| 		const finalLogs = deploy.map((d) => { | ||||
| 			const finalLogs = { ...d._doc }; | ||||
| 			const updatedAt = dayjs(d.updatedAt).utc(); | ||||
| 			finalLogs.took = updatedAt.diff(dayjs(d.createdAt)) / 1000; | ||||
| 			finalLogs.since = updatedAt.fromNow(); | ||||
| 			finalLogs.isPr = d.domain.startsWith('pr') | ||||
| 			return finalLogs; | ||||
| 		}); | ||||
| 		return { | ||||
|   | ||||
| @@ -1,61 +1,69 @@ | ||||
| import { purgeImagesContainers } from '$lib/api/applications/cleanup'; | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import Deployment from '$models/Deployment'; | ||||
| import ApplicationLog from '$models/ApplicationLog'; | ||||
| import { delay, execShellAsync } from '$lib/api/common'; | ||||
| import Configuration from '$models/Configuration'; | ||||
|  | ||||
| async function call(found) { | ||||
| async function purgeImagesAsync(found) { | ||||
| 	await delay(10000); | ||||
| 	await purgeImagesContainers(found, true); | ||||
| } | ||||
| export async function post(request: Request) { | ||||
| 	const { organization, name, branch } = request.body; | ||||
| 	let found = false; | ||||
| 	const { organization, name, branch, domain } = request.body; | ||||
| 	try { | ||||
| 		(await docker.engine.listServices()) | ||||
| 			.filter((r) => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application') | ||||
| 			.map((s) => { | ||||
| 				const running = JSON.parse(s.Spec.Labels.configuration); | ||||
| 				if ( | ||||
| 					running.repository.organization === organization && | ||||
| 					running.repository.name === name && | ||||
| 					running.repository.branch === branch | ||||
| 				) { | ||||
| 					found = running; | ||||
| 		const configurationFound = await Configuration.findOne({ | ||||
| 			'repository.organization': organization, | ||||
| 			'repository.name': name, | ||||
| 			'repository.branch': branch, | ||||
| 			'publish.domain': domain | ||||
| 		}) | ||||
| 		if (configurationFound) { | ||||
| 			const id = configurationFound._id | ||||
| 			if (configurationFound?.general?.pullRequest === 0) { | ||||
| 				// Main deployment deletion request; deleting main + PRs | ||||
| 				const allConfiguration = await Configuration.find({ | ||||
| 					'repository.name': name, | ||||
| 					'repository.organization': organization, | ||||
| 					'repository.branch': branch, | ||||
| 				}) | ||||
| 				for (const config of allConfiguration) { | ||||
| 					await Configuration.findOneAndRemove({ | ||||
| 						'repository.name': config.repository.name, | ||||
| 						'repository.organization': config.repository.organization, | ||||
| 						'repository.branch': config.repository.branch, | ||||
| 					}) | ||||
| 					await execShellAsync(`docker stack rm ${config.build.container.name}`); | ||||
| 				} | ||||
| 				return null; | ||||
| 			}); | ||||
| 		if (found) { | ||||
| 			await Configuration.findOneAndRemove({ | ||||
| 				'repository.name': name, | ||||
| 				'repository.organization': organization, | ||||
| 				'repository.branch': branch, | ||||
| 			}) | ||||
| 			const deploys = await Deployment.find({ organization, branch, name }); | ||||
| 			for (const deploy of deploys) { | ||||
| 				await ApplicationLog.deleteMany({ deployId: deploy.deployId }); | ||||
| 				await Deployment.deleteMany({ deployId: deploy.deployId }); | ||||
| 				const deploys = await Deployment.find({ organization, branch, name }) | ||||
| 				for (const deploy of deploys) { | ||||
| 					await ApplicationLog.deleteMany({ deployId: deploy.deployId }); | ||||
| 					await Deployment.deleteMany({ deployId: deploy.deployId }); | ||||
| 				} | ||||
|  | ||||
| 				purgeImagesAsync(configurationFound); | ||||
| 			} else { | ||||
| 				// Delete only PRs | ||||
| 				await Configuration.findByIdAndRemove(id) | ||||
| 				await execShellAsync(`docker stack rm ${configurationFound.build.container.name}`); | ||||
| 				const deploys = await Deployment.find({ organization, branch, name, domain }) | ||||
| 				for (const deploy of deploys) { | ||||
| 					await ApplicationLog.deleteMany({ deployId: deploy.deployId }); | ||||
| 					await Deployment.deleteMany({ deployId: deploy.deployId }); | ||||
| 				} | ||||
| 				purgeImagesAsync(configurationFound); | ||||
| 			} | ||||
| 			await execShellAsync(`docker stack rm ${found.build.container.name}`); | ||||
| 			call(found); | ||||
| 			return { | ||||
| 				status: 200, | ||||
| 				body: { | ||||
| 					organization, | ||||
| 					name, | ||||
| 					branch | ||||
| 				} | ||||
| 			}; | ||||
| 		} else { | ||||
| 			return { | ||||
| 				status: 500, | ||||
| 				error: { | ||||
| 					message: 'Nothing to do.' | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
|  | ||||
| 		return { | ||||
| 			status: 200, | ||||
| 			body: { | ||||
| 				organization, | ||||
| 				name, | ||||
| 				branch | ||||
| 			} | ||||
| 		}; | ||||
| 	} catch (error) { | ||||
| 		console.log(error) | ||||
| 		return { | ||||
| 			status: 500, | ||||
| 			error: { | ||||
|   | ||||
| @@ -1,14 +1,9 @@ | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import type { Request } from '@sveltejs/kit'; | ||||
|  | ||||
| import Configuration from '$models/Configuration' | ||||
| export async function get(request: Request) { | ||||
| 	// Should update this to get data from mongodb and update db with the currently running services on start! | ||||
| 	const dockerServices = await docker.engine.listServices(); | ||||
| 	let applications: any = dockerServices.filter( | ||||
| 		(r) => | ||||
| 			r.Spec.Labels.managedBy === 'coolify' && | ||||
| 			r.Spec.Labels.type === 'application' && | ||||
| 			r.Spec.Labels.configuration | ||||
| 	); | ||||
| 	let databases: any = dockerServices.filter( | ||||
| 		(r) => | ||||
| 			r.Spec.Labels.managedBy === 'coolify' && | ||||
| @@ -21,15 +16,6 @@ export async function get(request: Request) { | ||||
| 			r.Spec.Labels.type === 'service' && | ||||
| 			r.Spec.Labels.configuration | ||||
| 	); | ||||
| 	applications = applications.map((r) => { | ||||
| 		if (JSON.parse(r.Spec.Labels.configuration)) { | ||||
| 			return { | ||||
| 				configuration: JSON.parse(r.Spec.Labels.configuration), | ||||
| 				UpdatedAt: r.UpdatedAt | ||||
| 			}; | ||||
| 		} | ||||
| 		return {}; | ||||
| 	}); | ||||
| 	databases = databases.map((r) => { | ||||
| 		if (JSON.parse(r.Spec.Labels.configuration)) { | ||||
| 			return { | ||||
| @@ -47,14 +33,23 @@ export async function get(request: Request) { | ||||
| 		} | ||||
| 		return {}; | ||||
| 	}); | ||||
| 	applications = [ | ||||
| 		...new Map( | ||||
| 			applications.map((item) => [ | ||||
| 				item.configuration.publish.domain + item.configuration.publish.path, | ||||
| 				item | ||||
| 			]) | ||||
| 		).values() | ||||
| 	]; | ||||
| 	const configurations = await Configuration.find({ | ||||
| 		'general.pullRequest': { '$in': [null, 0] } | ||||
| 	}).select('-_id -__v -createdAt') | ||||
| 	const applications = [] | ||||
| 	for (const configuration of configurations) { | ||||
| 		const foundPRDeployments = await Configuration.find({ | ||||
| 			'repository.id': configuration.repository.id, | ||||
| 			'repository.branch': configuration.repository.branch, | ||||
| 			'general.pullRequest': { '$ne': 0 } | ||||
| 		}).select('-_id -__v -createdAt') | ||||
| 		const payload = { | ||||
| 			configuration, | ||||
| 			UpdatedAt: configuration.updatedAt, | ||||
| 			prBuilds: foundPRDeployments.length > 0 ? true : false, | ||||
| 		} | ||||
| 		applications.push(payload) | ||||
| 	} | ||||
| 	return { | ||||
| 		status: 200, | ||||
| 		body: { | ||||
|   | ||||
| @@ -4,11 +4,16 @@ import Deployment from '$models/Deployment'; | ||||
| import { docker } from '$lib/api/docker'; | ||||
| import { precheckDeployment, setDefaultConfiguration } from '$lib/api/applications/configuration'; | ||||
| import cloneRepository from '$lib/api/applications/cloneRepository'; | ||||
| import { cleanupTmp } from '$lib/api/common'; | ||||
| import { cleanupTmp, execShellAsync } from '$lib/api/common'; | ||||
| import queueAndBuild from '$lib/api/applications/queueAndBuild'; | ||||
| import Configuration from '$models/Configuration'; | ||||
| import ApplicationLog from '$models/ApplicationLog'; | ||||
| import { cleanupStuckedDeploymentsInDB } from '$lib/api/applications/cleanup'; | ||||
| export async function post(request: Request) { | ||||
| 	let configuration; | ||||
| 	const allowedGithubEvents = ['push', 'pull_request'] | ||||
| 	const allowedPRActions = ['opened', , 'reopened', 'synchronize', 'closed'] | ||||
| 	const githubEvent = request.headers['x-github-event'] | ||||
| 	const { GITHUP_APP_WEBHOOK_SECRET } = process.env; | ||||
| 	const hmac = crypto.createHmac('sha256', GITHUP_APP_WEBHOOK_SECRET); | ||||
| 	const digest = Buffer.from( | ||||
| @@ -20,52 +25,92 @@ export async function post(request: Request) { | ||||
| 		return { | ||||
| 			status: 500, | ||||
| 			body: { | ||||
| 				error: 'Invalid request' | ||||
| 				error: 'Invalid request.' | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	if (request.headers['x-github-event'] !== 'push') { | ||||
| 	if (!allowedGithubEvents.includes(githubEvent)) { | ||||
| 		return { | ||||
| 			status: 500, | ||||
| 			body: { | ||||
| 				error: 'Not a push event.' | ||||
| 				error: 'Event not allowed.' | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	try { | ||||
| 		const services = (await docker.engine.listServices()).filter( | ||||
| 			(r) => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application' | ||||
| 		); | ||||
|  | ||||
| 		configuration = services.find((r) => { | ||||
| 			if (request.body.ref.startsWith('refs')) { | ||||
| 				const branch = request.body.ref.split('/')[2]; | ||||
| 				if ( | ||||
| 					JSON.parse(r.Spec.Labels.configuration).repository.id === request.body.repository.id && | ||||
| 					JSON.parse(r.Spec.Labels.configuration).repository.branch === branch | ||||
| 				) { | ||||
| 					return r; | ||||
| 		const applications = await Configuration.find({ | ||||
| 			'repository.id': request.body.repository.id, | ||||
| 		}).select('-_id -__v -createdAt -updatedAt') | ||||
| 		if (githubEvent === 'push') { | ||||
| 			configuration = applications.find((r) => { | ||||
| 				if (request.body.ref.startsWith('refs')) { | ||||
| 					if (r.repository.branch === request.body.ref.split('/')[2]) { | ||||
| 						return r; | ||||
| 					} | ||||
| 				} | ||||
| 				return null; | ||||
| 			}); | ||||
| 		} else if (githubEvent === 'pull_request') { | ||||
| 			if (!allowedPRActions.includes(request.body.action)) { | ||||
| 				return { | ||||
| 					status: 500, | ||||
| 					body: { | ||||
| 						error: 'PR action is not allowed.' | ||||
| 					} | ||||
| 				}; | ||||
| 			} | ||||
|  | ||||
| 			return null; | ||||
| 		}); | ||||
| 		configuration = setDefaultConfiguration(JSON.parse(configuration.Spec.Labels.configuration)); | ||||
|  | ||||
| 			configuration = applications.find((r) => r.repository.branch === request.body['pull_request'].base.ref); | ||||
| 			if (configuration) { | ||||
| 				if (!configuration.general.isPreviewDeploymentEnabled) { | ||||
| 					return { | ||||
| 						status: 500, | ||||
| 						body: { | ||||
| 							error: 'PR deployments are not enabled.' | ||||
| 						} | ||||
| 					}; | ||||
| 				} | ||||
| 				configuration.general.pullRequest = request.body.number | ||||
| 			} | ||||
| 		} | ||||
| 		if (!configuration) { | ||||
| 			return { | ||||
| 				status: 500, | ||||
| 				body: { | ||||
| 					error: 'Whaaat?' | ||||
| 					error: 'No configuration found.' | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| 		configuration = setDefaultConfiguration(configuration); | ||||
| 		const { id, organization, name, branch } = configuration.repository; | ||||
| 		const { domain } = configuration.publish; | ||||
| 		const { deployId, nickname, pullRequest } = configuration.general; | ||||
|  | ||||
| 		if (request.body.action === 'closed') { | ||||
| 			const deploys = await Deployment.find({ organization, branch, name, domain }); | ||||
| 			for (const deploy of deploys) { | ||||
| 				await ApplicationLog.deleteMany({ deployId: deploy.deployId }); | ||||
| 				await Deployment.deleteMany({ deployId: deploy.deployId }); | ||||
| 			} | ||||
| 			await Configuration.findOneAndRemove({ | ||||
| 				'repository.id': id, | ||||
| 				'repository.organization': organization, | ||||
| 				'repository.name': name, | ||||
| 				'repository.branch': branch, | ||||
| 				'general.pullRequest': pullRequest | ||||
| 			}) | ||||
| 			await execShellAsync(`docker stack rm ${configuration.build.container.name}`); | ||||
| 			return { | ||||
| 				status: 200, | ||||
| 				body: { | ||||
| 					success: true, | ||||
| 					message: 'Removed' | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| 		await cloneRepository(configuration); | ||||
| 		const { foundService, imageChanged, configChanged, forceUpdate } = await precheckDeployment({ | ||||
| 			services, | ||||
| 			configuration | ||||
| 		}); | ||||
| 		const { foundService, imageChanged, configChanged, forceUpdate } = await precheckDeployment(configuration); | ||||
| 		if (foundService && !forceUpdate && !imageChanged && !configChanged) { | ||||
| 			cleanupTmp(configuration.general.workdir); | ||||
| 			return { | ||||
| @@ -77,11 +122,11 @@ export async function post(request: Request) { | ||||
| 			}; | ||||
| 		} | ||||
| 		const alreadyQueued = await Deployment.find({ | ||||
| 			repoId: configuration.repository.id, | ||||
| 			branch: configuration.repository.branch, | ||||
| 			organization: configuration.repository.organization, | ||||
| 			name: configuration.repository.name, | ||||
| 			domain: configuration.publish.domain, | ||||
| 			repoId: id, | ||||
| 			branch: branch, | ||||
| 			organization: organization, | ||||
| 			name: name, | ||||
| 			domain: domain, | ||||
| 			progress: { $in: ['queued', 'inprogress'] } | ||||
| 		}); | ||||
| 		if (alreadyQueued.length > 0) { | ||||
| @@ -93,9 +138,7 @@ export async function post(request: Request) { | ||||
| 				} | ||||
| 			}; | ||||
| 		} | ||||
| 		const { id, organization, name, branch } = configuration.repository; | ||||
| 		const { domain } = configuration.publish; | ||||
| 		const { deployId, nickname } = configuration.general; | ||||
|  | ||||
| 		await new Deployment({ | ||||
| 			repoId: id, | ||||
| 			branch, | ||||
| @@ -105,14 +148,29 @@ export async function post(request: Request) { | ||||
| 			name, | ||||
| 			nickname | ||||
| 		}).save(); | ||||
| 		await Configuration.findOneAndUpdate({ | ||||
| 			'repository.id': id, | ||||
| 			'repository.organization': organization, | ||||
| 			'repository.name': name, | ||||
| 			'repository.branch': branch, | ||||
| 		}, | ||||
| 			{ ...configuration }, | ||||
| 			{ upsert: true, new: true }) | ||||
|  | ||||
|  | ||||
| 		if (githubEvent === 'pull_request') { | ||||
| 			await Configuration.findOneAndUpdate({ | ||||
| 				'repository.id': id, | ||||
| 				'repository.organization': organization, | ||||
| 				'repository.name': name, | ||||
| 				'repository.branch': branch, | ||||
| 				'general.pullRequest': pullRequest | ||||
| 			}, | ||||
| 				{ ...configuration }, | ||||
| 				{ upsert: true, new: true }) | ||||
| 		} else { | ||||
| 			await Configuration.findOneAndUpdate({ | ||||
| 				'repository.id': id, | ||||
| 				'repository.organization': organization, | ||||
| 				'repository.name': name, | ||||
| 				'repository.branch': branch, | ||||
| 				'general.pullRequest': { '$in': [null, 0] } | ||||
| 			}, | ||||
| 				{ ...configuration }, | ||||
| 				{ upsert: true, new: true }) | ||||
| 		} | ||||
|  | ||||
| 		queueAndBuild(configuration, imageChanged); | ||||
| 		return { | ||||
| @@ -125,28 +183,40 @@ export async function post(request: Request) { | ||||
| 			} | ||||
| 		}; | ||||
| 	} catch (error) { | ||||
| 		await Deployment.findOneAndUpdate( | ||||
| 			{ | ||||
| 				repoId: configuration.repository.id, | ||||
| 				branch: configuration.repository.branch, | ||||
| 				organization: configuration.repository.organization, | ||||
| 				name: configuration.repository.name, | ||||
| 				domain: configuration.publish.domain | ||||
| 			}, | ||||
| 			{ | ||||
| 				repoId: configuration.repository.id, | ||||
| 				branch: configuration.repository.branch, | ||||
| 				organization: configuration.repository.organization, | ||||
| 				name: configuration.repository.name, | ||||
| 				domain: configuration.publish.domain, | ||||
| 				progress: 'failed' | ||||
| 			} | ||||
| 		); | ||||
| 		console.log(error) | ||||
| 		// console.log(configuration) | ||||
| 		if (configuration) { | ||||
| 			cleanupTmp(configuration.general.workdir); | ||||
| 			await Deployment.findOneAndUpdate( | ||||
| 				{ | ||||
| 					repoId: configuration.repository.id, | ||||
| 					branch: configuration.repository.branch, | ||||
| 					organization: configuration.repository.organization, | ||||
| 					name: configuration.repository.name, | ||||
| 					domain: configuration.publish.domain | ||||
| 				}, | ||||
| 				{ | ||||
| 					repoId: configuration.repository.id, | ||||
| 					branch: configuration.repository.branch, | ||||
| 					organization: configuration.repository.organization, | ||||
| 					name: configuration.repository.name, | ||||
| 					domain: configuration.publish.domain, | ||||
| 					progress: 'failed' | ||||
| 				} | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		return { | ||||
| 			status: 500, | ||||
| 			body: { | ||||
| 				error: error.message || error | ||||
| 			} | ||||
| 		}; | ||||
| 	} finally { | ||||
| 		try { | ||||
| 			await cleanupStuckedDeploymentsInDB(); | ||||
| 		} catch (error) { | ||||
| 			console.log(error) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -84,13 +84,15 @@ | ||||
| 									deployment.progress !== 'failed'} | ||||
| 								class:bg-warmGray-800={deployment.progress !== 'done' && | ||||
| 									deployment.progress !== 'failed'} | ||||
| 								class:hover:bg-red-200={deployment.progress === 'failed'} | ||||
| 								class:hover:border-red-500={deployment.progress === 'failed'} | ||||
| 								on:click={() => goto(`./logs/${deployment.deployId}`)} | ||||
| 							> | ||||
| 								<div class="font-bold text-sm px-3 flex justify-center items-center"> | ||||
| 									{deployment.branch} | ||||
| 							<div class="flex space-x-2 px-2"> | ||||
| 								<div class="font-bold text-sm flex justify-center items-center"> | ||||
| 									{deployment.branch}  | ||||
| 								</div> | ||||
| 								<div class="font-bold text-xs flex justify-center items-center text-warmGray-500">{deployment.isPr ? 'PR' : ''}</div> | ||||
| 							</div> | ||||
| 								<div class="flex-1" /> | ||||
| 								<div class="px-3 w-48"> | ||||
| 									<div | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <script> | ||||
| 	import { application, initialApplication, initConf, dashboard } from '$store'; | ||||
| 	import { application, initialApplication, initConf, dashboard, prApplication } from '$store'; | ||||
| 	import { onDestroy } from 'svelte'; | ||||
| 	import Loading from '$components/Loading.svelte'; | ||||
| 	import Navbar from '$components/Application/Navbar.svelte'; | ||||
| @@ -14,15 +14,16 @@ | ||||
|  | ||||
| 	async function setConfiguration() { | ||||
| 		try { | ||||
| 			const config = await request(`/api/v1/application/config`, $session, { | ||||
| 			const { configuration } = await request(`/api/v1/application/config`, $session, { | ||||
| 				body: { | ||||
| 					name: $application.repository.name, | ||||
| 					organization: $application.repository.organization, | ||||
| 					branch: $application.repository.branch | ||||
| 				} | ||||
| 			}); | ||||
| 			$application = { ...config }; | ||||
| 			$initConf = JSON.parse(JSON.stringify($application)); | ||||
| 			$prApplication = configuration.filter((c) => c.general.pullRequest !== 0); | ||||
| 			$application = configuration.find((c) => c.general.pullRequest === 0); | ||||
| 			if (!$application) browser && goto('/dashboard/applications'); | ||||
| 		} catch (error) { | ||||
| 			browser && goto('/dashboard/applications'); | ||||
| 		} | ||||
|   | ||||
| @@ -67,9 +67,7 @@ | ||||
| 		<div class="pb-2 pt-5 space-y-4"> | ||||
| 			<div class="text-2xl font-bold border-gradient w-32">Database</div> | ||||
| 			<div class="flex items-center pt-4"> | ||||
| 				{#if $database.config.general.type !== 'redis'} | ||||
| 					<div class="font-bold w-64 text-warmGray-400">Connection string</div> | ||||
| 				{/if} | ||||
| 				<div class="font-bold w-64 text-warmGray-400">Connection string</div> | ||||
| 				{#if $database.config.general.type === 'mongodb'} | ||||
| 					<PasswordField | ||||
| 						value={`mongodb://${$database.envs.MONGODB_USERNAME}:${$database.envs.MONGODB_PASSWORD}@${$database.config.general.deployId}:27017/${$database.envs.MONGODB_DATABASE}`} | ||||
| @@ -86,6 +84,10 @@ | ||||
| 					<PasswordField | ||||
| 						value={`http://${$database.envs.COUCHDB_USER}:${$database.envs.COUCHDB_PASSWORD}@${$database.config.general.deployId}:5984`} | ||||
| 					/> | ||||
| 				{:else if $database.config.general.type === 'redis'} | ||||
| 					<PasswordField | ||||
| 						value={`redis://${$database.envs.REDIS_PASSWORD}@${$database.config.general.deployId}:6379`} | ||||
| 					/> | ||||
| 				{:else if $database.config.general.type === 'clickhouse'} | ||||
| 					<!-- {JSON.stringify($database)} --> | ||||
| 					<!-- <textarea | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
| 				', toolbar=0, menubar=0, status=0' | ||||
| 		); | ||||
| 		const timer = setInterval(() => { | ||||
| 			if (newWindow.closed) { | ||||
| 			if (newWindow?.closed) { | ||||
| 				clearInterval(timer); | ||||
| 				browser && location.reload() | ||||
| 			} | ||||
|   | ||||
| @@ -26,9 +26,9 @@ | ||||
| <script> | ||||
| 	export let allowRegistration; | ||||
| 	export let sendErrors; | ||||
|  | ||||
| 	import { browser } from '$app/env'; | ||||
| 	import { session } from '$app/stores'; | ||||
|  | ||||
| 	import { request } from '$lib/request'; | ||||
| 	import { toast } from '@zerodevx/svelte-toast'; | ||||
| 	import { fade } from 'svelte/transition'; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Andras Bacsai
					Andras Bacsai