mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-04 03:02:16 +00:00
Merge pull request #4923 from dmtrTm/fix/rollback-environment-variables
fix: resolve environment variables on application rollback
(cherry picked from commit 46c87a22b0)
This commit is contained in:
committed by
Mauricio Siu
parent
b7fdbd4704
commit
112b2c8358
@@ -0,0 +1,108 @@
|
|||||||
|
import { prepareEnvironmentVariables } from "@dokploy/server/index";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
const projectEnv = `
|
||||||
|
ENVIRONMENT=staging
|
||||||
|
DATABASE_URL=postgres://postgres:postgres@localhost:5432/project_db
|
||||||
|
`;
|
||||||
|
|
||||||
|
const environmentEnv = `
|
||||||
|
NODE_ENV=production
|
||||||
|
POSTGRES_HOST=postgres.internal
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
REDIS_URL=redis://redis.internal:6379
|
||||||
|
`;
|
||||||
|
|
||||||
|
const serviceEnv = `
|
||||||
|
NODE_ENV=\${{environment.NODE_ENV}}
|
||||||
|
REDIS_URL=\${{environment.REDIS_URL}}
|
||||||
|
PORT=3000
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A rollback replays the snapshot stored in `rollbacks.fullContext`, which keeps
|
||||||
|
* the service env, the environment env and the project env captured at deploy time.
|
||||||
|
*/
|
||||||
|
const fullContext = {
|
||||||
|
env: serviceEnv,
|
||||||
|
environment: {
|
||||||
|
env: environmentEnv,
|
||||||
|
project: {
|
||||||
|
env: projectEnv,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("prepareEnvironmentVariables for application rollback", () => {
|
||||||
|
it("resolves environment variables from the rollback snapshot", () => {
|
||||||
|
const result = prepareEnvironmentVariables(
|
||||||
|
fullContext.env,
|
||||||
|
fullContext.environment.project.env,
|
||||||
|
fullContext.environment.env,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
"NODE_ENV=production",
|
||||||
|
"REDIS_URL=redis://redis.internal:6379",
|
||||||
|
"PORT=3000",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves project and environment variables together on rollback", () => {
|
||||||
|
const rollbackEnv = `
|
||||||
|
DATABASE_URL=\${{project.DATABASE_URL}}
|
||||||
|
POSTGRES_URL=postgres://\${{environment.POSTGRES_HOST}}:\${{environment.POSTGRES_PORT}}/app
|
||||||
|
ENVIRONMENT=\${{project.ENVIRONMENT}}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = prepareEnvironmentVariables(
|
||||||
|
rollbackEnv,
|
||||||
|
projectEnv,
|
||||||
|
environmentEnv,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
"DATABASE_URL=postgres://postgres:postgres@localhost:5432/project_db",
|
||||||
|
"POSTGRES_URL=postgres://postgres.internal:5432/app",
|
||||||
|
"ENVIRONMENT=staging",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws when the environment env of the snapshot is not passed", () => {
|
||||||
|
expect(() =>
|
||||||
|
prepareEnvironmentVariables(fullContext.env, projectEnv),
|
||||||
|
).toThrow("Invalid environment variable: environment.NODE_ENV");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maintains precedence: service > environment > project on rollback", () => {
|
||||||
|
const conflictingProjectEnv = `
|
||||||
|
NODE_ENV=project
|
||||||
|
API_URL=https://project.api.com
|
||||||
|
`;
|
||||||
|
|
||||||
|
const conflictingEnvironmentEnv = `
|
||||||
|
NODE_ENV=environment
|
||||||
|
API_URL=https://environment.api.com
|
||||||
|
`;
|
||||||
|
|
||||||
|
const rollbackEnv = `
|
||||||
|
NODE_ENV=service
|
||||||
|
PROJECT_API_URL=\${{project.API_URL}}
|
||||||
|
ENVIRONMENT_API_URL=\${{environment.API_URL}}
|
||||||
|
SELF_REFERENCE=\${{NODE_ENV}}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = prepareEnvironmentVariables(
|
||||||
|
rollbackEnv,
|
||||||
|
conflictingProjectEnv,
|
||||||
|
conflictingEnvironmentEnv,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
"NODE_ENV=service",
|
||||||
|
"PROJECT_API_URL=https://project.api.com",
|
||||||
|
"ENVIRONMENT_API_URL=https://environment.api.com",
|
||||||
|
"SELF_REFERENCE=service",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Application } from "@dokploy/server/services/application";
|
import type { Application } from "@dokploy/server/services/application";
|
||||||
|
import type { Environment } from "@dokploy/server/services/environment";
|
||||||
import type { Mount } from "@dokploy/server/services/mount";
|
import type { Mount } from "@dokploy/server/services/mount";
|
||||||
import type { Port } from "@dokploy/server/services/port";
|
import type { Port } from "@dokploy/server/services/port";
|
||||||
import type { Project } from "@dokploy/server/services/project";
|
import type { Project } from "@dokploy/server/services/project";
|
||||||
@@ -27,7 +28,7 @@ export const rollbacks = pgTable("rollback", {
|
|||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
fullContext: jsonb("fullContext").$type<
|
fullContext: jsonb("fullContext").$type<
|
||||||
Application & {
|
Application & {
|
||||||
environment: {
|
environment: Environment & {
|
||||||
project: Project;
|
project: Project;
|
||||||
};
|
};
|
||||||
mounts: Mount[];
|
mounts: Mount[];
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { execAsync, execAsyncRemote } from "../utils/process/execAsync";
|
|||||||
import { getRemoteDocker } from "../utils/servers/remote-docker";
|
import { getRemoteDocker } from "../utils/servers/remote-docker";
|
||||||
import { type Application, findApplicationById } from "./application";
|
import { type Application, findApplicationById } from "./application";
|
||||||
import { findDeploymentById } from "./deployment";
|
import { findDeploymentById } from "./deployment";
|
||||||
|
import type { Environment } from "./environment";
|
||||||
import type { Mount } from "./mount";
|
import type { Mount } from "./mount";
|
||||||
import type { Port } from "./port";
|
import type { Port } from "./port";
|
||||||
import type { Project } from "./project";
|
import type { Project } from "./project";
|
||||||
@@ -201,7 +202,7 @@ const rollbackApplication = async (
|
|||||||
image: string,
|
image: string,
|
||||||
serverId?: string | null,
|
serverId?: string | null,
|
||||||
fullContext?: Application & {
|
fullContext?: Application & {
|
||||||
environment: {
|
environment: Environment & {
|
||||||
project: Project;
|
project: Project;
|
||||||
};
|
};
|
||||||
mounts: Mount[];
|
mounts: Mount[];
|
||||||
@@ -263,6 +264,7 @@ const rollbackApplication = async (
|
|||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
env,
|
env,
|
||||||
fullContext.environment.project.env,
|
fullContext.environment.project.env,
|
||||||
|
fullContext.environment.env,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rollbackImage = image;
|
let rollbackImage = image;
|
||||||
|
|||||||
Reference in New Issue
Block a user