Hello everyone,
EAS Build works great on our local-dev and staging profiles, but fails with an obscure error when using production profile from CI.
I post here hoping someone will have an idea which would resolve this error, or a way to investigate this issue. Please ask me any other information which might be helpful for your understanding.
[ gitlab-ci.yml ]
variables:
EXPO_TOKEN: $EXPO_TOKEN
default:
image: node:16.13.1
stages:
- setup
- test
- build
- update
- submission
setup:
stage: setup
only:
- dev
- /^(ci|feat|bug|fix|chore|task)/
- production
cache:
key:
files:
- yarn.lock
paths:
- node_modules
script:
- yarn set version classic
- yarn
test:
stage: test
only:
- dev
- /^(ci|feat|bug|fix|chore|task)/
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn set version classic
- yarn lint
- yarn test
build-preprod:
stage: build
only: [dev]
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn build:staging:ci
after_script:
- echo "=== Staging Build complete ==="
update-preprod:
stage: update
only: [dev]
when: manual
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn update:staging:ci
- ls -al ./dist
after_script:
- echo "=== Staging Update complete ==="
build-prod:
stage: build
only: [production]
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn build:production:ci
after_script:
- echo "=== Production Build complete ==="
update-prod:
stage: update
only: [production]
when: manual
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn update:production:ci
after_script:
- echo "=== Production Update complete ==="
submit-to-stores:
stage: submission
only: [production]
cache:
key:
files:
- yarn.lock
paths:
- node_modules
policy: pull
script:
- yarn submit:production:ci
after_script:
- echo "=== Production Update complete ==="
[ Sections of package.json - non-relevant content has been removed. ]
{
"scripts": {
"start": "expo start --clear",
"android": "expo start --android",
"build:dev": "eas build --profile dev",
"build:dev:ios-simulator": "eas build -p ios --profile dev-ios-simulator",
"build:staging": "eas build --profile staging --platform all --no-wait",
"build:staging:ci": "eas build --profile staging --platform all --non-interactive --no-wait",
"build:production": "eas build --profile production --platform all --no-wait",
"build:production:ci": "eas build --profile production --platform all --non-interactive --no-wait --verbose",
"update:staging": "eas update --branch dev",
"update:staging:ci": "eas update --branch dev --non-interactive --auto",
"update:production": "eas update --branch production",
"update:production:ci": "eas update --branch production --non-interactive --auto",
"submit:production:ci": "eas submit --platform all --non-interactive --no-wait",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "^45.0.0",
"expo-ads-admob": "~13.0.0",
"expo-app-loading": "~2.0.0",
"expo-application": "~4.1.0",
"expo-barcode-scanner": "~11.3.0",
"expo-chart-kit": "^1.2.4",
"expo-constants": "~13.1.1",
"expo-dev-client": "~1.0.1",
"expo-device": "~4.2.0",
"expo-font": "~10.1.0",
"expo-haptics": "~11.2.0",
"expo-intent-launcher": "~10.2.0",
"expo-linear-gradient": "~11.3.0",
"expo-localization": "~13.0.0",
"expo-location": "~14.2.2",
"expo-notifications": "~0.15.4",
"expo-screen-orientation": "~4.2.0",
"expo-splash-screen": "~0.15.1",
"expo-status-bar": "~1.3.0",
"expo-system-ui": "~1.2.0",
"expo-tracking-transparency": "~2.2.0",
"expo-updates": "~0.13.4"
},
"devDependencies": {
"eas-cli": "^2.3.0",
"expo-cli": "^6.0.6",
},
"private": true,
"engines": {
"node": ">=16.13.1",
"yarn": ">=1.22.15"
}
}
[ eas.json ]
{
"cli": {
"version": ">= 0.52.0"
},
"build": {
"dev": {
"developmentClient": true,
"distribution": "internal",
"env": {
"API_ENDPOINT": "<secret-removed>",
"MIXPANEL_TOKEN": "<secret-removed>"
}
},
"dev-ios-simulator": {
"distribution": "internal",
"env": {
"API_ENDPOINT": "<secret-removed>",
"MIXPANEL_TOKEN": "<secret-removed>"
},
"ios": {
"simulator": true
}
},
"staging": {
"channel": "staging",
"distribution": "internal"
},
"production": {
"channel": "production"
}
},
"submit": {
"production": {}
}
}
[ app.config.js ]
// See doc at --> https://docs.expo.io/versions/latest/config/app/
export default {
expo: {
name: '<secret-removed>',
// References <secret-removed> Expo's Organization
owner: '<secret-removed>',
description: `<secret-removed>`,
slug: '<secret-removed>',
version: '2.1.0',
platforms: ['ios', 'android'],
orientation: 'portrait',
userInterfaceStyle: 'automatic',
icon: './assets/images/appicon.png',
scheme: '<secret-removed>',
runtimeVersion: {
policy: 'sdkVersion',
},
extra: {
eas: {
projectId: 'c86bb2a8-ed60-4144-a5f4-6ecbdd7e5450', // Kept this for you Expo Team.
},
},
updates: {
// Some users might need to update the app using very slow network.
fallbackToCacheTimeout: 300000,
url: 'https://u.expo.dev/<secret-removed>',
},
assetBundlePatterns: ['**/*'],
splash: {
image: './assets/images/splash.png',
resizeMode: 'contain',
backgroundColor: '#ffffff',
},
ios: {
buildNumber: '2.1.0',
bundleIdentifier: 'com.<secret-removed>.<secret-removed>',
infoPlist: {
// CFBundleAllowMixedLocalizations: Permits the use of "locales" iOS translations.
// Translation messages like "NS..." should be set for each locale in locale files.
// https://docs.expo.dev/distribution/app-stores/?redirected#localizing-your-ios-app
CFBundleAllowMixedLocalizations: true,
UIUserInterfaceStyle: 'automatic',
},
userInterfaceStyle: 'automatic',
config: {
googleMapsApiKey: '<secret-removed>',
// googleMobileAdsAppId - https://docs.expo.dev/versions/latest/sdk/admob/
// We don't make use of Ads Mob, but Expo SDK references it so it is required to have an App ID even if not using the feature.
// Might be removed on SDK 46.
// https://apps.admob.com/v2/apps/list?utm_source=internal&utm_medium=et&utm_campaign=helpcentrecontextualopt&utm_term=http%3A%2F%2Fgoo.gl%2F6Xkfcf&subid=ww-ww-et-amhelpv4
googleMobileAdsAppId: 'ca-app-pub-<secret-removed>',
},
},
locales: {
fr: './ios-permissions-locales/fr.json',
en: './ios-permissions-locales/en.json',
es: './ios-permissions-locales/es.json',
pt: './ios-permissions-locales/pt.json',
},
android: {
versionCode: 210,
softwareKeyboardLayoutMode: 'pan',
package: 'com.<secret-removed>.<secret-removed>',
config: {
googleMaps: {
apiKey: '<secret-removed>',
},
// googleMobileAdsAppId - https://docs.expo.dev/versions/latest/sdk/admob/
// We don't make use of Ads Mob, but Expo SDK references it so it is required to have an App ID even if not using the feature.
// Might be removed on SDK 46.
// https://apps.admob.com/v2/apps/list?utm_source=internal&utm_medium=et&utm_campaign=helpcentrecontextualopt&utm_term=http%3A%2F%2Fgoo.gl%2F6Xkfcf&subid=ww-ww-et-amhelpv4
googleMobileAdsAppId: 'ca-app-pub-<secret-removed>',
},
// https://docs.expo.dev/guides/permissions/
// Note: We don't add any permission here because this would override EVERY OTHER permission.
// Permissions are injected automatically by Expo's modules at compilation time.
// If you need to add something here, you MUST know that this will restrict the app to using
// ONLY the permissions you mention here. Review Expo's reco first.
// vibrate: ['VIBRATE'],
// Expo push notifications
// https://console.firebase.google.com/project/expo-push-notifications-2354d/settings/cloudmessaging/android:com.<secret-removed>.<secret-removed>
// https://console.cloud.google.com/apis/credentials?project=<secret-removed>
googleServicesFile: './google-services.json',
},
plugins: ['sentry-expo', 'expo-tracking-transparency'],
hooks: {
postPublish: [
{
file: 'sentry-expo/upload-sourcemaps',
config: {
organization: '<secret-removed>',
project: '<secret-removed>',
authToken: '<secret-removed>',
},
},
],
},
},
}
[ The CI “build-prod” log ]
Running with gitlab-runner 15.6.0~beta.186.ga889181a (a889181a)
on blue-1.shared.runners-manager.gitlab.com/default <secret-removed>
Preparing the "docker+machine" executor
00:31
Using Docker executor with image node:16.13.1 ...
Pulling docker image node:16.13.1 ...
Using docker image sha256:8381a2328ac23db134520977fdc4c4c34ba6afbf1b7bc72c62ad086db86003a2 for node:16.13.1 with digest node@sha256:32605ead97ed57bd39a8a7b0e919240e1a3218974dfc6965e61b54a801753131 ...
Preparing environment
00:04
Running on runner-j<secret-removed>-concurrent-0 via runner-<secret-removed>...
Getting source from Git repository
00:03
$ eval "$CI_PRE_CLONE_SCRIPT"
Fetching changes with git depth set to 50...
Initialized empty Git repository in /builds/<secret-removed>/expo-app/.git/
Created fresh repository.
Checking out f80ab9bc as production...
Skipping Git submodules setup
Restoring cache
00:29
Checking cache for <secret-removed>-1-non_protected...
Downloading cache.zip from https://storage.googleapis.com/gitlab-com-runners-cache/project/<secret-removed>/<secret-removed>-1-non_protected
Successfully extracted cache
Executing "step_script" stage of the job script
00:05
Using docker image sha256:8381a2328ac23db134520977fdc4c4c34ba6afbf1b7bc72c62ad086db86003a2 for node:16.13.1 with digest node@sha256:32605ead97ed57bd39a8a7b0e919240e1a3218974dfc6965e61b54a801753131 ...
$ yarn build:production:ci
yarn run v1.22.15
$ eas build --profile production --platform all --non-interactive --no-wait --verbose
CombinedError: [Network] Unauthorized
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Running after_script
00:01
Running after script...
$ echo "=== Production Build complete ==="
=== Production Build complete ===
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 1