EAS CI fails due to gitignore pattern preventing upload of bundle
The Context
Working on a React Native Expo project which uses the EAS build tools for CI whilst also using a custom native module for Mapbox turn-by-turn navigation which is not supported by the Expo Go app out of the box.
We have a
/plugins/mapboxNavigation
folder in our root directory which stores our plugin which can be installed in the EAS build process. Inside this we have android/
and ios/
directories for the native plugins.We have an
index.js
file inside the plugin which dangerously alters the Gradle/Podfiles
during the prebuild
step to inject the native dependencies we require.The Problem
Our CI started failing at the
prebuild
step after needing a new native build.
For iOS:
[stderr] Error: [ios.xcodeproj]: withIosXcodeprojBaseMod: ENOENT: no such file or directory, open '/Users/expo/workingdir/build/plugins/mapboxNavigation/ios/MapboxNavigationManager.swift'
For Android:
[stderr] Error: [android.dangerous]: withAndroidDangerousBaseMod: ENOENT: no such file or directory, open '/home/expo/workingdir/build/plugins/mapboxNavigation/android/NavigationViewActivity.java'
withIosXcodeprojBaseMod
and withAndroidDangerousBaseMod
were being called from withDangerousMod
from '@expo/config-plugins'
. So our index.js
which was injecting the native dependencies was throwing an error.The Solution
We reran the build with a clear cache - but the error was the same:

We checked the git history between the last commit that built successfully, but couldn’t find any changes to
index.js
.We tried reproducing locally, by running the exact command run in the CI:
node_modules/.bin/expo prebuild --no-install --platform android
but this succeeded.This, plus the
no such file or directory
error, suggested that our directory structure was different to the one remotely. It would have helped if there was an SSH agent we could have attached to investigate the local files of the machine.Interestingly, checking out to the last commit where a remote build succeeded and running
npx eas build
again failed. I would have expected this to succeed (as we’re running on identical code).
Interestingly, the
prebuild
step is skipped here (whereas in the last succeeding run it was not skipped) with the message: Skipped running "expo prebuild" because the "android" directory already exists. Learn more about the build process: https://docs.expo.dev/build-reference/android-builds/
.The
Run gradlew
step fails and as I inspect the error I see that it fails with some compilation errors which has some local code I’m working on inside the /android
directory. I wasn’t expecting the CI to have any access to my local code.This suggested to me that something was happening with the upload process that I didn’t understand which meant that files I didn’t expect to be sent to EAS were.
The answer was explained to me after I read these docs!
It turns out that the upload process that happens in
eas build
respects the .gitignore
file. This prevents any secrets in the .env
file being uploaded for example (makes sense!).Each build creates an
/android
and /ios
folder that we never want to commit to source control - because it’s generated code. Since the last build, these directories had been added to the .gitignore
to prevent them ever being committed accidentally, however the pattern that was used actually excluded all directories named android
or ios
. This meant that during the upload phase, /plugins/mapboxNavigation/android
and /plugins/mapboxNavigation/ios
were both excluded from the upload, which explains why we get the error no such file or directory
!The Code
// .gitignore causing the error // ignores all files in directories call 'android' or 'ios' android/ ios/
// .gitignore fixed // only ignores 'android'|'ios' directories in the project root /android/ /ios/