oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.16k stars 2.77k forks source link

`env` variables are not loading in bun 1.0.36 or 1.1 #9877

Open vijaypushkin opened 7 months ago

vijaypushkin commented 7 months ago

What version of Bun is running?

1.0.36+40f61ebb9

What platform is your computer?

Linux 5.15.146.1-microsoft-standard-WSL2 x86_64 x86_64

What steps can reproduce the bug?

bun create vite my-app

cd my-app

echo  "VITE_BACKEND=https://api.example.com" > .env

bun i

bun dev

What is the expected behavior?

import.meta.env should have VITE_BACKEND

What do you see instead?

import.meta.env doesn't have VITE_BACKEND

Additional information

logging Object.keys(process.env) in vite.config.ts gives this in 1.0.36 / 1.1

[
  'BUN_INSTALL',
  'COLORTERM',
  'DBUS_SESSION_BUS_ADDRESS',
  'DENO_INSTALL',
  'DISPLAY',
  'EDITOR',
  'GIT_ASKPASS',
  'GREP_COLOR',
  'GREP_COLORS',
  'HOME',
  'HOMEBREW_CELLAR',
  'HOMEBREW_PREFIX',
  'HOMEBREW_REPOSITORY',
  'HOSTTYPE',
  'INFOPATH',
  'LANG',
  'LESS',
  'LESSOPEN',
  'LESS_TERMCAP_mb',
  'LESS_TERMCAP_md',
  'LESS_TERMCAP_me',
  'LESS_TERMCAP_se',
  'LESS_TERMCAP_so',
  'LESS_TERMCAP_ue',
  'LESS_TERMCAP_us',
  'LOGNAME',
  'LS_COLORS',
  'MANPATH',
  'NAME',
  'NODE',
  'NODE_ENV',
  'NVM_BIN',
  'NVM_CD_FLAGS',
  'NVM_DIR',
  'NVM_INC',
  'OLDPWD',
  'P9K_SSH',
  'P9K_TTY',
  'PAGER',
  'PATH',
  'PNPM_HOME',
  'PULSE_SERVER',
  'PWD',
  'SHELL',
  'SHLVL',
  'TERM',
  'TERM_PROGRAM',
  'TERM_PROGRAM_VERSION',
  'USER',
  'USER_ZDOTDIR',
  'VISUAL',
  'VSCODE_GIT_ASKPASS_EXTRA_ARGS',
  'VSCODE_GIT_ASKPASS_MAIN',
  'VSCODE_GIT_ASKPASS_NODE',
  'VSCODE_GIT_IPC_HANDLE',
  'VSCODE_INJECTION',
  'VSCODE_IPC_HOOK_CLI',
  'VSCODE_NONCE',
  'WAYLAND_DISPLAY',
  'WSL2_GUI_APPS_ENABLED',
  'WSLENV',
  'WSL_DISTRO_NAME',
  'WSL_INTEROP',
  'XDG_RUNTIME_DIR',
  'ZDOTDIR',
  '_',
  '_P9K_SSH_TTY',
  '_P9K_TTY',
  'npm_config_local_prefix',
  'npm_config_user_agent',
  'npm_execpath',
  'npm_lifecycle_event',
  'npm_node_execpath',
  'npm_package_json',
  'npm_package_name',
  'npm_package_version'
]

whereas bun 1.0.35 has VITE_BACKEND

[
  'BUN_INSTALL',
  'COLORTERM',
  'DBUS_SESSION_BUS_ADDRESS',
  'DENO_INSTALL',
  'DISPLAY',
  'EDITOR',
  'GIT_ASKPASS',
  'GREP_COLOR',
  'GREP_COLORS',
  'HOME',
  'HOMEBREW_CELLAR',
  'HOMEBREW_PREFIX',
  'HOMEBREW_REPOSITORY',
  'HOSTTYPE',
  'INFOPATH',
  'LANG',
  'LESS',
  'LESSOPEN',
  'LESS_TERMCAP_mb',
  'LESS_TERMCAP_md',
  'LESS_TERMCAP_me',
  'LESS_TERMCAP_se',
  'LESS_TERMCAP_so',
  'LESS_TERMCAP_ue',
  'LESS_TERMCAP_us',
  'LOGNAME',
  'LS_COLORS',
  'MANPATH',
  'NAME',
  'NODE',
  'NODE_ENV',
  'NVM_BIN',
  'NVM_CD_FLAGS',
  'NVM_DIR',
  'NVM_INC',
  'OLDPWD',
  'P9K_SSH',
  'P9K_TTY',
  'PAGER',
  'PATH',
  'PNPM_HOME',
  'PULSE_SERVER',
  'PWD',
  'SHELL',
  'SHLVL',
  'TERM',
  'TERM_PROGRAM',
  'TERM_PROGRAM_VERSION',
  'USER',
  'USER_ZDOTDIR',
  'VISUAL',
  'VITE_BACKEND', // <------------------------------------ HERE
  'VSCODE_GIT_ASKPASS_EXTRA_ARGS',
  'VSCODE_GIT_ASKPASS_MAIN',
  'VSCODE_GIT_ASKPASS_NODE',
  'VSCODE_GIT_IPC_HANDLE',
  'VSCODE_INJECTION',
  'VSCODE_IPC_HOOK_CLI',
  'VSCODE_NONCE',
  'WAYLAND_DISPLAY',
  'WSL2_GUI_APPS_ENABLED',
  'WSLENV',
  'WSL_DISTRO_NAME',
  'WSL_INTEROP',
  'XDG_RUNTIME_DIR',
  'ZDOTDIR',
  '_',
  '_P9K_SSH_TTY',
  '_P9K_TTY',
  'npm_config_local_prefix',
  'npm_config_user_agent',
  'npm_execpath',
  'npm_lifecycle_event',
  'npm_node_execpath',
  'npm_package_json',
  'npm_package_name',
  'npm_package_version'
]

vite version - 5.2.7

subodhpareek18 commented 7 months ago

My .env.local file was not loading but renaming it to .env worked

Can confirm the behavior on both 1.0.36 and 1.1

For the .env file working it could also be a behavior coming from nextjs which is the stack I'm using

redbmk commented 7 months ago

I'm just upgrading from around 1.0.30 to 1.1.1 and noticing this.

Previously, opening anything in bun would pass env vars along (e.g. when running a script that calls node). You can see this checking that the envs are available after running bun run sh:

❯ docker run -it oven/bun:1.0.30-alpine sh
/home/bun/app # echo HELLO=world > .env
/home/bun/app # echo $HELLO

/home/bun/app # bun -e 'console.log(process.env.HELLO)'
world
/home/bun/app # bun run sh -c 'echo $HELLO'
world
/home/bun/app # bun run sh
/home/bun/app # echo $HELLO
world
/home/bun/app # 

But in 1.1.1 (sounds like it may have been introduced around 1.0.36?), it's acting more like X=Y instead of export X=Y

❯ docker run -it oven/bun:1.1.1-alpine sh
/home/bun/app # echo HELLO=world > .env
/home/bun/app # echo $HELLO

/home/bun/app # bun -e 'console.log(process.env.HELLO)'
world
/home/bun/app # bun --print 'process.env.HELLO'
world
/home/bun/app # bun run sh -c 'echo $HELLO'

/home/bun/app # bun run sh
/home/bun/app # echo $HELLO

/home/bun/app # 
lostpebble commented 7 months ago

Yea quite a regression for us too. Changing over from WSL to just using Bun on windows (1.1.1), and we didn't have issues before, but were still running on older version on WSL where the .env.local file was picked up without issue.

This is just using the bun run ./some/script.ts syntax- where we expect our .env.local files to be picked up in the CWD.

JoBurgard commented 7 months ago

I have the same problem.

My current workaround is this: bun --env-file=.env run [...]

lostpebble commented 7 months ago

Using the latest version 1.1.3 seems to have resolved it for me- can you guys confirm?

subodhpareek18 commented 7 months ago

No it still doesn't work for me. To clarify further, the issue is when running it via package.json scripts bun run ..., it does pick up the env variable when running directly via bun ./script.ts

chribjel commented 6 months ago

bun doesn't pick up .env.local in 1.1.4 either.

running bun payload:generate doesn't work, but bun --env-file=.env.local payload:generate works.

redbmk commented 6 months ago

Still working on getting my dev environment set up to build bun but I was able to write some tests that pass with 1.0.30 and fail with 1.1.5

https://github.com/oven-sh/bun/commit/90d49af21d1d02ac78e7b267bc322b6c3dbb3658

redbmk commented 6 months ago

@paperdave I'm working through trying to fix this issue, but would like to hear your thoughts on it. I believe these started breaking between 1.0.35 an 1.0.36, specifically in 1ae9f998f4541c445c522a10a0184dad20ef5cc1 (#9689) to fix #9635.

Reading through those issues and this comment:

            // Do not automatically load .env files in `bun run <script>`
            // Instead, it is the responsibility of the script's instance of `bun` to load .env,
            // so that if the script runner is NODE_ENV=development, but the script is
            // "NODE_ENV=production bun ...", there should be no development env loaded.
            //
            // See https://github.com/oven-sh/bun/issues/9635#issuecomment-2021350123
            // for more details on how this edge case works.

it sounds like the intent is for bun run to only include environment variables when running a command directly, but essentially scripts in package.json wouldn't get them unless they explicitly call bun run; Is that right? The issue I'm running into is that I use some scripts that call node (e.g. via a shebang) and don't work just yet with --bun (I've had issues getting prisma to work properly with pure bun, for example). But as of that change, any environment variables I've loaded don't get passed to the script, making the default env loader not very useful. The only workaround I can think of is to include dotenv-flow as a dependency, which the docs say shouldn't be needed anymore. This is preventing us from upgrading past 1.0.35, but I'd really love to start using --filter.

I have some tests that I wrote for this (https://github.com/redbmk/bun/commit/2de357bf360a2cf79921b95605a9c55330897fbe) but if I get them to pass then the NODE_ENV=production tests end up failing. I'm hoping there's a good compromise here. I just wanted to get your thoughts on this before I sink too much time into a wontfix.

(btw, I saw some TODOs that mention not needing to do something until --filter is implemented, but didn't that ship recently?

            // TODO: remember to free this when we add --filter or --concurrent
            // in the meantime we don't need to free it.
redbmk commented 6 months ago

I see the dilemma though. With something like dotenv it's usually called at the script's entrypoint or explicitly via the CLI. In this case, bun is potentially loading envs before touching any js. Then even if you have NODE_ENV unset by default and set it to production inside a package json script, you've already loaded the .env variables into the shell so they will take precedence over anything in .env.production which would normally override .env.

I feel like the documentation could at least use updating to reflect this, but what if we introduce a new argument to choose the behavior? Something like bun --dotenv could work like dotenv-flow --, but by default we use the existing behavior. Maybe the default could even be set in bunfig.toml depending on how the project wants to use it - something like dotenv = shallow | export?

For a more real-world example of the issue I'm facing, I use prisma with postgres, and to connect to the database for debugging I use psql. Since the local dev url is kept in .env I found it convenient to have a script in package.json:

{"scripts": {"sql": "psql $(echo $DATABASE_URL | cut -d'?' -f1)"}}

It looks like newer versions of bun (somewhere between 1.0.36 and 1.1.6) allow you to just run a shell script like bun sql.sh, so perhaps the workaround here would be to create shell scripts that do the work and package.json scripts can just be a light wrapper around those but would need to call bun explicitly. e.g.

scripts/sql.sh

psql $(echo $DATABASE_URL | cut -d'?' -f1)

package.json

{"scripts": {"sql": "bun scripts/sql.sh"}}

We could call bun scripts/sql.sh or essentially bun sql is just an alias for that

redbmk commented 6 months ago

I've been playing around with 1.1.6 more today and after converting some scripts from bun run and moving that inline shell script to an actual shell script, things seem to be working OK.

I feel like this ticket isn't really so much an issue with the code but the documentation probably could be updated to be a little more clear on how it works.

.env.local and .env are both loading fine for me but I'm curious if @vijaypushkin is still having issues with vite. import.meta.env seems to work for me in some basic testing

Poolshark commented 6 months ago

I have the same issue with 1.1.6 and codegen.ts. However, I am actually already using package.json scripts as a light wrapper with a script attached to the command. Unfortunately, this gives me the same error. I am using Bun.spawnSync() inside the script.

A workaround would be checking for the branch name and use bun --env-file=.env.<branch_identifier> <script_name>.

redbmk commented 6 months ago

Hmm, yeah actually now I'm running into an issue where it's not working again.

{ "scripts": { "cypress:open": "cypress open" } }

If I run this with bun cypress:open or bun run cypress:open, it doesn't get any of my variables from .env.

I tried changing the script to bunx cypress open thinking I need to run bun again in there, but that didn't help. The only thing that worked was changing the script to use bunx --bun cypress open.

This is node_modules/.bin/cypress:

#!/usr/bin/env node

require('../lib/cli').init()

So it seems the issue is that it's explicitly calling node and the variables aren't actually in the env.

In this case, --bun seems to work, but there are going to be some packages that still aren't fully compatible with Bun.


EDIT: I take it back about cypress working with --bun. It gets confused now and throws this error trying to read a typescript file:

You are attempting to run a TypeScript file, but do not have TypeScript installed. Ensure you have 'typescript' installed to enable TypeScript support.

EDIT 2: This feels like a terribly convoluted workaround, but solves my issue:

~/scripts/bunrun.sh

bun run $1

~/zshrc

alias bunrun="bun ~/scripts/bunrun.sh"

now instead of bun run cypress:open I can do bunrun cypress:open and everything works the way it did pre-1.0.36.

This is super limited - I would do alias bun="/path/to/bun ~/scripts/bundotenv.sh" and have the script be bun $@ as a better workaround, but apparently $@ isn't supported yet. Not sure if there's an issue for this but searching for $@ turns up nothing in github. Not sure the search can handle special chars like that

zulrang commented 5 months ago

Having this issue in 1.1.8, but only during bun test

~/buntest$ bun --version
1.1.8
~/buntest$ echo 'k=v' > .env.local
~/buntest$ echo "console.log(process.env.k)" > index.test.js
~/buntest$ bun index.test.js 
v
~/buntest$ bun test
bun test v1.1.8 (89d25807)

index.test.js:
undefined

 0 pass
 0 fail
Ran 0 tests across 1 files. [8.00ms]
~/buntest$ mv .env.local .env
~/buntest$ bun test
bun test v1.1.8 (89d25807)

index.test.js:
v

 0 pass
 0 fail
Ran 0 tests across 1 files. [7.00ms]
vijaypushkin commented 5 months ago

Hey @redbmk, still facing the same issue with version 1.1.12. Neither process.env (in vite.config) nor import.meta.env (in react files) loads for me

cblberlin commented 4 months ago

Hey @redbmk , got another issues with version 1.1.18 on next.js app router project, process.envload but got the wrong variable because i changed the variable, but it just didn't reload it after i rm -rf .next and rm -rf node_modules

marsch commented 1 month ago

+1 - I really do think this is vital

4e576rt8uh9ij9okp commented 1 month ago

I don't know what I'm doing wrong but my env variables are also undefined. I tried with Bun.env same as process.env, both don't have my variables.

.env

PORT=3030

trying

console.log(Bun.env.PORT)

Returns undefined.