mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
288 lines
8.1 KiB
TypeScript
288 lines
8.1 KiB
TypeScript
import * as adminService from "@dokploy/server/services/admin";
|
|
import * as applicationService from "@dokploy/server/services/application";
|
|
import { deployApplication } from "@dokploy/server/services/application";
|
|
import * as deploymentService from "@dokploy/server/services/deployment";
|
|
import * as builders from "@dokploy/server/utils/builders";
|
|
import * as notifications from "@dokploy/server/utils/notifications/build-success";
|
|
import * as execProcess from "@dokploy/server/utils/process/execAsync";
|
|
import * as gitProvider from "@dokploy/server/utils/providers/git";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("@dokploy/server/db", () => {
|
|
const createChainableMock = (): any => {
|
|
const chain = {
|
|
set: vi.fn(() => chain),
|
|
where: vi.fn(() => chain),
|
|
returning: vi.fn().mockResolvedValue([{}] as any),
|
|
from: vi.fn(() => chain),
|
|
innerJoin: vi.fn(() => chain),
|
|
then: (resolve: (v: any) => void) => {
|
|
resolve([]);
|
|
},
|
|
} as any;
|
|
return chain;
|
|
};
|
|
|
|
return {
|
|
db: {
|
|
select: vi.fn(() => createChainableMock()),
|
|
insert: vi.fn(),
|
|
update: vi.fn(() => createChainableMock()),
|
|
delete: vi.fn(),
|
|
query: {
|
|
applications: {
|
|
findFirst: vi.fn(),
|
|
},
|
|
patch: {
|
|
findMany: vi.fn().mockResolvedValue([]),
|
|
},
|
|
member: {
|
|
findMany: vi.fn().mockResolvedValue([]),
|
|
},
|
|
},
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("@dokploy/server/services/application", async () => {
|
|
const actual = await vi.importActual<
|
|
typeof import("@dokploy/server/services/application")
|
|
>("@dokploy/server/services/application");
|
|
return {
|
|
...actual,
|
|
findApplicationById: vi.fn(),
|
|
updateApplicationStatus: vi.fn(),
|
|
};
|
|
});
|
|
|
|
vi.mock("@dokploy/server/services/admin", () => ({
|
|
getDokployUrl: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@dokploy/server/services/deployment", () => ({
|
|
createDeployment: vi.fn(),
|
|
updateDeploymentStatus: vi.fn(),
|
|
updateDeployment: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@dokploy/server/utils/providers/git", async () => {
|
|
const actual = await vi.importActual<
|
|
typeof import("@dokploy/server/utils/providers/git")
|
|
>("@dokploy/server/utils/providers/git");
|
|
return {
|
|
...actual,
|
|
getGitCommitInfo: vi.fn(),
|
|
};
|
|
});
|
|
|
|
vi.mock("@dokploy/server/utils/process/execAsync", () => ({
|
|
execAsync: vi.fn(),
|
|
ExecError: class ExecError extends Error {},
|
|
}));
|
|
|
|
vi.mock("@dokploy/server/utils/builders", async () => {
|
|
const actual = await vi.importActual<
|
|
typeof import("@dokploy/server/utils/builders")
|
|
>("@dokploy/server/utils/builders");
|
|
return {
|
|
...actual,
|
|
mechanizeDockerContainer: vi.fn(),
|
|
getBuildCommand: vi.fn(),
|
|
};
|
|
});
|
|
|
|
vi.mock("@dokploy/server/utils/notifications/build-success", () => ({
|
|
sendBuildSuccessNotifications: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@dokploy/server/utils/notifications/build-error", () => ({
|
|
sendBuildErrorNotifications: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@dokploy/server/services/rollbacks", () => ({
|
|
createRollback: vi.fn(),
|
|
}));
|
|
|
|
import { db } from "@dokploy/server/db";
|
|
import { cloneGitRepository } from "@dokploy/server/utils/providers/git";
|
|
|
|
const createMockApplication = (overrides = {}) => ({
|
|
applicationId: "test-app-id",
|
|
name: "Test App",
|
|
appName: "test-app",
|
|
sourceType: "git" as const,
|
|
customGitUrl: "https://github.com/Dokploy/examples.git",
|
|
customGitBranch: "main",
|
|
customGitSSHKeyId: null,
|
|
buildType: "nixpacks" as const,
|
|
buildPath: "/astro",
|
|
env: "NODE_ENV=production",
|
|
serverId: null,
|
|
rollbackActive: false,
|
|
enableSubmodules: false,
|
|
environmentId: "env-id",
|
|
environment: {
|
|
projectId: "project-id",
|
|
env: "",
|
|
name: "production",
|
|
project: {
|
|
name: "Test Project",
|
|
organizationId: "org-id",
|
|
env: "",
|
|
},
|
|
},
|
|
domains: [],
|
|
...overrides,
|
|
});
|
|
|
|
const createMockDeployment = () => ({
|
|
deploymentId: "deployment-id",
|
|
logPath: "/tmp/test-deployment.log",
|
|
});
|
|
|
|
describe("deployApplication - Command Generation Tests", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(db.query.applications.findFirst).mockResolvedValue(
|
|
createMockApplication() as any,
|
|
);
|
|
vi.mocked(applicationService.findApplicationById).mockResolvedValue(
|
|
createMockApplication() as any,
|
|
);
|
|
vi.mocked(adminService.getDokployUrl).mockResolvedValue(
|
|
"http://localhost:3000",
|
|
);
|
|
vi.mocked(deploymentService.createDeployment).mockResolvedValue(
|
|
createMockDeployment() as any,
|
|
);
|
|
vi.mocked(execProcess.execAsync).mockResolvedValue({
|
|
stdout: "",
|
|
stderr: "",
|
|
} as any);
|
|
vi.mocked(builders.mechanizeDockerContainer).mockResolvedValue(
|
|
undefined as any,
|
|
);
|
|
vi.mocked(deploymentService.updateDeploymentStatus).mockResolvedValue(
|
|
undefined as any,
|
|
);
|
|
vi.mocked(applicationService.updateApplicationStatus).mockResolvedValue(
|
|
{} as any,
|
|
);
|
|
vi.mocked(notifications.sendBuildSuccessNotifications).mockResolvedValue(
|
|
undefined as any,
|
|
);
|
|
vi.mocked(gitProvider.getGitCommitInfo).mockResolvedValue({
|
|
message: "test commit",
|
|
hash: "abc123",
|
|
});
|
|
vi.mocked(deploymentService.updateDeployment).mockResolvedValue({} as any);
|
|
});
|
|
|
|
it("should generate correct git clone command for astro example", async () => {
|
|
const app = createMockApplication();
|
|
const command = await cloneGitRepository(app);
|
|
console.log(command);
|
|
|
|
expect(command).toContain("https://github.com/Dokploy/examples.git");
|
|
expect(command).not.toContain("--recurse-submodules");
|
|
expect(command).toContain("--branch main");
|
|
expect(command).toContain("--depth 1");
|
|
expect(command).toContain("git clone");
|
|
});
|
|
|
|
it("should generate git clone with submodules when enabled", async () => {
|
|
const app = createMockApplication({ enableSubmodules: true });
|
|
const command = await cloneGitRepository(app);
|
|
|
|
expect(command).toContain("--recurse-submodules");
|
|
expect(command).toContain("https://github.com/Dokploy/examples.git");
|
|
});
|
|
|
|
it("should verify nixpacks command is called with correct app", async () => {
|
|
const mockNixpacksCommand = "nixpacks build /path/to/app --name test-app";
|
|
vi.mocked(builders.getBuildCommand).mockResolvedValue(mockNixpacksCommand);
|
|
|
|
await deployApplication({
|
|
applicationId: "test-app-id",
|
|
titleLog: "Test deployment",
|
|
descriptionLog: "",
|
|
});
|
|
|
|
expect(builders.getBuildCommand).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
buildType: "nixpacks",
|
|
customGitUrl: "https://github.com/Dokploy/examples.git",
|
|
buildPath: "/astro",
|
|
}),
|
|
);
|
|
|
|
expect(execProcess.execAsync).toHaveBeenCalledWith(
|
|
expect.stringContaining("nixpacks build"),
|
|
);
|
|
});
|
|
|
|
it("should verify railpack command includes correct parameters", async () => {
|
|
const mockApp = createMockApplication({ buildType: "railpack" });
|
|
vi.mocked(db.query.applications.findFirst).mockResolvedValue(
|
|
mockApp as any,
|
|
);
|
|
vi.mocked(applicationService.findApplicationById).mockResolvedValue(
|
|
mockApp as any,
|
|
);
|
|
|
|
const mockRailpackCommand = "railpack prepare /path/to/app";
|
|
vi.mocked(builders.getBuildCommand).mockResolvedValue(mockRailpackCommand);
|
|
|
|
await deployApplication({
|
|
applicationId: "test-app-id",
|
|
titleLog: "Railpack test",
|
|
descriptionLog: "",
|
|
});
|
|
|
|
expect(builders.getBuildCommand).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
buildType: "railpack",
|
|
}),
|
|
);
|
|
|
|
expect(execProcess.execAsync).toHaveBeenCalledWith(
|
|
expect.stringContaining("railpack prepare"),
|
|
);
|
|
});
|
|
|
|
it("should execute commands in correct order", async () => {
|
|
const mockNixpacksCommand = "nixpacks build";
|
|
vi.mocked(builders.getBuildCommand).mockResolvedValue(mockNixpacksCommand);
|
|
|
|
await deployApplication({
|
|
applicationId: "test-app-id",
|
|
titleLog: "Test",
|
|
descriptionLog: "",
|
|
});
|
|
|
|
const execCalls = vi.mocked(execProcess.execAsync).mock.calls;
|
|
expect(execCalls.length).toBeGreaterThan(0);
|
|
|
|
const fullCommand = execCalls[0]?.[0];
|
|
expect(fullCommand).toContain("set -e");
|
|
expect(fullCommand).toContain("git clone");
|
|
expect(fullCommand).toContain("nixpacks build");
|
|
});
|
|
|
|
it("should include log redirection in command", async () => {
|
|
const mockCommand = "nixpacks build";
|
|
vi.mocked(builders.getBuildCommand).mockResolvedValue(mockCommand);
|
|
|
|
await deployApplication({
|
|
applicationId: "test-app-id",
|
|
titleLog: "Test",
|
|
descriptionLog: "",
|
|
});
|
|
|
|
const execCalls = vi.mocked(execProcess.execAsync).mock.calls;
|
|
const fullCommand = execCalls[0]?.[0];
|
|
|
|
expect(fullCommand).toContain(">> /tmp/test-deployment.log 2>&1");
|
|
});
|
|
});
|