mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: enhance rollback functionality with UI updates and database schema changes
- Updated Tailwind configuration for responsive design. - Modified the ShowDeployments component to include rollback settings and actions. - Introduced a new "rollback" table in the database schema with foreign key relationships. - Updated deployment and application schemas to support rollback features. - Added rollback mutation to the API for initiating rollbacks.
This commit is contained in:
@@ -27,7 +27,6 @@ import { server } from "./server";
|
||||
import { applicationStatus, certificateType, triggerType } from "./shared";
|
||||
import { sshKeys } from "./ssh-key";
|
||||
import { generateAppName } from "./utils";
|
||||
import { rollbacks } from "./rollbacks";
|
||||
export const sourceType = pgEnum("sourceType", [
|
||||
"docker",
|
||||
"git",
|
||||
@@ -277,7 +276,6 @@ export const applicationsRelations = relations(
|
||||
references: [server.serverId],
|
||||
}),
|
||||
previewDeployments: many(previewDeployments),
|
||||
rollbacks: many(rollbacks),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { compose } from "./compose";
|
||||
import { previewDeployments } from "./preview-deployments";
|
||||
import { schedules } from "./schedule";
|
||||
import { server } from "./server";
|
||||
import { rollbacks } from "./rollbacks";
|
||||
export const deploymentStatus = pgEnum("deploymentStatus", [
|
||||
"running",
|
||||
"done",
|
||||
@@ -58,6 +59,10 @@ export const deployments = pgTable("deployment", {
|
||||
backupId: text("backupId").references((): AnyPgColumn => backups.backupId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
rollbackId: text("rollbackId").references(
|
||||
(): AnyPgColumn => rollbacks.rollbackId,
|
||||
{ onDelete: "cascade" },
|
||||
),
|
||||
});
|
||||
|
||||
export const deploymentsRelations = relations(deployments, ({ one }) => ({
|
||||
@@ -85,6 +90,10 @@ export const deploymentsRelations = relations(deployments, ({ one }) => ({
|
||||
fields: [deployments.backupId],
|
||||
references: [backups.backupId],
|
||||
}),
|
||||
rollback: one(rollbacks, {
|
||||
fields: [deployments.deploymentId],
|
||||
references: [rollbacks.deploymentId],
|
||||
}),
|
||||
}));
|
||||
|
||||
const schema = createInsertSchema(deployments, {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { pgTable, serial, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { applications } from "./application";
|
||||
import { deployments } from "./deployment";
|
||||
|
||||
export const rollbacks = pgTable("rollback", {
|
||||
rollbackId: text("rollbackId")
|
||||
@@ -11,9 +11,9 @@ export const rollbacks = pgTable("rollback", {
|
||||
.primaryKey()
|
||||
.$defaultFn(() => nanoid()),
|
||||
env: text("env"),
|
||||
applicationId: text("applicationId")
|
||||
deploymentId: text("deploymentId")
|
||||
.notNull()
|
||||
.references(() => applications.applicationId, {
|
||||
.references(() => deployments.deploymentId, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
version: serial(),
|
||||
@@ -26,9 +26,9 @@ export const rollbacks = pgTable("rollback", {
|
||||
export type Rollback = typeof rollbacks.$inferSelect;
|
||||
|
||||
export const rollbacksRelations = relations(rollbacks, ({ one }) => ({
|
||||
application: one(applications, {
|
||||
fields: [rollbacks.applicationId],
|
||||
references: [applications.applicationId],
|
||||
deployment: one(deployments, {
|
||||
fields: [rollbacks.deploymentId],
|
||||
references: [deployments.deploymentId],
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
@@ -224,12 +224,10 @@ export const deployApplication = async ({
|
||||
application.project.env,
|
||||
);
|
||||
|
||||
console.log(resolveEnvs);
|
||||
|
||||
await createRollback({
|
||||
appName: application.appName,
|
||||
env: resolveEnvs.join("\n"),
|
||||
applicationId: applicationId,
|
||||
deploymentId: deployment.deploymentId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -34,20 +34,34 @@ import { findScheduleById } from "./schedule";
|
||||
|
||||
export type Deployment = typeof deployments.$inferSelect;
|
||||
|
||||
export const findDeploymentById = async (applicationId: string) => {
|
||||
const application = await db.query.deployments.findFirst({
|
||||
where: eq(deployments.applicationId, applicationId),
|
||||
export const findDeploymentById = async (deploymentId: string) => {
|
||||
const deployment = await db.query.deployments.findFirst({
|
||||
where: eq(deployments.deploymentId, deploymentId),
|
||||
with: {
|
||||
application: true,
|
||||
},
|
||||
});
|
||||
if (!application) {
|
||||
if (!deployment) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Deployment not found",
|
||||
});
|
||||
}
|
||||
return application;
|
||||
return deployment;
|
||||
};
|
||||
|
||||
export const findDeploymentByApplicationId = async (applicationId: string) => {
|
||||
const deployment = await db.query.deployments.findFirst({
|
||||
where: eq(deployments.applicationId, applicationId),
|
||||
});
|
||||
|
||||
if (!deployment) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Deployment not found",
|
||||
});
|
||||
}
|
||||
return deployment;
|
||||
};
|
||||
|
||||
export const createDeployment = async (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getRemoteDocker } from "../utils/servers/remote-docker";
|
||||
import type { ApplicationNested } from "../utils/builders";
|
||||
import { execAsync, execAsyncRemote } from "../utils/process/execAsync";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import { findDeploymentById } from "./deployment";
|
||||
|
||||
export const createRollback = async (
|
||||
input: z.infer<typeof createRollbackSchema>,
|
||||
@@ -31,7 +32,13 @@ export const createRollback = async (
|
||||
})
|
||||
.where(eq(rollbacks.rollbackId, rollback.rollbackId));
|
||||
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
const deployment = await findDeploymentById(rollback.deploymentId);
|
||||
|
||||
if (!deployment?.applicationId) {
|
||||
throw new Error("Deployment not found");
|
||||
}
|
||||
|
||||
const application = await findApplicationById(deployment.applicationId);
|
||||
|
||||
await createRollbackImage(application, tagImage);
|
||||
|
||||
@@ -86,7 +93,13 @@ export const removeRollbackById = async (rollbackId: string) => {
|
||||
|
||||
if (result?.image) {
|
||||
try {
|
||||
const application = await findApplicationById(result.applicationId);
|
||||
const deployment = await findDeploymentById(result.deploymentId);
|
||||
|
||||
if (!deployment?.applicationId) {
|
||||
throw new Error("Deployment not found");
|
||||
}
|
||||
|
||||
const application = await findApplicationById(deployment.applicationId);
|
||||
await deleteRollbackImage(result.image, application.serverId);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -99,7 +112,13 @@ export const removeRollbackById = async (rollbackId: string) => {
|
||||
export const rollback = async (rollbackId: string) => {
|
||||
const result = await findRollbackById(rollbackId);
|
||||
|
||||
const application = await findApplicationById(result.applicationId);
|
||||
const deployment = await findDeploymentById(result.deploymentId);
|
||||
|
||||
if (!deployment?.applicationId) {
|
||||
throw new Error("Deployment not found");
|
||||
}
|
||||
|
||||
const application = await findApplicationById(deployment.applicationId);
|
||||
|
||||
await rollbackApplication(
|
||||
application.appName,
|
||||
@@ -122,7 +141,7 @@ const rollbackApplication = async (
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: image,
|
||||
Env: env.split("\n"),
|
||||
// Env: env.split("\n"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user