Skip to content

chore(deps): bump dotenv to 18.0.5 - #16

Merged
agentHits merged 4 commits into
AgentHits-Devfrom
chore/deps-dotenv
Oct 7, 2026
Merged

agentHits merged 4 commits into
AgentHits-Devfrom
chore/deps-dotenv

Conversation

@agentHits

Copy link
Copy Markdown
Collaborator

What changed

  • dotenv 16.6.1 → 18.0.5 in every workspace: root devDependency, apps/dokploy, packages/server (exact pins), apps/api and apps/schedules (^18.0.5). bun.lock only changes the top-level dotenv entry; the nested 17.4.2 copies used by @dotenvx/dotenvx and auth are untouched.
  • apps/dokploy/server/server.ts and apps/dokploy/esbuild.config.ts: the explicit config() calls now pass quiet: true.
  • No script, Dockerfile or entry-file changes: node -r dotenv/config …, tsx -r dotenv/config … and import "dotenv/config" stay as they are (see below).

Release notes that matter here

  • 17.0.0: quiet defaults to false, so config() prints injected env (N) from .env.
  • 18.0.0: that line goes to stderr; tips, .env.vault support and "preloading" are removed; new dotenv run -- cmd CLI and an opt-in fast parser (fast: true). The default parser is still the classic regex parser.
  • 18.0.4: dotenv/config defaults to quiet: true.

Why -r dotenv/config stays

The 18.0.0 changelog line "Removed preloading; use dotenv run" sounds like node -r dotenv/config stops working. It does not. I read the published 18.0.5 package:

  • exports["./config"] still points to dist/config.cjs, a CommonJS side-effect module, so both -r dotenv/config and import "dotenv/config" resolve.
  • What was removed is the argv parsing (node -r dotenv/config app.js dotenv_config_path=…, the old lib/cli-options.js). We never pass those arguments.
  • dist/config.cjs calls config({ quiet: true }) unless DOTENV_QUIET/DOTENV_CONFIG_QUIET is set. The README still describes it this way: "dotenv/config imports and preloads default to true".
  • parse() without fast uses the same LINE regex and the same unquote/\n expansion as 16.6.1. populate() still skips keys that are already in process.env unless override is set. A missing .env is still reported in the return value, not thrown.

I compared the candidates on a fixture .env with plain, export, single/double/backtick quotes, # inside and after values, multiline double and single quotes, escaped \", KEY: value, duplicate keys, an empty value and a key that is also set in the shell:

approach result vs 16.6.1 -r dotenv/config
18.0.5 -r dotenv/config identical output, no stderr
18.0.5 dotenv run -q -- identical values, but adds a wrapper Node process that re-spawns the child in its own process group and forwards signals
Node 24 --env-file-if-exists=.env differs: ESCQ="say \"hi\"" becomes say \, and KEY: value lines are dropped

In all three, the existing shell variable won over .env. Keeping -r dotenv/config is the only option that matches 16.6.1 exactly and keeps the process tree under tini the same (bun → sh → node). Node's native loader parses some values differently, so switching to it could quietly change values in .env.production. dotenv run would add a process and new signal handling around node dist/server.mjs.

One small new behaviour in 18: config() now also reads DOTENV_PATH/DOTENV_OVERRIDE/DOTENV_DEBUG/DOTENV_ENCODING/DOTENV_FAST (plus the DOTENV_CONFIG_* fallbacks) from the environment. Explicit options win. None of these are set in our images.

Verification

  • bun run typecheck: all 4 workspaces pass.
  • Env tests (__test__/env/*, deploy/env-file-literals-dockerfile, compose/env-file-literals, compose/env-file-preserved): 15 files, 180 tests pass.
  • Full apps/dokploy vitest run: 2052 passed, 10 failed. All 10 failures are timeouts or real-Docker tests. The machine was heavily loaded (load average ~47, other suites running in parallel):
    • application.real.test.ts (5) needs real Docker builds and is expected to fail locally.
    • better-auth-schema-compat, cloud-queue-availability, listen-deployment-boundary and db-backup-restore-injection hit 5 s/10 s timeouts. Rerun with --testTimeout/--hookTimeout=120000: 4 files, 32/32 pass.
    • compose/env-file-literals hit its 60 s timeout during the full run but passed in the targeted env run above.
  • bunx biome check on the changed files is clean.
  • Production start path: I built dist/ with bun run build-server (no injected-env line during the build) and ran it from a Docker-like layout (dist/, hoisted node_modules/, package.json, a temp .env):
    • bun run wait-for-postgres (the image's first CMD step) used DATABASE_URL, POSTGRES_WAIT_TIMEOUT and POSTGRES_WAIT_RETRY from .env.
    • With DATABASE_URL set in the shell, the shell value won over .env.
    • With no .env at all it started normally and used the shell value.
    • bun run start: migration.mjs connected to the host from .env (ENOTFOUND on the fake host) and the && chain stopped there as before.
    • tsx -r dotenv/config (dev scripts) loaded .env, and the shell value won.
    • None of these runs printed an injected env line.
    • I deleted the build output and temp files afterwards.

Manual check on dev

  • After the rollout, check that the dokploy container logs have no ◇ injected env line, and that the app reaches Postgres, which shows that .env (copied from .env.production) was loaded.
  • Check the schedules and api containers start and read their env the same way (import "dotenv/config").
  • I did not run next build locally; CI covers it.

🤖 Generated with Claude Code

agentHits and others added 4 commits October 6, 2026 16:46
Move every workspace from dotenv 16.6.1 to 18.0.5.

Since 17.0.0, config() logs an "injected env" line unless quiet is set,
and 18 prints it to stderr. Pass quiet: true to the two explicit
config() calls (server entry and esbuild config) so startup and build
output stay unchanged. dotenv/config sets quiet: true itself since
18.0.4, so the `-r dotenv/config` scripts and `import "dotenv/config"`
entries stay silent.

The 18.0.0 "removed preloading" entry drops the dotenv_config_* argv
options of dotenv/config. The module itself still exists and loads
.env from the cwd with the same regex parser and no-override populate,
so the `-r dotenv/config` scripts keep working unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@agentHits
agentHits merged commit 37809a1 into AgentHits-Dev Oct 7, 2026
8 checks passed
@agentHits
agentHits deleted the chore/deps-dotenv branch October 7, 2026 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant