[general-kit]: add --env-file CLI flag for loading dotenv files#5885
Open
h2m6jcm94s-eng wants to merge 1 commit into
Open
[general-kit]: add --env-file CLI flag for loading dotenv files#5885h2m6jcm94s-eng wants to merge 1 commit into
h2m6jcm94s-eng wants to merge 1 commit into
Conversation
Adds support for loading environment variables from one or more files before the drizzle config is evaluated, matching the semantics of Node 22's --env-file flag: drizzle-kit migrate --env-file=.env.local drizzle-kit push --env-file=.env --env-file=.env.local The flag is parsed in a new ./env-loader module imported as the first side-effect in src/cli/index.ts. It runs before src/cli/schema.ts (whose top-level `import 'dotenv/config'` loads the default .env), so values from --env-file are visible to the config file alongside any default .env values. Precedence (highest to lowest): 1. Existing process.env (shell-exported vars), never overwritten 2. The last --env-file on the command line 3. Earlier --env-file occurrences 4. The auto-loaded .env (existing behavior) The flag is stripped from process.argv after parsing so brocli, which doesn't share an option across every command, never sees it. It is still registered as an option on every subcommand so it appears in --help output and assertCollisions ignores it the same way it ignores --config. Tests cover the argv extractor (multiple forms, ordering) and the loader semantics (single file, multi-file precedence, shell-var protection) in drizzle-kit/tests/cli-env-file.test.ts. Closes drizzle-team#4588
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Closes #4588.
drizzle-kit only auto-loads a top-level
.envfrom the current working directory via theimport 'dotenv/config'side-effect at the top ofsrc/cli/schema.ts. Anyone keeping theirDATABASE_URLin a non-default file (e.g..env.local,.env.staging) currently has to either:DATABASE_URL=... drizzle-kit migrate), ordotenv -e .env.local --/tsx --env-file=…shim.This matches the precedent set by Node 22+'s native
--env-fileflag and bytsx --env-file=. The issue explicitly asks for multiple-flag support, which this PR delivers.Behavior
Precedence (highest → lowest):
process.env(shell-exported vars) — never overwritten.--env-fileon the command line.--env-fileoccurrences..envin the cwd (existing behavior, unchanged).This mirrors Node 22's semantics: shell vars win, later
--env-fileoverrides earlier--env-file, and.envremains the auto-loaded baseline.Implementation
drizzle-kit/src/cli/env-loader.ts— exportsextractEnvFiles(argv parser, supports--env-file=path,--env-file path,-e=path,-e path) andapplyEnvFiles(loader honoring the precedence above). The module body runs the extraction againstprocess.argv.slice(2), applies the files, and strips the flags fromprocess.argvso brocli (which doesn't share an option across commands) never sees them.drizzle-kit/src/cli/index.ts—import './env-loader';as the first statement. Because ES module bindings are evaluated in source order, this fires before./schema's top-levelimport 'dotenv/config', ensuring.env(override-false) does not stomp the--env-filevalues.drizzle-kit/src/cli/schema.ts— addsoptionEnvFile = string('env-file').desc(...)and includes it on every subcommand'soptionsblock so it shows up in--help. The handler never reads it (the loader has already consumed it); it's purely documentation.drizzle-kit/src/cli/validations/common.ts— extendsassertCollisionsto excludeenvFilefrom the exhaustiveness check the same wayconfigis excluded, since it's an out-of-band option.Tests
drizzle-kit/tests/cli-env-file.test.ts(vitest, 9 cases):extractEnvFiles:--env-file=path,--env-file path,-e=path,-e path, multiple occurrences in declaration order, no-flag case.applyEnvFiles: single file loads, shell vars not overwritten, later file wins over earlier file, shell var still wins over multi-file overrides.Existing
cli-migrate.test.ts/cli-generate.test.tscontinue to pass — verified locally.Compatibility
dotenvwas already a (dev) dep.--env-fileis byte-for-byte unchanged (the auto-loaded.envstill loads fromschema.ts).DATABASE_URLvia the shell continue to take precedence over any--env-file.