mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
Merge pull request #3212 from Dokploy/feat/add-create-env-file-flag
feat(environment): add createEnvFile option to environment settings
This commit is contained in:
@@ -28,6 +28,7 @@ const baseApp: ApplicationNested = {
|
||||
railpackVersion: "0.2.2",
|
||||
applicationId: "",
|
||||
previewLabels: [],
|
||||
createEnvFile: true,
|
||||
herokuVersion: "",
|
||||
giteaBranch: "",
|
||||
buildServerId: "",
|
||||
|
||||
@@ -7,6 +7,7 @@ const baseApp: ApplicationNested = {
|
||||
rollbackActive: false,
|
||||
applicationId: "",
|
||||
previewLabels: [],
|
||||
createEnvFile: true,
|
||||
herokuVersion: "",
|
||||
giteaRepository: "",
|
||||
giteaOwner: "",
|
||||
|
||||
@@ -5,14 +5,23 @@ import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Form } from "@/components/ui/form";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
} from "@/components/ui/form";
|
||||
import { Secrets } from "@/components/ui/secrets";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { api } from "@/utils/api";
|
||||
|
||||
const addEnvironmentSchema = z.object({
|
||||
env: z.string(),
|
||||
buildArgs: z.string(),
|
||||
buildSecrets: z.string(),
|
||||
createEnvFile: z.boolean(),
|
||||
});
|
||||
|
||||
type EnvironmentSchema = z.infer<typeof addEnvironmentSchema>;
|
||||
@@ -39,6 +48,7 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
env: "",
|
||||
buildArgs: "",
|
||||
buildSecrets: "",
|
||||
createEnvFile: true,
|
||||
},
|
||||
resolver: zodResolver(addEnvironmentSchema),
|
||||
});
|
||||
@@ -47,10 +57,12 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
const currentEnv = form.watch("env");
|
||||
const currentBuildArgs = form.watch("buildArgs");
|
||||
const currentBuildSecrets = form.watch("buildSecrets");
|
||||
const currentCreateEnvFile = form.watch("createEnvFile");
|
||||
const hasChanges =
|
||||
currentEnv !== (data?.env || "") ||
|
||||
currentBuildArgs !== (data?.buildArgs || "") ||
|
||||
currentBuildSecrets !== (data?.buildSecrets || "");
|
||||
currentBuildSecrets !== (data?.buildSecrets || "") ||
|
||||
currentCreateEnvFile !== (data?.createEnvFile ?? true);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -58,6 +70,7 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
env: data.env || "",
|
||||
buildArgs: data.buildArgs || "",
|
||||
buildSecrets: data.buildSecrets || "",
|
||||
createEnvFile: data.createEnvFile ?? true,
|
||||
});
|
||||
}
|
||||
}, [data, form]);
|
||||
@@ -67,6 +80,7 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
env: formData.env,
|
||||
buildArgs: formData.buildArgs,
|
||||
buildSecrets: formData.buildSecrets,
|
||||
createEnvFile: formData.createEnvFile,
|
||||
applicationId,
|
||||
})
|
||||
.then(async () => {
|
||||
@@ -83,6 +97,7 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
env: data?.env || "",
|
||||
buildArgs: data?.buildArgs || "",
|
||||
buildSecrets: data?.buildSecrets || "",
|
||||
createEnvFile: data?.createEnvFile ?? true,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -167,6 +182,30 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
|
||||
placeholder="NPM_TOKEN=xyz"
|
||||
/>
|
||||
)}
|
||||
{data?.buildType === "dockerfile" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="createEnvFile"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-center justify-between p-3 border rounded-lg shadow-sm">
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel>Create Environment File</FormLabel>
|
||||
<FormDescription>
|
||||
When enabled, an .env file will be created during the
|
||||
build process. Disable this if you don't want to generate
|
||||
an environment file.
|
||||
</FormDescription>
|
||||
</div>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<div className="flex flex-row justify-end gap-2">
|
||||
{hasChanges && (
|
||||
<Button type="button" variant="outline" onClick={handleCancel}>
|
||||
|
||||
1
apps/dokploy/drizzle/0131_volatile_beast.sql
Normal file
1
apps/dokploy/drizzle/0131_volatile_beast.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "application" ADD COLUMN "createEnvFile" boolean DEFAULT true NOT NULL;
|
||||
6928
apps/dokploy/drizzle/meta/0131_snapshot.json
Normal file
6928
apps/dokploy/drizzle/meta/0131_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -918,6 +918,13 @@
|
||||
"when": 1765167657813,
|
||||
"tag": "0130_perpetual_screwball",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 131,
|
||||
"version": "7",
|
||||
"when": 1765342621312,
|
||||
"tag": "0131_volatile_beast",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -365,6 +365,7 @@ export const applicationRouter = createTRPCRouter({
|
||||
env: input.env,
|
||||
buildArgs: input.buildArgs,
|
||||
buildSecrets: input.buildSecrets,
|
||||
createEnvFile: input.createEnvFile,
|
||||
});
|
||||
return true;
|
||||
}),
|
||||
|
||||
@@ -181,6 +181,7 @@ export const applications = pgTable("application", {
|
||||
herokuVersion: text("herokuVersion").default("24"),
|
||||
publishDirectory: text("publishDirectory"),
|
||||
isStaticSpa: boolean("isStaticSpa"),
|
||||
createEnvFile: boolean("createEnvFile").notNull().default(true),
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
@@ -332,6 +333,7 @@ const createSchema = createInsertSchema(applications, {
|
||||
herokuVersion: z.string().optional(),
|
||||
publishDirectory: z.string().optional(),
|
||||
isStaticSpa: z.boolean().optional(),
|
||||
createEnvFile: z.boolean().optional(),
|
||||
owner: z.string(),
|
||||
healthCheckSwarm: HealthCheckSwarmSchema.nullable(),
|
||||
restartPolicySwarm: RestartPolicySwarmSchema.nullable(),
|
||||
@@ -501,6 +503,7 @@ export const apiSaveEnvironmentVariables = createSchema
|
||||
env: true,
|
||||
buildArgs: true,
|
||||
buildSecrets: true,
|
||||
createEnvFile: true,
|
||||
})
|
||||
.required();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getDockerContextPath,
|
||||
} from "../filesystem/directory";
|
||||
import type { ApplicationNested } from ".";
|
||||
import { createEnvFileCommand } from "./utils";
|
||||
|
||||
export const getDockerCommand = (application: ApplicationNested) => {
|
||||
const {
|
||||
@@ -18,6 +19,7 @@ export const getDockerCommand = (application: ApplicationNested) => {
|
||||
buildSecrets,
|
||||
dockerBuildStage,
|
||||
cleanCache,
|
||||
createEnvFile,
|
||||
} = application;
|
||||
const dockerFilePath = getBuildAppDirectory(application);
|
||||
|
||||
@@ -60,6 +62,21 @@ export const getDockerCommand = (application: ApplicationNested) => {
|
||||
.map(([key, value]) => `${key}=${quote([value])}`)
|
||||
.join(" ");
|
||||
|
||||
/*
|
||||
Do not generate an environment file when publishDirectory is specified,
|
||||
as it could be publicly exposed.
|
||||
Also respect the createEnvFile flag.
|
||||
*/
|
||||
let command = "";
|
||||
if (!publishDirectory && createEnvFile) {
|
||||
command += createEnvFileCommand(
|
||||
dockerFilePath,
|
||||
env,
|
||||
application.environment.project.env,
|
||||
application.environment.env,
|
||||
);
|
||||
}
|
||||
|
||||
for (const key in secrets) {
|
||||
// Although buildx is smart enough to know we may be referring to an environment variable name,
|
||||
// we still make sure it doesn't fall back to `type=file`.
|
||||
@@ -67,7 +84,7 @@ export const getDockerCommand = (application: ApplicationNested) => {
|
||||
commandArgs.push("--secret", `type=env,id=${key}`);
|
||||
}
|
||||
|
||||
const command = `
|
||||
command += `
|
||||
echo "Building ${appName}" ;
|
||||
cd ${dockerContextPath} || {
|
||||
echo "❌ The path ${dockerContextPath} does not exist" ;
|
||||
|
||||
Reference in New Issue
Block a user