Skip to content

Commit 0dac1fe

Browse files
authored
Merge pull request #1460 from Dokploy/canary
🚀 Release v0.20.2
2 parents 633ba89 + 47db683 commit 0dac1fe

File tree

6 files changed

+79
-21
lines changed

6 files changed

+79
-21
lines changed

apps/dokploy/__test__/templates/config.template.test.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,38 @@ describe("processTemplate", () => {
166166
if (!baseUrl || !secretKey) return;
167167

168168
expect(baseUrl).toContain(mockSchema.projectName);
169-
expect(secretKey.split("=")[1]).toHaveLength(64);
169+
const base64Value = secretKey.split("=")[1];
170+
expect(base64Value).toBeDefined();
171+
if (!base64Value) return;
172+
expect(base64Value).toMatch(/^[A-Za-z0-9+/]+={0,2}$/);
173+
expect(base64Value.length).toBeGreaterThanOrEqual(86);
174+
expect(base64Value.length).toBeLessThanOrEqual(88);
175+
});
176+
177+
it("should process env vars when provided as an array", () => {
178+
const template: CompleteTemplate = {
179+
metadata: {} as any,
180+
variables: {},
181+
config: {
182+
domains: [],
183+
env: [
184+
'CLOUDFLARE_TUNNEL_TOKEN="<INSERT TOKEN>"',
185+
'ANOTHER_VAR="some value"',
186+
"DOMAIN=${domain}",
187+
],
188+
mounts: [],
189+
},
190+
};
191+
192+
const result = processTemplate(template, mockSchema);
193+
expect(result.envs).toHaveLength(3);
194+
195+
// Should preserve exact format for static values
196+
expect(result.envs[0]).toBe('CLOUDFLARE_TUNNEL_TOKEN="<INSERT TOKEN>"');
197+
expect(result.envs[1]).toBe('ANOTHER_VAR="some value"');
198+
199+
// Should process variables in array items
200+
expect(result.envs[2]).toContain(mockSchema.projectName);
170201
});
171202

172203
it("should allow using utility functions directly in env vars", () => {
@@ -195,7 +226,12 @@ describe("processTemplate", () => {
195226
if (!randomDomainEnv || !secretKeyEnv) return;
196227

197228
expect(randomDomainEnv).toContain(mockSchema.projectName);
198-
expect(secretKeyEnv.split("=")[1]).toHaveLength(32);
229+
const base64Value = secretKeyEnv.split("=")[1];
230+
expect(base64Value).toBeDefined();
231+
if (!base64Value) return;
232+
expect(base64Value).toMatch(/^[A-Za-z0-9+/]+={0,2}$/);
233+
expect(base64Value.length).toBeGreaterThanOrEqual(42);
234+
expect(base64Value.length).toBeLessThanOrEqual(44);
199235
});
200236
});
201237

@@ -325,17 +361,31 @@ describe("processTemplate", () => {
325361
if (!baseUrl || !secretKey || !totpKey) return;
326362

327363
expect(baseUrl).toContain(mockSchema.projectName);
328-
expect(secretKey.split("=")[1]).toHaveLength(64);
329-
expect(totpKey.split("=")[1]).toHaveLength(32);
364+
365+
// Check base64 lengths and format
366+
const secretKeyValue = secretKey.split("=")[1];
367+
const totpKeyValue = totpKey.split("=")[1];
368+
369+
expect(secretKeyValue).toBeDefined();
370+
expect(totpKeyValue).toBeDefined();
371+
if (!secretKeyValue || !totpKeyValue) return;
372+
373+
expect(secretKeyValue).toMatch(/^[A-Za-z0-9+/]+={0,2}$/);
374+
expect(secretKeyValue.length).toBeGreaterThanOrEqual(86);
375+
expect(secretKeyValue.length).toBeLessThanOrEqual(88);
376+
377+
expect(totpKeyValue).toMatch(/^[A-Za-z0-9+/]+={0,2}$/);
378+
expect(totpKeyValue.length).toBeGreaterThanOrEqual(42);
379+
expect(totpKeyValue.length).toBeLessThanOrEqual(44);
330380

331381
// Check mounts
332382
expect(result.mounts).toHaveLength(1);
333383
const mount = result.mounts[0];
334384
expect(mount).toBeDefined();
335385
if (!mount) return;
336386
expect(mount.content).toContain(mockSchema.projectName);
337-
expect(mount.content).toMatch(/secret=[A-Za-z0-9+/]{64}/);
338-
expect(mount.content).toMatch(/totp=[A-Za-z0-9+/]{32}/);
387+
expect(mount.content).toMatch(/secret=[A-Za-z0-9+/]{86,88}/);
388+
expect(mount.content).toMatch(/totp=[A-Za-z0-9+/]{42,44}/);
339389
});
340390
});
341391

apps/dokploy/components/dashboard/projects/show.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export const ShowProjects = () => {
186186
target="_blank"
187187
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
188188
>
189-
<span>{domain.host}</span>
189+
<span className="truncate">{domain.host}</span>
190190
<ExternalLinkIcon className="size-4 shrink-0" />
191191
</Link>
192192
</DropdownMenuItem>
@@ -222,7 +222,7 @@ export const ShowProjects = () => {
222222
target="_blank"
223223
href={`${domain.https ? "https" : "http"}://${domain.host}${domain.path}`}
224224
>
225-
<span>{domain.host}</span>
225+
<span className="truncate">{domain.host}</span>
226226
<ExternalLinkIcon className="size-4 shrink-0" />
227227
</Link>
228228
</DropdownMenuItem>

apps/dokploy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dokploy",
3-
"version": "v0.20.1",
3+
"version": "v0.20.2",
44
"private": true,
55
"license": "Apache-2.0",
66
"type": "module",

apps/dokploy/server/api/routers/compose.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ export const composeRouter = createTRPCRouter({
607607

608608
const processedTemplate = processTemplate(config, {
609609
serverIp: serverIp,
610-
projectName: compose.project.name,
610+
projectName: compose.appName,
611611
});
612612

613613
return {
@@ -676,7 +676,7 @@ export const composeRouter = createTRPCRouter({
676676

677677
const processedTemplate = processTemplate(config, {
678678
serverIp: serverIp,
679-
projectName: compose.project.name,
679+
projectName: compose.appName,
680680
});
681681

682682
// Update compose file

packages/server/src/templates/index.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,12 @@ export const generatePassword = (quantity = 16): string => {
5353
};
5454

5555
/**
56-
* Generate a random base64 string of specified length
56+
* Generate a random base64 string from N random bytes
57+
* @param bytes Number of random bytes to generate before base64 encoding (default: 32)
58+
* @returns base64 encoded string of the random bytes
5759
*/
58-
export function generateBase64(length: number): string {
59-
// To get N characters in base64, we need to generate N * 3/4 bytes
60-
const bytesNeeded = Math.ceil((length * 3) / 4);
61-
return Buffer.from(randomBytes(bytesNeeded))
62-
.toString("base64")
63-
.substring(0, length);
60+
export function generateBase64(bytes = 32): string {
61+
return randomBytes(bytes).toString("base64");
6462
}
6563

6664
export function generateJwt(length = 256): string {

packages/server/src/templates/processors.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export interface CompleteTemplate {
4545
variables: Record<string, string>;
4646
config: {
4747
domains: DomainConfig[];
48-
env: Record<string, string>;
48+
env: Record<string, string> | string[];
4949
mounts?: MountConfig[];
5050
};
5151
}
@@ -176,7 +176,6 @@ export function processDomains(
176176
schema: Schema,
177177
): Template["domains"] {
178178
if (!template?.config?.domains) return [];
179-
180179
return template?.config?.domains?.map((domain: DomainConfig) => ({
181180
...domain,
182181
host: domain.host
@@ -195,7 +194,18 @@ export function processEnvVars(
195194
): Template["envs"] {
196195
if (!template?.config?.env) return [];
197196

198-
return Object.entries(template?.config?.env).map(
197+
// Handle array of env vars
198+
if (Array.isArray(template.config.env)) {
199+
return template.config.env.map((env) => {
200+
if (typeof env === "string") {
201+
return processValue(env, variables, schema);
202+
}
203+
return env;
204+
});
205+
}
206+
207+
// Handle object of env vars
208+
return Object.entries(template.config.env).map(
199209
([key, value]: [string, string]) => {
200210
const processedValue = processValue(value, variables, schema);
201211
return `${key}=${processedValue}`;

0 commit comments

Comments
 (0)