iOS release build: .env.production.local file does not overwrite variables defined in base .env file
zarv1k opened this issue ยท 27 comments
- Asked question in discussions
- Tried the troubleshooting Wiki
- Followed the migration Wiki
In iOS release build, variables defined in base .env
file aren't overwritten by variables in .env.production.local
Reproduces only for iOS release builds. On Android there is no any issue.
To Reproduce
.env
file:
SOME_VAR1=var1
.env.production
file:
SOME_VAR2=var2
.env.production.local
file:
SOME_VAR1=overwrite-var1
SOME_VAR2=overwrite-var2
Expected behavior
console.log(SOME_VAR1); // overwrite-var1
console.log(SOME_VAR2); // overwrite-var2
Actual behavior Android (release)
console.log(SOME_VAR1); // overwrite-var1
console.log(SOME_VAR2); // overwrite-var2
Actual behavior iOS (release)
console.log(SOME_VAR1); // var1
- but it should be overwritten by value in .env.production.local
console.log(SOME_VAR2); // overwrite-var2
RN: 0.70.6
react-native-dotenv: 3.4.2, 3.4.6
babel.config.js:
plugins:[
//...
[
'module:react-native-dotenv',
{
moduleName: '@env',
path: '.env',
safe: false,
allowUndefined: true,
},
],
]
Hey, thank you for opening this issue! ๐ To boost priority on this issue and support open source please tip the team at https://issuehunt.io/r/goatandsheep/react-native-dotenv/issues/393
A bit more info:
- I don't use cache, it happens in CI that always starts a build from scratch by cloning repo into clean folder, then install npm deps etc.
- I don't use APP_ENV, but I tried it and it doesn't help
hm... did you set your XCode config? https://github.com/goatandsheep/react-native-dotenv/wiki/Multi-env-troubleshooting#xcode
@goatandsheep I do use XCode schemes + build configurations like described in https://shockoe.com/ideas/development/how-to-setup-configurations-and-schemes-in-xcode/, but I don't set NODE_ENV anywhere - just didn't find where should I do that. But anyway, after some experiments I realized that .env.production.*
files are used (so NODE_ENV=production in release configurations) like in issue description, but they aren't overwrite vars defined in base .env
file.
Also I didn't give Full Disk Access for XCode, like described in https://github.com/goatandsheep/react-native-dotenv/wiki/Multi-env-troubleshooting#xcode, but I don't think it matters for this case.
Thinking about giving Full Disk Access for XCode, but I don't understand for what case should I do that? Moreover I use cli for building apps with (XCode is not even opened).
Just tried to change set up for all release build configurations in XCode: for every Release build configuration added NODE_ENV=production
user defined setting.
Also gave Full Disk Access for XCode
Nothing helps, unfortunately :(
I know you're actively on this but I'll have to think longer on this. and also will need to improve some of the docs on caching and switching environments.
I don't think it's some cache, but who knows....
I wipe out the repo folder before build in CI, clone RN app repo again, yarn install, xcodebuild clean..., xcodebuild archive..., so metro starts on every build by "Start Packager" script in XCode build phase that looks like the following:
export RCT_METRO_PORT="${RCT_METRO_PORT:=8081}"
echo "export RCT_METRO_PORT=${RCT_METRO_PORT}" > "${SRCROOT}/../node_modules/react-native/scripts/.packager.env"
if [ -z "${RCT_NO_LAUNCH_PACKAGER+xxx}" ] ; then
if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then
if ! curl -s "http://localhost:${RCT_METRO_PORT}/status" | grep -q "packager-status:running" ; then
echo "Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly"
exit 2
fi
else
open "$SRCROOT/../node_modules/react-native/scripts/launchPackager.command" || echo "Can't start packager automatically"
fi
fi
It doesn't work if Metro is started with the build and runs on another shell:
APP_ENV=staging react-native run-ios
APP_ENV=staging react-native run-android
It works if Metro is started alone
APP_ENV=staging react-native start
I have a strong suspicion about what is happening here but I don't know why.
I added a bunch of console.log
into react-native-dotenv. I discovered that everything in .env
gets loaded into the environment. i.e. it exists in process.env when the babel transforms run.
So anything in the files is ignored because it exists in the environment.
I'm trying to work out what on the code side is pulling this into the environment.
I'm fairly sure it's code as my code push build, which calls metro directly, isn't affected.
I've worked this out for my particular use case.
I'm using sentry. sentry-cli
gets called as part of the xCode build process. Sentry supports .env files to load in things like SENTRY_DSN.
You can disable it by setting SENTRY_LOAD_DOTENV=0
Hi @johnf ! Yes that's exactly how this is supposed to work. Sorry if there's been confusion and that you had to do all that digging.
@goatandsheep Do you think it's worth adding an entry to the README specifically about sentry? I'm happy to create a PR
I've worked this out for my particular use case.
I'm using sentry.
sentry-cli
gets called as part of the xCode build process. Sentry supports .env files to load in things like SENTRY_DSN.You can disable it by setting
SENTRY_LOAD_DOTENV=0
I'm also using sentry-cli, so I'll try to set SENTRY_LOAD_DOTENV=0
and inform here
Hi @johnf I suppose that should be fine. Usually for specific use cases, I prefer to move it to the Wiki as the README is getting quite long. Do you think that this is prohibitive to people knowing how to use the library?
I have used Sentry before, but haven't setup the DSN before so looked on this page https://docs.sentry.io/product/cli/configuration/
I don't think this is a good recommendation so I don't think I should approve merging this to the README. My recommendation is to not push your keys to git and instead use the dashboards. This library is supposed to get the keys from the environment which is what the DSN does
Have you tried this out?
@goatandsheep What I want to add (wiki could be OK) is a warning about sentry.
I am setting SENTRY_DSN
in GitHub Action environment variables, but this happened to me.
My .env
looks like this (simplified example)
APP_VERSION="git"
It's committed to git and will be loaded in on developer machines. In the burger menu Version: git is displayed as the version of the app.
As part of the CI process, I grab the git tag being processed and write the following to .env.local
APP_VERSION="1.4.1"
This works without any issues for my android builds. But for my ios builds, I was getting Version: git
in my production app.
What was happening was this:
- Sentry overrides the code build process in Xcode to build the JS bundle and upload the source files
- It runs
sentry-cli react-native xcode ../node_modules/react-native/scripts/react-native-xcode.sh
- As part of this process, it has its own internal dotenv (using the go library, I believe)
- This loads
.env
but not.env.local
and sets the environment up forreact-native-xcode.sh
This means when react-native-dotenv runs you have process.env.APP_ENV
set to git
. Most importantly, Sentry ignores .env.local
.
This affects anyone who
- Uses sentry in their react-native app
- Has a variable in
.env
- Then changes it in
.env.local
The env.local
override will be ignored by react-native-dotenv because Sentry already loaded it into the environment.
From my perspective, this is completely unexpected behaviour from Sentry. I would never have expected that it supports .env
files, and you must read the documentation thoroughly and deeply to discover it.
So perhaps we can add a one-liner to the readme like
NOTE: If environment variables are not loading correctly and use are using Sentry refer to WIKIPAGE
The wiki page could then dive into something like my explanation above and how to use SENTRY_DOTENV_LOAD=0
Oh interesting. This happens for local Sentry not just on the server. That is really bizarre. Yes I'm happy to put this on the wiki
Yeah it happens where ever you're running sentry-cli to upload the artifacts.
I'll throw some text together and send it across for you to add a little later
Okay I will update this entry to what you recommend https://github.com/goatandsheep/react-native-dotenv/wiki/Additional-Troubleshooting#sentry
Btw instead of setting to .env.local why don't you set the value in your environment variables in shell in the CI script. Shell variables take precedence.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I can confirm that env variables are only overwritten on android and not on ios. The behavior is different. If a var exists in .env AND in .env.production, when building for production the .env.production won't be used on ios where it will on Android
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This link https://shockoe.com/ideas/development/how-to-setup-configurations-and-schemes-in-xcode/ is not working mentioned here in docs https://github.com/goatandsheep/react-native-dotenv/wiki/Multi-env-troubleshooting#xcode
same issue here. do you have any suggestions about how to fix it or any workaround? thanks.
I am not sure if it will help you but I am just checking my old git commit to what files I changed to make it work
I modified or created only these files:
- .env
- .env.development
- babel.config.js include 'module:react-native-dotenv',
Now when I run the the app in dev mode react-native run-ios
then it simply picks the variables from .env.development but when I create a release build it takes the variables from .env files.