Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eas update: build eas environment variables are not automatically passed to update #1265

Closed
redcranesolutions opened this issue Aug 10, 2022 · 50 comments
Labels
needs review Issue is ready to be reviewed by a maintainer

Comments

@redcranesolutions
Copy link

redcranesolutions commented Aug 10, 2022

Build/Submit details page URL

https://expo.dev/accounts/redcranejapan/projects/renraccoon-parent/

Summary

When publishing an eas update, the build eas environment variables are not automatically passed to update. Docs state that the only way to pass env variables are via command lines such as "API_URL="https://prod.example.com" eas update --branch production". It does not give any info about previous build envs being passed or not. Currently it seems the case is the latter. What it does say is if you only have a few env's to pass, just add them in the command prompt before eas update, however, isn't the whole concept of eas, it's channels and branches is to pass those env variables on and thus to make quick eas updates to that branch and then on to the channels connected to that branch. Currently, if you do not pass new env variables as stated above, env's result null/undefined.

Unless, I've made a mistake (and if so then the docs need to be more clear), the current way of updating projects is troublesome to say the least. In our case we have a whole list of env's and I personally don't want to be typing 20 lines of env before "${allTheEnvs} eas update --branch [branchName]" in console for every update that should be as simple as typing "eas update --branch [branchName]" and those changes being passed on to that branch and it's channels. Please someone tell me this is not the new way of eas updates and I am totally wrong...

https://docs.expo.dev/eas-update/environment-variables/

Managed or bare?

managed

Environment

expo-env-info 1.0.5 environment info:
System:
OS: macOS 10.15.7
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 8.3.1 - ~/.nvm/versions/node/v16.14.0/bin/npm
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 14.3, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
IDEs:
Android Studio: 4.2 AI-202.7660.26.42.7351085
Xcode: 12.3/12C33 - /usr/bin/xcodebuild
npmPackages:
babel-preset-expo: ~9.2.0 => 9.2.0
expo: ^46.0.2 => 46.0.2
react: 18.0.0 => 18.0.0
react-dom: 18.0.0 => 18.0.0
react-native: 0.69.4 => 0.69.4
react-native-web: ~0.18.7 => 0.18.7
npmGlobalPackages:
eas-cli: 0.57.0
expo-cli: 6.0.1
Expo Workflow: managed

Error output

No response

Reproducible demo or steps to reproduce from a blank project

none

@redcranesolutions redcranesolutions added the needs review Issue is ready to be reviewed by a maintainer label Aug 10, 2022
@redcranesolutions
Copy link
Author

@brentvatne I'm tagging you as you were awesome in resolving the last problem I found with eas build/updates. Sorry in advance.

@redcranesolutions redcranesolutions changed the title eas update: build environment variables are not automatically passed to update eas update: build eas environment variables are not automatically passed to update Aug 10, 2022
@wkozyra95
Copy link
Contributor

This is expected behavior:

  • build section of eas.json is only for builds and when you run update there is no way to specify the build profile, so I don't see what suggests that envs would be passed to the update.
  • Secrets are by definition sensitive values, so they never should be included in updates, because anyone could just read them from js bundle.

@redcranesolutions
Copy link
Author

@wkozyra95 Thank you for your fast response. I've reread the docs and have used Updates.channel as suggested to switch between env's in an env.ts file. However, is there no way for eas update to retrieve secrets stored automatically or preferably that the secrets set in the initial eas build not be overwritten and read with in the app after an update is published? It seems that having secrets stored for eas builds are great, but totally useless if you want to publish an update and must manually add any secret that is stored in the command line before eas update. Thank you in advance.

@mvincent7891
Copy link

mvincent7891 commented Sep 20, 2022

I have the same exact question. We have secrets that are required for normal app functionality. These secrets are currently stored in and pulled from Expo secrets to enable EAS build and submit.

I've tried setting environment variables from the command line for EAS updates, but these secrets are also nulled out if they are not included. To be clear, I'm setting vars like API_URL from command line, but not setting secrets.

How are we to proceed with EAS updates if secrets can't be passed to the updated build? Any help is greatly appreciated - this feature would be killer if we could just fall back to the current build's env vars when the update does not include them.

@nicolinho22
Copy link

Please reopen this, as the questions asked here are valid and unanswered. As a new Expo user, I'd like to know how this works since the docs are unclear. I have a big application which uses a LOT of environment variables. I'm interested in EAS Updates but it mustn't override any environment variables set during the initial build.

@brentvatne
Copy link
Member

However, is there no way for eas update to retrieve secrets stored automatically or preferably that the secrets set in the initial eas build not be overwritten and read with in the app after an update is published? It seems that having secrets stored for eas builds are great, but totally useless if you want to publish an update and must manually add any secret that is stored in the command line before eas update.

as @wkozyra95 said: "Secrets are by definition sensitive values, so they never should be included in updates, because anyone could just read them from js bundle."

Please reopen this, as the questions asked here are valid and unanswered. As a new Expo user, I'd like to know how this works since the docs are unclear. I have a big application which uses a LOT of environment variables. I'm interested in EAS Updates but it mustn't override any environment variables set during the initial build.

I think there is certainly more that we can do here to improve the workflow around environment variables. Can you open a discussion on https://github.com/expo/expo/discussions with some ideas for how you would like this to work? Also if you can explain what you believe is unclear on the EAS Update environment variable docs we can definitely look into that. I'll leave the issue closed though, because "build eas environment variables are not automatically passed to update" is intended behavior.

@VinoSilva
Copy link

@brentvatne The issue is that I have a preview channel which I use to test the updates. When I want to deploy the updates to the production channel it is using environment variables meant for preview.

So my question here is that how do I push updates to production when it keep using preview environment variables?

@flolege
Copy link

flolege commented Oct 13, 2022

I have an similar issue. My app uses firebase and I created the respective secrets on my expo project and address them in app.config.js via process.env.. eas build is working fine. The app works.

Then I correct just a little typo in a text displayed in my app and run eas update.
The app crashes - most probably because eas update sets the secrets to null.

This is not a logical behavior. The update should not delete secrets which are necessary for fundamental app functionality and do not have to do with the update itself at all.

@dmitryame
Copy link

The expo documentation is either confusing or wrong.
In my app.config.js i have:

export default {
  expo: {
...
    extra: {
      API_URI: process.env.API_URI,
      API_KEY: process.env.API_KEY,
    },
...

In consts.js :

import Constants from 'expo-constants'
...
export const { API_URI, API_KEY } = Constants.manifest.extra

When I export API_URI and API_KEY env vars on my local box, expo start works just fine (does not work without the exports which is expected).

When I create build with eas build and submit it to the app store -- the app in the test flight can never connect to the API as it can't find the config values. I have created the secrets via expo UI -- nada.

It does not have to be this complicated. What am I missing?
Please help!

@jferrettiboke
Copy link

jferrettiboke commented Nov 3, 2022

@dmitryame Don't use Constants.manifest. That doesn't work nicely with OTA updates via EAS Update because it's null after an update. If you rely on that to be set, it will crash. It will make Expo to rollback immediately to its previous JS bundle which would result in no update.

On SDK 46, use Constants.expoConfig everywhere which works for both build and update.

Try with this:

const API_URI = Constants.expoConfig.extra.API_URI;
const API_KEY = Constants.expoConfig.extra.API_KEY;

Instead of this:

export const { API_URI, API_KEY } = Constants.manifest.extra

@dmitryame
Copy link

@jferrettiboke you are the best -- finally works for me and no need for dot env or other fancy solutions like babel plugins. Exactly as it supposed to be. I do wish expo simplified/cleaned their documentation a bit and made like one simple example which just works out of the box instead of providing tons of information where it's so easy to miss Constants.expoConfig vs Constants.manifest

@cseelus
Copy link

cseelus commented Nov 20, 2022

Unfortunately this doesn't work in platform 'web'.

Constants.expoConfig is empty there (works on 'android' and 'ios' though).

@OneLoneFox
Copy link

Am I the only one thinking that maybe the 'eas update' command should warn about env variables before executing? it's really easy to accidentally push an update with empty environment variables because they're either in another terminal session or just not set at all

@brentvatne
Copy link
Member

@OneLoneFox - i'd love that! do you have suggestions for how to accomplish that? we would need to be able to statically determine what all of the env vars are that the application depends on. we could do this by introducing our own abstraction on top of environment variables, but then we'd only be able to catch env var usage that flows through that abstraction. very interested in hearing proposals. so far, the best approach seems to be for developers to take care of ensuring that their project is in the correct state when they run update, since everyone has their own way of managing env vars.

@OneLoneFox
Copy link

Generally all the env vars MUST be set in eas.json at build time right? instead of building an abstraction layer on top of env variables and disrupt everyone's current workflow how about just reading the "env" keys under the profile/channel to update and reading said system variables, check if they're set and if not warn the developer about unset variables before proceeding, a warning should be enough since maybe for some unknown reason someone actually wants to unset a variable.

@balkrushnag
Copy link

@jferrettiboke you are the best -- finally works for me and no need for dot env or other fancy solutions like babel plugins. Exactly as it supposed to be. I do wish expo simplified/cleaned their documentation a bit and made like one simple example which just works out of the box instead of providing tons of information where it's so easy to miss Constants.expoConfig vs Constants.manifest

@dmitryame did it work for secrets as well? without including them in eas update command.
I am still unable to access the secrets after the eas update.

@dmitryame
Copy link

dmitryame commented Dec 30, 2022

I'm using Constants.expoConfig and prior to running eas build or eas update I export env vars -- that's how it works for me.

@Irfanwani
Copy link

@dmitryame check this link

@georgibakken
Copy link

Reading the comments in this thread, this and this, I understand env variables can be passed to EAS Update.

However, secrets can't be accessed with EAS Update ? Is that correct?

@Irfanwani
Copy link

@georgibakken what exactly do you mean by secrets, and where are they located?

@georgibakken
Copy link

I mean these secrets, that can for instance be stored on expo's website or in a GitHub action environment.

The one's on Expo's website can be accessed with EAS Build.

@Irfanwani
Copy link

Irfanwani commented Mar 8, 2023

Yes we can access them in eas build too. first you will create the secrets, or you can upload them from local env file too (if you have stored them in env file) eas secret:push --env-file path/to/.env (use --force flag you want to overwrite the secrets already present on expo server).
After creating a build using eas, they will be loaded into process.env and you can access them in app.config.js file (use dotenv).

So the whole app.config.js will look something like this;

import 'dotenv/config'

export default {
expo: {
...,

extra: {
SOME_NAME_FOR_SECRET: process.env.VAR_NAME_IN_ENV,
... // same for other secrets too
},
...
}

}

Then to access them in your code;

import Constants from 'expo-constants'; Constants.expoConfig.extra.SOME_NAME_FOR_SECRET

@georgibakken
Copy link

You write eas build, did you mean to write eas update?

I have secrets on expo's website, and have the setup with extra and constants as you describe. it works perfectly with eas build, but not eas update.

@balkrushnag
Copy link

You write eas build, did you mean to write eas update?

I have secrets on expo's website, and have the setup with extra and constants as you describe. it works perfectly with eas build, but not eas update.

Exactly, the secrets are not available with eas update. I need to run eas update with the secrets to make it work. This exposes the secrets on publicly accessible url https://u.expo.dev/{app_id} which is not a good thing.

@nickolas-wilson
Copy link

nickolas-wilson commented Mar 8, 2023

@Irfanwani I think you misunderstood, @georgibakken was asking about secrets securely stored in your project build profile on expo.dev and being used for EAS update, not EAS build. Eas build correctly fetches those variables on build time and they can be imported with "expo-constants" - Constants.expoConfig.extra.{secretName}. The problem is when you do an EAS update - unless you prepend those secrets before running eas-update, all your previous secret variables set at build-time are lost and result in your app crashing due to them being undefined.
Now, I'm pretty sure that this is still the case since I created this issue 7 months ago. So @georgibakken to answer your question, nope it can't be done when running Eas update and wanting to use your secured secrets on expo.dev, which makes expo.dev secrets absolutely useless for anyone wanting to use eas update locally.
However, in theory if you are setting up a ci/cd and store your secrets in GitHub and use actions, it maybe possible. In fact, just went and checked and found this, it might be the answer to all our problems - just means having to do a ci/cd pipeline to get it to work.

https://github.com/expo/expo-github-action#create-new-eas-update-on-push-to-main

Think I might set this up as well.

UPDATE:
Thanks to @balkrushnag and opening my eyes to the fact that our secrets can technically be publicly viewed. I'm going to rethink about even bothering with secret stored variables with expo.dev or locally and just move the processes that need them to our backend and then just do API calls.

@nickolas-wilson
Copy link

nickolas-wilson commented Mar 8, 2023

@balkrushnag I had no idea that our updates would expose our secrets so easierly.. Just checked one of my projects and can confirm it is possible to see them. It's been a while since I last checked the docs and at least they have updated them to vaguely warn you that EAS Secrets are intended to be used to provide values to an EAS Build job.

@Irfanwani
Copy link

@balkrushnag I had no idea that our updates would expose our secrets so easierly.. Just checked one of my projects and can confirm it is possible to see them. Has an issue been made about this? Surely something is wrong here?

I think expo does encrypt them and it is nearly impossible to make frontend that secure.

Anyway, if you want to make it secure, you can use some other ways like using a remote server to serve you credentials which you need on frontend and if possible, try to do all the operations which require important creds on backend.

@nickolas-wilson
Copy link

@balkrushnag I had no idea that our updates would expose our secrets so easierly.. Just checked one of my projects and can confirm it is possible to see them. Has an issue been made about this? Surely something is wrong here?

I think expo does encrypt them and it is nearly impossible to make frontend that secure.

Anyway, if you want to make it secure, you can use some other ways like using a remote server to serve you credentials which you need on frontend and if possible, try to do all the operations which require important creds on backend.

Yep, thats what I will do. It's only really one secret var that needs to be moved and had planned to move that process over to our backend anyway, so all good.

@Irfanwani
Copy link

Irfanwani commented Mar 8, 2023

You write eas build, did you mean to write eas update?

I have secrets on expo's website, and have the setup with extra and constants as you describe. it works perfectly with eas build, but not eas update.

Eas update does support secrets. But on every update you need to manually send the secrets again. Here is how you do that;
E.g, if our .env has two vars (and our secrets are same on expo too);

.env

BASE_URL=https://example.com
ANOTHER_VAR=somevalue

To send an update, you need to append the vars in front of the update command separated with a space;

BASE_URL=https://example.com ANOTHER_VAR=somevalue eas update --branch production --message "some message"

This is what eas has for now, as mentioned by @nickolas-wilson

@georgibakken
Copy link

Thank you so much for all the good answers, it makes sense now :)

@moxorama
Copy link

Main question - what is secure way to use expo secrets?

  • Secrets are exposed to environment variables during build.
  • If we pushing update - update overrides environment
  • Solution is to store it during build somewehere where it will not be overwritten via update.

But I can't create idea of correct workflow.

@MacPiston
Copy link

@moxorama Exactly, I'm dealing with this right now and I cannot wrap my head around on how stupid the current flow is. The whole point of build-time environment variables substitution is so they are not meant to be changed unless a new build is created, so I really don't get why EAS Update messes with them. I've been using extra field so far, then I've noticed that EAS Update had substituted them with undefined (essentialy bringing the whole app down) and I wanted to just inline these env's using babel plugin, but it turns out that this won't solve the problem. And now, I have to flood my CI with all these environment variables just to push an update... Or maybe I just don't see something there

@DevYuns
Copy link

DevYuns commented Apr 7, 2023

We can use dotenv with expo-updates 😄

dotenv -e .env -- eas update

@Irfanwani
Copy link

how to install dotenv to use this command?

@DevYuns
Copy link

DevYuns commented Apr 7, 2023

@Irfanwani In package.json :)

@Irfanwani
Copy link

Irfanwani commented Apr 7, 2023

oh you mean we have add this as a script in package.json, right?
Not getting how to use it.

@DevYuns
Copy link

DevYuns commented Apr 7, 2023

  1. Install dotenv-cli in your project.
  2. Add script like below
"scripts" : {
   "eas-updates": "dotenv -e .env -- eas update"
}
  1. Execute the command with your package manager like yarn eas-updates.

@Irfanwani Is that clear?

@Irfanwani
Copy link

Oh, missed the dotenv-cli, thanks. What does this command actually do? Is it just spreading the env variables in front of update command or is there any special thing happening?

@DevYuns
Copy link

DevYuns commented Apr 7, 2023

@Irfanwani Right. It just spreading the env variables.

@Irfanwani
Copy link

Thanks @DevYuns. This will save some time when env is a bit large.

@sebastianjung
Copy link

@DevYuns
So how would the command look like to update the stage or production branch with eas update, when the .env file usually only holds dev environemnt variables when working with the codebase?

Seperate .env files? like .env.stage? What would you recommend?

@DevYuns
Copy link

DevYuns commented Apr 14, 2023

@sebastianjung I prefer to separate .env file like .env.prod and .env.dev.

@senghuotlay
Copy link

if i would like it to be run from ci, then i would have to create github secret for that correct?

@rcwestlake
Copy link

I came across the thread b/c I was confused as well. For any other late-comers in the future, I ended up just following the standard env fallback where I have a .env (local values) .env.development, and .env.production and it seems to work well.

@akinwol
Copy link

akinwol commented Oct 16, 2023

  1. Install dotenv-cli in your project.
  2. Add script like below
"scripts" : {
   "eas-updates": "dotenv -e .env -- eas update"
}
  1. Execute the command with your package manager like yarn eas-updates.

@Irfanwani Is that clear?

this is the only thing that worked for me. As a newbie using expo I was banging my head with eas update

@sameigen
Copy link

sameigen commented Oct 27, 2023

This caused me a headache for sure! For those in the future, I think this is what we've learned:

  1. You can't pass in any environment variables using EAS Update from any .env* file that is gitignored.
  2. NODE_ENV= prepending an eas update command causes some unexpected behavior.
  3. @DevYuns script works for passing in a *.env file.

If you're like me and only have one, non-sensitive environment variable in the environment variable section of your eas.json, you need to pass that in again when you run eas update on that channel. I personally think there should be some language on eas update saying that all build-time environment variables that are not in Expo secrets get thrown out.

The scripts that came in handy for us:

"scripts": {
   "publish-stg": "EXPO_PUBLIC_ENVIRONMENT=staging eas update --channel=staging",
   "publish-prod": "EXPO_PUBLIC_ENVIRONMENT=production eas update --channel=production",
 },

@matart15
Copy link

matart15 commented Jan 17, 2024

None of this work for me. I think expo cli have a bug

    "eas:update:preview": "EXPO_PUBLIC_ENVIRONMENT=staging eas update --branch preview --message \"update try\""
    "eas:update": "NODE_ENV=preview; pnpx eas-cli update --branch preview --message \"update try\"",
    "eas:update1": "NODE_ENV=preview eas update --branch preview --message \"update try\"",

@mfrfinbox
Copy link

Just for anyone having this problem, the following worked for me:

Installed npm install env-cmd --save-dev then in my package.json

"eas-update": "env-cmd -f .env eas update --branch preview --message updating"

This will send your env variables to eas update taking your .env, I hope that helps.

@trevorpfiz
Copy link

I was having this problem with eas credentials. My solution is to pnpm install dotenv-cli, then add a script, "with-env": "dotenv -e ./.env --". now I can do pnpm with-env eas credentials.

@DiazIgnacio
Copy link

DiazIgnacio commented Nov 8, 2024

@DevYuns

  1. Install dotenv-cli in your project.
  2. Add script like below
"scripts" : {
   "eas-updates": "dotenv -e .env -- eas update"
}
  1. Execute the command with your package manager like yarn eas-updates.

@Irfanwani Is that clear?

this is the only thing that worked for me. As a newbie using expo I was banging my head with eas update

Works like a charm, but only after adding --clear-cache to it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs review Issue is ready to be reviewed by a maintainer
Projects
None yet
Development

No branches or pull requests