expo / eas-cli

Fastest way to build, submit, and update iOS and Android apps
https://docs.expo.dev/eas/
MIT License
781 stars 81 forks source link

Environment variables don't seem to be detected in build #2195

Open JorensM opened 8 months ago

JorensM commented 8 months ago

Build/Submit details page URL

https://expo.dev/accounts/jorensm/projects/app/builds/3dcb9d5c-dfb2-487d-a6e5-8ce5c65b2288

Summary

So I'm trying to add environment variables to my EAS build. I've added them in my eas.json file, like so:

env vars

But they don't seem to be detected in my build. I have a validator function that throws an error if the env variables are not set, and its throwing it in my builds, thought it works fine with Expo Go.

Managed or bare?

Managed

Environment

expo-env-info 1.2.0 environment info: System: OS: Windows 10 10.0.19045 Binaries: Node: 20.8.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.17 - ~\AppData\Roaming\npm\yarn.CMD npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD SDKs: Android SDK: API Levels: 30, 31, 33 Build Tools: 30.0.2, 30.0.3 IDEs: Android Studio: Version 2020.3.0.0 AI-203.7717.56.2031.7678000 npmPackages: @expo/webpack-config: ^19.0.0 => 19.0.0 expo: ~49.0.15 => 49.0.21 expo-router: ^2.0.0 => 2.0.14 react: 18.2.0 => 18.2.0 react-dom: 18.2.0 => 18.2.0 react-native: 0.72.6 => 0.72.6 react-native-web: ~0.19.6 => 0.19.10 Expo Workflow: managed

expo-doctor didn't find any issues

Error output

No response

Reproducible demo or steps to reproduce from a blank project

This is the file that loads my env variables. On Expo Go it doesn't throw an error but on a EAS build it does.

// Constants from environment variables

const ENV_VARIABLE_NAMES = [
    'API_URL',
    'STRIPE_PUBLISHABLE_KEY',
    'SUPABASE_URL',
    'SUPABASE_KEY'
]

const validateEnvVariables = () => {
    const missing_vars = []
    for(const var_name of ENV_VARIABLE_NAMES) {
        const full_var_name = 'EXPO_PUBLIC_' + var_name
        if(!process.env[full_var_name]) {
            missing_vars.push(full_var_name)
        }
    }

    if (missing_vars.length > 0) {
        throw new Error('Missing the following environment variables: ' + missing_vars.join(', '))
    }
}

validateEnvVariables();

export const API_URL = process.env.EXPO_PUBLIC_API_URL!;
export const SUPABASE_URL = process.env.EXPO_PUBLIC_SUPABASE_URL!;
export const SUPABASE_KEY = process.env.EXPO_PUBLIC_SUPABASE_KEY!;
export const STRIPE_PUBLISHABLE_KEY = process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY!;
JorensM commented 8 months ago

Apparently Expo only supports dot notation for accessing env variables. Which is strange because it worked with Expo Go. I'll try changing the validator to use dot notation and report back.

JorensM commented 8 months ago

Update: After changing my validator to use dot notation, I'm still getting the same error about missing env vars

JorensM commented 8 months ago

When I run the build command it does show in the CLI that the env variables were added:

console output

Whereas in my EAS build logs, under Spin up build envrionment it doesn't show the env variables (though I'm not sure if it should)

szdziedzic commented 7 months ago

Hi there,

I wanted to check your build logs, but they are expired. Are you still facing this issue? If so may I ask you to run the build once again and send me the link?

JorensM commented 7 months ago

@szdziedzic I'm not working on this project anymore as my client decided to pivot, but I'll try to re run the build when I have some free time

i-mighty commented 7 months ago

Can confirm this a real issue I am facing.

ermamud commented 6 months ago

I am having the same issue as well

EmilChigu commented 6 months ago

Also having the same issue except i can actually see them in the spin up build environment step. However when i publish my app, they are not there.

Screenshot 2024-03-01 at 09 36 06

pariah140 commented 6 months ago

Hello was this solved. I have the same issue. It works fine in expo go but when I run a dev build they are all undefined.

Inalegwu commented 5 months ago

Has anyone found a solution to this issue yet ?

anup-a commented 5 months ago

I had a similar issue, while doing local eas build. Everything looks to be working well with expo builds, but fails during eas local builds.

It appears that I needed to set the environment variables for the execution of build command. So, here is what I did -

  1. created a bash script set-env.sh (It reads your .env file, and sets the environment)
    
    #!/bin/bash

if [ $# -lt 1 ]; then echo "Usage: $0 " exit 1 fi

(env $(cat .env | xargs) "$@")


2. Run - `sh set-env.sh eas build --profile test --platform ios  --local`
ihaddy commented 4 months ago

this is still an issue, the above script by @anup-a doesn't work for me.

have a .env file and also a eas.json file

 "build": {
    "development": {
      "developmentClient": true,
      "env": {
        "EXPO_PUBLIC_BASE_URL": "....."}
       }
    }

still not working. kind of a big deal breaker and show stopper for running local builds where you can't leverage EAS cloud builds due to enterprise compliance reasons?

trying to call this in app code

  const response = await axios({
        method: method,
        url: `${process.env.EXPO_PUBLIC_BASE_URL || process.env.BASE_URL || 'did not load'}${url}`,
        data: body,
        headers: {
          'Content-Type': 'application/json',
          'securetoken': process.env.EXPO_PUBLIC_SECURE_TOKEN || process.env.SECURE_TOKEN || 'did not load' ,
          'Authorization': jwtToken ? `Bearer ${jwtToken}` : '',
          ...headers
        }
      });

i get 'did not load' in the development and production apk builds of the app ONLY, in expo go and the web browser it loads.

any advice?

jonra1993 commented 3 months ago

I have the same issue the environment variables appear in the expo logs console. But when I publish to play store the build of the app crashes because it says that the environment variable does not exist EXPO_PUBLIC_SUPABASE_URL. I works in development mode.

image
  expo-env-info 1.2.0 environment info:
    System:
      OS: macOS 13.6.7
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
      Yarn: 4.2.2 - ~/.nvm/versions/node/v20.11.1/bin/yarn
      npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm
      Watchman: 2024.01.22.00 - /usr/local/bin/watchman
    Managers:
      CocoaPods: 1.15.2 - /Users/jona/.rvm/gems/ruby-3.3.0/bin/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 23.2, iOS 17.2, macOS 14.2, tvOS 17.2, visionOS 1.0, watchOS 10.2
    IDEs:
      Android Studio: 2023.2 AI-232.10300.40.2321.11567975
      Xcode: 15.2/15C500b - /usr/bin/xcodebuild
    npmPackages:
      expo: ~51.0.9 => 51.0.9 
      expo-router: ~3.5.14 => 3.5.14 
      react: 18.2.0 => 18.2.0 
      react-native: 0.74.1 => 0.74.1 
      react-native-web: ^0.19.11 => 0.19.11 
    npmGlobalPackages:
      eas-cli: 9.1.0
      expo-cli: 6.3.10
    Expo Workflow: bare
KristianLentino99 commented 3 months ago

I have the same issue here

sthay8f commented 3 months ago

I have the same issue today.

The environment variable is correct when Spin up build environment in Logs.

圖片

圖片

dawidvdh commented 3 months ago

Yeah this is really problematic for me also, on production builds the env vars just are not present.

Varofon commented 3 months ago

Similar-ish issue here. npx expo run:android works fine and loads all EXPO_PUBLIC_ env variables from .env But npx expo run:android --variant release says that it loads variables in log, but process.env only has NODE_ENV in it

hkhawar21 commented 3 months ago

Facing a similar issue Env variables are loaded when running the application in development client mode or with expo go but no env variables are loaded with npx expo start --no-dev --minify

dawidvdh commented 3 months ago

Yeah this is really problematic for me also, on production builds the env vars just are not present.

In the end this was me missing a vital piece of documentation on the standard env resolution I had a .env.ci which although is not listed there seems to have taken preference over .env and so it appeared empty but in actual fact those values in the .env.ci file did not exist.

Weird gotcha, but I resolved this by combining the CI and app envs into a single .env.

Anis-Ghliss commented 3 months ago

I am facing the same issue, although the env variable is detected in dev mode, it is not when I run eas build, even though the logs show that it is loaded

saifborghol commented 2 months ago

You need to add EXPOPUBLIC befor each variable Folow this example Capture d'écran 2024-06-26 232758 https://docs.expo.dev/guides/environment-variables/#migrating-to-expo-environment-variables

cameronmurphy commented 2 months ago

This is annoying. local-build-plugin does not copy any .env files into the build dir when doing an EAS build locally. Currently the only way to get environment variables into the build is to manually export them before running eas build as per @anup-a's answer.

yogendra-meta commented 2 months ago

I even manually exported them, still facing the issue, no env vars were being read

magix022 commented 2 months ago

Having the same issue here, I can see the variable in the eas spin-up build environment too but its not there in the app.

rafaelgrilli92 commented 2 months ago

I'm having the exact same issue! I can't make the production build app work because the ENV are not present anymore. It all started after updating from Expo 49 to 50!!! This is ridiculous!

samimenouar commented 2 months ago

Well, that's weird. If I have console.error(process.env); before using the environement variables, everything works (even in Release mode). But as soon as I take it out, the variable is not available and the app crashes...

rafaelgrilli92 commented 2 months ago

Well, that's weird. If I have console.error(process.env); before using the environement variables, everything works (even in Release mode). But as soon as I take it out, the variable is not available and the app crashes...

@samimenouar , That's very strange! Have you built the apk and the env variables work after you console.log the process.env?

dragospeta commented 1 month ago

I managed to find a solution. (Was pretty scared to see an opened issue from January)

I added my env in eas.json, ex:

"preview": {
    "distribution": "internal",
    "node": "18.18.2",
    "yarn": "1.22.19",
    "env": {
        "EXPO_PUBLIC_API_URL": "https://www.some_url.com/api",
    }
}

I wrote in app.config.js (if you don't have it it's app.json and you have to rename it):

export default {
    expo: {
        name: "your app name",
        ....other config stuff
        extra: {
            ...
            EXPO_PUBLIC_API_URL: process.env.EXPO_PUBLIC_API_URL
        }
 }

Then i have a file named model.tsx and i used the expo-constants library (yarn add expo-constants, or npm install):

import Constants from "expo-constants";

const extra = Constants.expoConfig?.extra;

const API_URL = extra?.EXPO_PUBLIC_API_URL ?? "";

export { API_URL }

Now everywhere i import import { API_URL } from "./model"; it has the right value.

kaushiksahoo2000 commented 1 month ago

Can confirm the above works as well. Similar solution referenced in the Expo discord here

gcwill70 commented 1 month ago

For local builds, a workaround is to temporarily delete .env* from your .gitignore (so that it is unignored by git on your local machine) while running the local build command. This should include the .env file in the local build process.

For remote builds, you will have to split sensitive and non-sensitive values between expo.dev Secrets and eas.json respectively. You can upload expo.dev Secrets using eas secret:push. Non-sensitive values will unfortunately have to be repeated in eas.json. See this FAQ for further explanation.

brandtnewlabs commented 1 month ago

Same issue here. Took me a day to realise the EXPOPUBLIC… variables are undefined in production. App crashed on startup, as Supabase didn't get the right URL.

rafaelgrilli92 commented 1 month ago

This is a major issue and there's still no answer for it. I'm currently on the "on-demand" plan in EXPO Dev, which means I pay $1 every time I do a build, and before I realised that this was an issue with EXPO, and not my code, I did at least 5 builds + the time and effort wasted on trying to find an issue that is not even in my application. We need this fixed ASAP!!!

SwhiteMHC commented 1 month ago

I am also experiencing this issue. When values are defined in my .env file as EXPO_PUBLIC_VAR, and in my eas.json, when running locally none of the variables appear.

zollipaul commented 1 month ago

For me, the script below successfully makes the environment variables available for eas build, since it directly sources the .env file in the current shell context. This is more reliable and ensures that all environment variables are properly loaded and available for the eas build command

set-env.sh:

#!/bin/bash

# Load environment variables
set -a; source .env; set +a

# Execute command passed as arguments to this script
"$@"

run it like this: ./set-env.sh eas build --profile preview:device --platform ios --local

Ception commented 3 weeks ago

router

You. Are. A. Godsend. After 4 hours of beating my head against the wall and trying everything under the sun, including reading dozens of doc files, and tons of stackoverflow. This was the only solution that worked.

I can confirm this actually worked. Just a small correction to this:

I wrote in app.config.js (if you don't have it it's app.json and you have to rename it):

You do not need to rename your app.json to app.config.js, I'm sure they both work the same, but you can keep your existing app.json and add on EXPO_SECRET_KEY to extra in app.json and it works just the same.

Thank youuuuuu!!!!

ppinel commented 3 weeks ago

Same issue for me and it took me a while to figure it out. iOS doesn't say anything, and crash report is useless. I'll use the workaround waiting for an official solution (?)

Thanks guys !

djMax commented 3 weeks ago

I still don't understand what's at play here. This is basically eas-cli's whole job, and it USED to work. Latest versions 11.x break environment variable resolution.

kutsan commented 3 weeks ago

In addition to expo-constants instructions above, my approach was to use the dotenv-cli package. This tool loads environment variables into the current shell context. You can create a script in package.json to use with eas-cli. I think this is as clean as it gets.

npm i dotenv-cli -D

For .env.development file, you can use:

"build:android": "dotenv -c development -- eas build --platform android --profile preview --local",

Package docs: https://www.npmjs.com/package/dotenv-cli

Cancuuu commented 3 weeks ago

I waste time and money with this issue, please fix it ASAP! Im willing to help if you need it @expoteam

mjko2000 commented 3 weeks ago

Did you guys try to change to

presets: ['babel-preset-expo']

in babel.config.js ?

sanchit-bhalla commented 2 weeks ago

This fix works for me but there might be a better way to fix it. Basically what I have observed is that when the .env file is gitignored then environment variables are not loaded. So before generating the build we need to remove it from the .gitignore file.

  1. Before running the build command, remove .env from the .gitignore file and save the .gitignore file.
  2. Then run the build command eas build --platform android --profile preview
  3. After the build is generated, add .env back to .gitignore file

I only have .env file and didn't add env property in the eas.json

Cancuuu commented 2 weeks ago

This fix works for me but there might be a better way to fix it. Basically what I have observed is that when the .env file is gitignored then environment variables are not loaded. So before generating the build we need to remove it from the .gitignore file.

  1. Before running the build command, remove .env from the .gitignore file and save the .gitignore file.
  2. Then run the build command eas build --platform android --profile preview
  3. After the build is generated, add .env back to .gitignore file

I only have .env file and didn't add env property in the eas.json

Thats an interest solution, do you think that is the same for local build (with --local flag)?? this command for example 👉 eas build --platform android --local

sanchit-bhalla commented 2 weeks ago

I haven't tried building locally yet but if you are facing the issue because the environment variables are not loaded properly, you can try this way.

lgustavosoftwareengineer commented 1 week ago

I managed to find a solution. (Was pretty scared to see an opened issue from January)

I added my env in eas.json, ex:

"preview": {
    "distribution": "internal",
    "node": "18.18.2",
    "yarn": "1.22.19",
    "env": {
        "EXPO_PUBLIC_API_URL": "https://www.some_url.com/api",
    }
}

I wrote in app.config.js (if you don't have it it's app.json and you have to rename it):

export default {
    expo: {
        name: "your app name",
        ....other config stuff
        extra: {
            ...
            EXPO_PUBLIC_API_URL: process.env.EXPO_PUBLIC_API_URL
        }
 }

Then i have a file named model.tsx and i used the expo-constants library (yarn add expo-constants, or npm install):

import Constants from "expo-constants";

const extra = Constants.expoConfig?.extra;

const API_URL = extra?.EXPO_PUBLIC_API_URL ?? "";

export { API_URL }

Now everywhere i import import { API_URL } from "./model"; it has the right value.

Works for me in combination with: https://github.com/expo/eas-cli/issues/2195#issuecomment-2315788322 solution

Ception commented 1 week ago

Solution for Using Environment Variables in Expo with EAS Build

After diving deep into Expo's documentation and blogs, I’ve finally figured out how to properly handle environment variables in Expo projects, especially with EAS builds. I’m sharing this to help others who might run into the same issues.

First, I recommend reviewing the following:

  1. Environment Variables in Expo
  2. Environment Variables and Secrets in EAS Build

How it Works

Step-by-Step Guide

  1. Create a .env file in your project root and prefix your variables with EXPO_PUBLIC_. For example:

    EXPO_PUBLIC_SUPABASE_ANON_KEY="eyJ..."
  2. To access these variables in your project, use:

    const myVariable = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY;
    console.log(`Proof that this loads: ${myVariable}`);
  3. For better accessibility, you can create a config.ts file:

    const config = {
      SUPABASE_URL: process.env.EXPO_PUBLIC_SUPABASE_URL ?? "",
      SUPABASE_KEY: process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY ?? "",
    };
    
    export default config;

Important Note:

.env files are not included in your EAS build by default.

Using Environment Variables in EAS Builds

If you want to use your local environment variables during EAS builds:

  1. Create the same variables in your Expo project’s secrets. You can find them here:
    https://expo.dev/accounts/<username>/settings/secrets

  2. Update your eas.json to tell EAS which secrets to use for specific branches (e.g., development, production):

    "development": {
      "autoIncrement": true,
      "developmentClient": true,
      "distribution": "internal",
      "env": {
        "EXPO_PUBLIC_SUPABASE_URL": "EXPO_PUBLIC_SUPABASE_URL",
        "EXPO_PUBLIC_SUPABASE_ANON_KEY": "EXPO_PUBLIC_SUPABASE_ANON_KEY"
      },
      "channel": "development"
    }

This tells EAS to look for EXPO_PUBLIC_SUPABASE_ANON_KEY in the secrets and retrieve its value during the build.

Pushing Secrets Directly from the Command Line

To avoid manually setting up secrets in the Expo dashboard, you can push your .env file directly:

eas secret:push --scope project --env-file .env

This will automatically upload your existing env to project specific secrets.

I hope this helps someone else in the future because dealing with this was a total nightmare! But now that I understand the flow of Expo’s configurations, it’s much clearer!

PS: If you have anything to add, or if you think I might’ve misunderstood something, I’m all ears.

A Few Key Notes:

marinoandrea commented 5 days ago

It looks like the use of EXPO_PUBLIC* env vars has some drawbacks. The docs do discuss how to centralize configuration variables based on channels (and prevent EAS Updates from overriding the vars set by EAS Build which is what I believe is happening to most people here, me included).

fellenabmb commented 1 day ago

I managed to find a solution. (Was pretty scared to see an opened issue from January)

I added my env in eas.json, ex:

"preview": {
    "distribution": "internal",
    "node": "18.18.2",
    "yarn": "1.22.19",
    "env": {
        "EXPO_PUBLIC_API_URL": "https://www.some_url.com/api",
    }
}

I wrote in app.config.js (if you don't have it it's app.json and you have to rename it):

export default {
    expo: {
        name: "your app name",
        ....other config stuff
        extra: {
            ...
            EXPO_PUBLIC_API_URL: process.env.EXPO_PUBLIC_API_URL
        }
 }

Then i have a file named model.tsx and i used the expo-constants library (yarn add expo-constants, or npm install):

import Constants from "expo-constants";

const extra = Constants.expoConfig?.extra;

const API_URL = extra?.EXPO_PUBLIC_API_URL ?? "";

export { API_URL }

Now everywhere i import import { API_URL } from "./model"; it has the right value.

This did work for me, I can now access env variables in both development an eas builds. Generally, i wouldn't complain when something is not working in an open source project. But in this case, the company where I work is paying per build in EAS, and having to do a workaround for this is honestly not good. I'd expect something as common and basic as environment handling to work properly when using a paid service.