eas-cli: eas build with gitignored google-services.json file.

Hello, Great tool! enjoying using it a lot.

At the moment I am having to commit my google-services.json & GoogleService-Info.plist files in order to allow the cloud-build to work properly but this seems a bit of a security risk?

Ideally, I’d have these files reference in my .gitignore

Sat, 06 Feb 2021 17:16:45 GMT
[stderr] [17:16:45] Cannot copy google-services.json from /usr/local/lib/node_modules/@expo/eas-build-worker/workingdir/build/google-services-staging.json to /usr/local/lib/node_modules/@expo/eas-build-worker/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
Sat, 06 Feb 2021 17:16:45 GMT
[stderr] [17:16:45] Error: Cannot copy google-services.json from /usr/local/lib/node_modules/@expo/eas-build-worker/workingdir/build/google-services-staging.json to /usr/local/lib/node_modules/@expo/eas-build-worker/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
[stderr]     at setGoogleServicesFile (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/android/GoogleServices.ts:79:11)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at runMicrotasks (<anonymous>)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at processTicksAndRejections (internal/process/task_queues.js:93:5)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at /usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/android/GoogleServices.ts:53:7
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at action (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/plugins/core-plugins.ts:118:23)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at action (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/plugins/compiler-plugins.ts:282:23)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at evalModsAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/plugins/mod-compiler.ts:75:25)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at compileModsAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/@expo/config-plugins/src/plugins/mod-compiler.ts:17:10)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at configureManagedProjectAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/expo-cli/src/commands/apply/configureProjectAsync.ts:115:12)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at prebuildAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/expo-cli/src/commands/eject/Eject.ts:146:25)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at Object.ejectAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/expo-cli/src/commands/eject/Eject.ts:78:19)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at actionAsync (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/expo-cli/src/commands/eject.ts:46:5)
Sat, 06 Feb 2021 17:16:45 GMT
[stderr]     at Command.<anonymous> (/usr/local/lib/node_modules/@expo/eas-build-worker/node_modules/expo-cli/src/exp.ts:346:7)
Sat, 06 Feb 2021 17:16:45 GMT
Build failed: node exited with non-zero code: 1

Is there any workaround to this scenario/issue?

Thank you!

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 31 (8 by maintainers)

Most upvoted comments

Hi guys,

You don’t need to commit the gitignored files to the repo.

Here’s a workaround (assuming you want your build to have access to google-service.json):

  • Convert the secret file to a base64-encoded string: $ base64 google-services.json
  • Copy the output of the command and set an EAS secret with eas secret:create (e.g. GOOGLE_SERVICES_BASE64)
  • Use an EAS Build hook (https://docs.expo.io/build-reference/how-tos/#eas-build-specific-npm-hooks) to restore the file: In package.json: "eas-build-pre-install": "echo $GOOGLE_SERVICES_BASE64 | base64 --decode > /path/to/google-services.json"

I have a related case - I use tailwind-rn for styles, so I constantly have unexpected changes to tailwind.css and tailwind.json in my commits, which results in merge conflicts with other PRs. Ignoring them and generating at build time works, but then eas also ignores them. So I started generating .easignore, too.

cc/ @diegoconcha as you mentioned having to keep two files up to date.

tl;dr: generate your .easignore from your .gitignore at build time.

Which (I think) is the only time you need it.

.gitignore:

node_modules/
.expo/
dist/

# ignore .easignore, too ✨
.easignore

### EASINCLUDE! ###
### BELOW THIS LINE WILL NOT BE IGNORED BY EAS ###

tailwind.css
tailwind.json

generate-easignore.js

const fs = require('fs')
const gitignore = fs.readFileSync('./.gitignore', 'utf8')
const easignore = gitignore.split('### EASINCLUDE! ###')[0]
fs.writeFileSync('./.easignore', easignore)

package.json

{
  "scripts": {
    "build": "node ./generate-easignore.js && eas build"
  }
}

This will output a .easignore that includes everything in .gitignore except the EASINCLUDE! line and everything below it. Use whatever you want for the separator string, I chose something that seemed programmatic so no one touches it unwittingly. Run it before you run eas build, probably in an npm script.

Lots of comments, it’d be great to have a mini tutorial how to handle this situation in the Expo’s docs.

@dsokal is this still the recommended way to handle this situation? I’m using amplify and also have the aws-exports.js file someone else mentioned above. This file changes based on changes we make to the backend so it’s somewhat dynamic so we’d need to update it’s eas secret value often. I would much rather prefer to be able to include the latest version of this file in the build vs it being ignored by eas because it’s in the .gitignore. Thank you!

I have a similar issue, I’m using aws amplify which downloads a file aws-exports.js which is in .gitignore (as it should be). I need to include it in build without editing .gitignore.

@diegoconcha If you are using default git workflow (you don’t have requireCommit: true in eas.json) then you can add .easignore file

Note that if easignore is present, gitingore files are not respected(even in subdirectories) and there can only be one .easignore and it has to be in the root of the repository

@diegoconcha If you are using default git workflow (you don’t have requireCommit: true in eas.json) then you can add .easignore file Note that if easignore is present, gitingore files are not respected(even in subdirectories) and there can only be one .easignore and it has to be in the root of the repository

Thanks @wkozyra95 for your reply. The challenge with this approach is now we have to keep two ignore files up-to-date (.gitignore and .easignore). This approach is definitely an improvement over the base64 encoded string and eas pre-install step discussed above but it would probably be easier for most teams if expo added a .easincludes file where we can include important cloud configuration files like the aws-exports.js in our case. I hope you all consider adding this in the near future.

Hi @diegoconcha or @everyone here! I am currently on the process of eas build-ing an app, and I was wondering whether to use the base64 route or this .easignore. I am leaning towards the latter, but I am worried about inadvertently exposing my aws-exports.js to prying eyes. What are your thoughts about this?

Hey @AllanBengco we went the .easignore route. Ours is a copy of our .gitignore without the aws-exports.js so that the aws-exports.js is included in the build. This file only has routes and high level config of our backend so mostly stuff that’s already easy to figure out by analyzing network traffic on the device or using our app. Essentially nothing we’re worried about exposing but take a detailed look yourself.

Like @wkozyra95 said, the aws-exports.js is part of the js bundle after the app is built. As a result, it can also be replaced via an OTA update (eas update or expo updates). We updated our app via eas update and accidentally pointed our prod users to our dev backend for a short period of time so heads up @AllanBengco.

@diegoconcha If you are using default git workflow (you don’t have requireCommit: true in eas.json) then you can add .easignore file

Note that if easignore is present, gitingore files are not respected(even in subdirectories) and there can only be one .easignore and it has to be in the root of the repository

Thanks @wkozyra95 for your reply. The challenge with this approach is now we have to keep two ignore files up-to-date (.gitignore and .easignore). This approach is definitely an improvement over the base64 encoded string and eas pre-install step discussed above but it would probably be easier for most teams if expo added a .easincludes file where we can include important cloud configuration files like the aws-exports.js in our case. I hope you all consider adding this in the near future.

Surely the better solution these days is using eas file secrets

https://docs.expo.dev/build-reference/variables/

e.g. add secret with name ANDROID_GOOGLE_SERVICES_FILE_PATH, then in app.config.js/ts

android: {
    googleServicesFile: process.env.ANDROID_GOOGLE_SERVICES_FILE_PATH,
}

If it’s a secret it should be passed via EAS Secrets (base64 route), but if I understand correctly aws-exports.js is part of the js bundle, so anyone can extract those values by unzipping apk/ipa, so there is no point in going to far in protecting any secrets that are available client-side.

@VictorioMolina .easignore if present replaces .gitignore If you want to upload sth that is not committed or stop from upload sth that is committed you can use that file https://github.com/expo/fyi/blob/main/eas-build-archive.md

assetBundlePatterns defines what assets are bundled inside the app for classic builds and it’s not doing anything for eas build. https://docs.expo.dev/guides/offline-support/#eas-build

Not completely related, but in case this helps anyone who is struggling with multiple amplify envs I have been doing this:

"eas-build-pre-install": "node scripts/pre-install.js"

Which runs the following node script:

const fs = require("fs");

const buildProfile = process.env.EAS_BUILD_PROFILE;
const configProd = process.env.AWS_EXPORTS;
const configDevelop = process.env.AWS_EXPORTS_DEVELOP;

const config = buildProfile === "production" ? configProd : configDevelop;

const decoded = Buffer.from(config, "base64").toString();

fs.writeFileSync("./src/aws-exports.js", decoded);

In summary, you still have to update the secrets as your backend changes but at least you can build for multiple envs as required.

For referenece - I was initially running the following script - but had issues with it not working for Play store builds (it works fine for iOS), probably not escaping some variable or something?

"eas-build-pre-install": "[ $EAS_BUILD_PROFILE == \"production\" ] && config=\"$AWS_EXPORTS\" || config=\"$AWS_EXPORTS_DEVELOP\"; echo $config | base64 -d > ./src/aws-exports.js;"

It’d be nice to extend eas credentials to storing secrets in general. That way eas submit could get the Google api key file and the EXPO_APPLE_APP_SPECIFIC_PASSWORD from the Expo server.