185 lines · 5.1 KB · TypeScript
RawDownload
import { createWriteStream } from "node:fs";import path from "node:path";import { IS_CLOUD, paths } from "@dokploy/server/constants";import type { Schedule } from "@dokploy/server/db/schema/schedule";import {	createDeploymentSchedule,	updateDeployment,	updateDeploymentStatus,} from "@dokploy/server/services/deployment";import { findScheduleById } from "@dokploy/server/services/schedule";import { scheduledJobs, scheduleJob as scheduleJobNode } from "node-schedule";import { getComposeContainer, getServiceContainer } from "../docker/utils";import { execAsyncRemote } from "../process/execAsync";import { spawnAsync } from "../process/spawnAsync"; export const scheduleJob = (schedule: Schedule) => {	const { cronExpression, scheduleId, timezone } = schedule; 	// Use timezone from schedule, default to UTC if not specified	const tz = timezone || "UTC"; 	scheduleJobNode(		scheduleId,		{			tz,			rule: cronExpression,		},		async () => {			await runCommand(scheduleId);		},	);}; export const removeScheduleJob = (scheduleId: string) => {	const currentJob = scheduledJobs[scheduleId];	currentJob?.cancel();}; export const runCommand = async (scheduleId: string) => {	const {		application,		command,		shellType,		scheduleType,		compose,		serviceName,		appName,		serverId,	} = await findScheduleById(scheduleId); 	const deployment = await createDeploymentSchedule({		scheduleId,		title: "Schedule",		description: "Schedule",	}); 	if (scheduleType === "application" || scheduleType === "compose") {		let containerId = "";		let serverId = "";		if (scheduleType === "application" && application) {			const container = await getServiceContainer(				application.appName,				application.serverId,			);			containerId = container?.Id || "";			serverId = application.serverId || "";		}		if (scheduleType === "compose" && compose) {			const container = await getComposeContainer(compose, serviceName || "");			containerId = container?.Id || "";			serverId = compose.serverId || "";		} 		if (serverId) {			try {				await execAsyncRemote(					serverId,					`					set -e					echo "Running command: docker exec ${containerId} ${shellType} -c '${command}'" >> ${deployment.logPath};					docker exec ${containerId} ${shellType} -c '${command}' >> ${deployment.logPath} 2>> ${deployment.logPath} || { 						echo "❌ Command failed" >> ${deployment.logPath};						exit 1;					}					echo "✅ Command executed successfully" >> ${deployment.logPath};					`,				);			} catch (error) {				await updateDeploymentStatus(deployment.deploymentId, "error");				throw error;			}		} else {			const writeStream = createWriteStream(deployment.logPath, { flags: "a" }); 			try {				if (IS_CLOUD) {					writeStream.write(						"This feature is not available in the cloud version.",					);					writeStream.end();					return;				}				writeStream.write(					`docker exec ${containerId} ${shellType} -c ${command}\n`,				);				await spawnAsync(					"docker",					["exec", containerId, shellType, "-c", command],					(data) => {						if (writeStream.writable) {							writeStream.write(data);						}					},				); 				writeStream.write("✅ Command executed successfully\n");			} catch (error) {				writeStream.write("❌ Command failed\n");				writeStream.write(					error instanceof Error ? error.message : "Unknown error",				);				writeStream.end();				await updateDeploymentStatus(deployment.deploymentId, "error");				throw error;			}		}	} else if (scheduleType === "dokploy-server") {		try {			const writeStream = createWriteStream(deployment.logPath, { flags: "a" });			const { SCHEDULES_PATH } = paths();			const fullPath = path.join(SCHEDULES_PATH, appName || ""); 			await spawnAsync(				"bash",				["-c", "./script.sh"],				async (data) => {					if (writeStream.writable) {						// we need to extract the PID and Schedule ID from the data						const pid = data?.match(/PID: (\d+)/)?.[1]; 						if (pid) {							await updateDeployment(deployment.deploymentId, {								pid,							});						}						writeStream.write(data);					}				},				{					cwd: fullPath,				},			);		} catch (error) {			await updateDeploymentStatus(deployment.deploymentId, "error");			throw error;		}	} else if (scheduleType === "server") {		try {			const { SCHEDULES_PATH } = paths(true);			const fullPath = path.join(SCHEDULES_PATH, appName || "");			const command = `				set -e				echo "Running script" >> ${deployment.logPath};				bash -c ${fullPath}/script.sh 2>&1 | tee -a ${deployment.logPath} || { 					echo "❌ Command failed" >> ${deployment.logPath};					exit 1;				  }				echo "✅ Command executed successfully" >> ${deployment.logPath};			`;			await execAsyncRemote(serverId, command, async (data) => {				// we need to extract the PID and Schedule ID from the data				const pid = data?.match(/PID: (\d+)/)?.[1];				if (pid) {					await updateDeployment(deployment.deploymentId, {						pid,					});				}			});		} catch (error) {			await updateDeploymentStatus(deployment.deploymentId, "error");			throw error;		}	}	await updateDeploymentStatus(deployment.deploymentId, "done");};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t