@expo/build-tools 18.2.0 → 18.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/android/gradle.js +1 -1
  2. package/dist/buildErrors/detectError.d.ts +1 -1
  3. package/dist/buildErrors/detectError.js +8 -12
  4. package/dist/buildErrors/userErrorHandlers.d.ts +2 -2
  5. package/dist/buildErrors/userErrorHandlers.js +20 -20
  6. package/dist/builders/android.js +12 -2
  7. package/dist/builders/custom.js +1 -0
  8. package/dist/common/setup.js +4 -6
  9. package/dist/context.d.ts +2 -0
  10. package/dist/context.js +2 -0
  11. package/dist/customBuildContext.d.ts +5 -1
  12. package/dist/customBuildContext.js +22 -0
  13. package/dist/generic.d.ts +1 -3
  14. package/dist/generic.js +13 -15
  15. package/dist/ios/credentials/provisioningProfile.d.ts +2 -1
  16. package/dist/ios/credentials/provisioningProfile.js +10 -11
  17. package/dist/steps/functions/downloadArtifact.js +3 -3
  18. package/dist/steps/functions/downloadBuild.js +2 -2
  19. package/dist/steps/functions/internalMaestroTest.js +8 -12
  20. package/dist/steps/functions/maestroResultParser.js +134 -80
  21. package/dist/steps/functions/readIpaInfo.js +9 -9
  22. package/dist/steps/functions/reportMaestroTestResults.js +14 -7
  23. package/dist/steps/functions/uploadToAsc.js +4 -4
  24. package/dist/steps/utils/android/gradle.js +1 -1
  25. package/dist/steps/utils/android/gradleConfig.d.ts +3 -0
  26. package/dist/steps/utils/android/gradleConfig.js +15 -1
  27. package/dist/steps/utils/ios/AscApiUtils.js +3 -3
  28. package/dist/steps/utils/ios/credentials/provisioningProfile.d.ts +2 -1
  29. package/dist/steps/utils/ios/credentials/provisioningProfile.js +10 -11
  30. package/dist/utils/stepMetrics.d.ts +2 -2
  31. package/dist/utils/stepMetrics.js +4 -10
  32. package/package.json +4 -4
  33. package/dist/android/gradleConfig.d.ts +0 -3
  34. package/dist/android/gradleConfig.js +0 -47
  35. package/dist/templates/EasBuildGradle.d.ts +0 -1
  36. package/dist/templates/EasBuildGradle.js +0 -57
@@ -35,7 +35,7 @@ async function runGradleCommand(ctx, { logger, gradleCommand, androidDir, extraE
35
35
  return line;
36
36
  }
37
37
  },
38
- env: { ...ctx.env, ...extraEnv, ...resolveVersionOverridesEnvs(ctx) },
38
+ env: { ...ctx.env, ...extraEnv, ...resolveVersionOverridesEnvs(ctx), LC_ALL: 'C.UTF-8' },
39
39
  });
40
40
  if (ctx.env.EAS_BUILD_RUNNER === 'eas-build' && process.platform === 'linux') {
41
41
  adjustOOMScore(spawnPromise, logger);
@@ -1,3 +1,3 @@
1
1
  import { errors } from '@expo/eas-build-job';
2
2
  import { ErrorContext } from './errors.types';
3
- export declare function resolveBuildPhaseErrorAsync(error: any, logLines: string[], errorContext: ErrorContext, buildLogsDirectory: string): Promise<errors.BuildError>;
3
+ export declare function resolveBuildPhaseErrorAsync(error: any, logLines: string[], errorContext: ErrorContext, buildLogsDirectory: string): Promise<errors.ExpoError>;
@@ -49,24 +49,20 @@ function resolveError(errorHandlers, logLines, errorContext, xcodeBuildLogs) {
49
49
  }
50
50
  async function resolveBuildPhaseErrorAsync(error, logLines, errorContext, buildLogsDirectory) {
51
51
  const { phase } = errorContext;
52
- if (error instanceof eas_build_job_1.errors.BuildError) {
52
+ if (error instanceof eas_build_job_1.errors.ExpoError) {
53
+ error.buildPhase ??= phase;
53
54
  return error;
54
55
  }
55
56
  const xcodeBuildLogs = await maybeReadXcodeBuildLogs(phase, buildLogsDirectory);
56
- const userFacingError = error instanceof eas_build_job_1.errors.UserFacingError
57
- ? error
58
- : (resolveError(userErrorHandlers_1.userErrorHandlers, logLines, errorContext, xcodeBuildLogs) ??
59
- new eas_build_job_1.errors.UnknownError(errorContext.phase));
57
+ const userError = resolveError(userErrorHandlers_1.userErrorHandlers, logLines, errorContext, xcodeBuildLogs) ??
58
+ new eas_build_job_1.errors.UnknownError(errorContext.phase);
60
59
  const buildError = resolveError(buildErrorHandlers_1.buildErrorHandlers, logLines, errorContext, xcodeBuildLogs);
61
- const trackingCode = buildError && buildError.errorCode !== userFacingError.errorCode
62
- ? buildError.errorCode
63
- : undefined;
64
- return new eas_build_job_1.errors.BuildError(userFacingError.message, {
65
- errorCode: userFacingError.errorCode,
60
+ const trackingCode = buildError && buildError.errorCode !== userError.errorCode ? buildError.errorCode : undefined;
61
+ return new eas_build_job_1.errors.UserError(userError.errorCode, userError.message, {
66
62
  trackingCode,
67
- docsUrl: userFacingError.docsUrl,
68
- cause: error,
63
+ docsUrl: userError.docsUrl,
69
64
  buildPhase: phase,
70
65
  metadata: buildError?.metadata,
66
+ cause: error,
71
67
  });
72
68
  }
@@ -1,4 +1,4 @@
1
1
  import { errors } from '@expo/eas-build-job';
2
2
  import { ErrorHandler } from './errors.types';
3
- import UserFacingError = errors.UserFacingError;
4
- export declare const userErrorHandlers: ErrorHandler<UserFacingError>[];
3
+ import UserError = errors.UserError;
4
+ export declare const userErrorHandlers: ErrorHandler<UserError>[];
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.userErrorHandlers = void 0;
4
4
  const eas_build_job_1 = require("@expo/eas-build-job");
5
5
  const errors_types_1 = require("./errors.types");
6
- var UserFacingError = eas_build_job_1.errors.UserFacingError;
6
+ var UserError = eas_build_job_1.errors.UserError;
7
7
  exports.userErrorHandlers = [
8
8
  {
9
9
  platform: eas_build_job_1.Platform.IOS,
@@ -11,7 +11,7 @@ exports.userErrorHandlers = [
11
11
  regexp: /requires CocoaPods version/,
12
12
  // example log:
13
13
  // [!] `React` requires CocoaPods version `>= 1.10.1`, which is not satisfied by your current version, `1.10.0`.
14
- createError: () => new UserFacingError('EAS_BUILD_UNSUPPORTED_COCOAPODS_VERSION_ERROR', `Your project requires a newer version of CocoaPods. You can update it in the build profile in eas.json by either:
14
+ createError: () => new UserError('EAS_BUILD_UNSUPPORTED_COCOAPODS_VERSION_ERROR', `Your project requires a newer version of CocoaPods. You can update it in the build profile in eas.json by either:
15
15
  - changing the current version under key "cocoapods"
16
16
  - switching to an image that supports that version under key "image"`, { docsUrl: 'https://docs.expo.dev/build-reference/eas-json/' }),
17
17
  },
@@ -21,7 +21,7 @@ exports.userErrorHandlers = [
21
21
  regexp: /Could not find 'bundler' (.*) required by your/,
22
22
  // example log:
23
23
  // /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/dependency.rb:313:in `to_specs': Could not find 'bundler' (2.2.3) required by your /Users/expo/project/build/ios/Gemfile.lock. (Gem::MissingSpecVersionError)
24
- createError: () => new UserFacingError('EAS_BUILD_UNSUPPORTED_BUNDLER_VERSION_ERROR', `Your project requires a different version of the Ruby "bundler" program than the version installed in this EAS Build environment. You can specify which version of "bundler" to install by specifying the version under "build"→[buildProfileName]→"ios"→"bundler" in eas.json.`, { docsUrl: 'https://docs.expo.dev/build-reference/eas-json/' }),
24
+ createError: () => new UserError('EAS_BUILD_UNSUPPORTED_BUNDLER_VERSION_ERROR', `Your project requires a different version of the Ruby "bundler" program than the version installed in this EAS Build environment. You can specify which version of "bundler" to install by specifying the version under "build"→[buildProfileName]→"ios"→"bundler" in eas.json.`, { docsUrl: 'https://docs.expo.dev/build-reference/eas-json/' }),
25
25
  },
26
26
  {
27
27
  platform: eas_build_job_1.Platform.ANDROID,
@@ -29,7 +29,7 @@ exports.userErrorHandlers = [
29
29
  // example log:
30
30
  // > Failed to read key keyalias from store "/build/workingdir/build/generic/keystore-5787e6af-3002-4cb7-8a57-3e73d13313c2.jks": Invalid keystore format
31
31
  regexp: /Invalid keystore format/,
32
- createError: () => new UserFacingError('EAS_BUILD_INVALID_KEYSTORE_FORMAT_ERROR', 'The keystore used in this build is malformed or it has an unsupported type. Make sure you provided the correct file.'),
32
+ createError: () => new UserError('EAS_BUILD_INVALID_KEYSTORE_FORMAT_ERROR', 'The keystore used in this build is malformed or it has an unsupported type. Make sure you provided the correct file.'),
33
33
  },
34
34
  {
35
35
  platform: eas_build_job_1.Platform.ANDROID,
@@ -37,7 +37,7 @@ exports.userErrorHandlers = [
37
37
  // example log:
38
38
  // > Failed to read key keyalias from store "/build/workingdir/build/generic/keystore-286069a8-4bb9-48a6-add9-acf6b58ea06d.jks": null
39
39
  regexp: /Failed to read key[^\n]+from store/,
40
- createError: () => new UserFacingError('EAS_BUILD_INVALID_KEYSTORE_ALIAS_ERROR', 'The alias specified for this keystore does not exist. Make sure you specified the correct value.'),
40
+ createError: () => new UserError('EAS_BUILD_INVALID_KEYSTORE_ALIAS_ERROR', 'The alias specified for this keystore does not exist. Make sure you specified the correct value.'),
41
41
  },
42
42
  {
43
43
  platform: eas_build_job_1.Platform.ANDROID,
@@ -48,7 +48,7 @@ exports.userErrorHandlers = [
48
48
  // [11:17:29] [android.dangerous]: withAndroidDangerousBaseMod: Cannot copy google-services.json from /home/expo/workingdir/build/test/test-google-services.json to /home/expo/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
49
49
  // [11:17:29] Error: [android.dangerous]: withAndroidDangerousBaseMod: Cannot copy google-services.json from /home/expo/workingdir/build/test/test-google-services.json to /home/expo/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
50
50
  regexp: /Cannot copy google-services\.json/,
51
- createError: () => new UserFacingError('EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR', '"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
51
+ createError: () => new UserError('EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR', '"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
52
52
  },
53
53
  {
54
54
  platform: eas_build_job_1.Platform.ANDROID,
@@ -57,7 +57,7 @@ exports.userErrorHandlers = [
57
57
  // > File google-services.json is missing. The Google Services Plugin cannot function without it.
58
58
  // Searched Location:
59
59
  regexp: /File google-services\.json is missing\. The Google Services Plugin cannot function without it/,
60
- createError: () => new UserFacingError('EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR', '"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
60
+ createError: () => new UserError('EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR', '"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
61
61
  },
62
62
  {
63
63
  platform: eas_build_job_1.Platform.IOS,
@@ -65,7 +65,7 @@ exports.userErrorHandlers = [
65
65
  // example log:
66
66
  // [08:44:18] ENOENT: no such file or directory, copyfile '/Users/expo/workingdir/build/managed/abc' -> '/Users/expo/workingdir/build/managed/ios/testapp/GoogleService-Info.plist'
67
67
  regexp: /ENOENT: no such file or directory, copyfile .*GoogleService-Info.plist/,
68
- createError: () => new UserFacingError('EAS_BUILD_MISSING_GOOGLE_SERVICES_PLIST_ERROR', '"GoogleService-Info.plist" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
68
+ createError: () => new UserError('EAS_BUILD_MISSING_GOOGLE_SERVICES_PLIST_ERROR', '"GoogleService-Info.plist" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.', { docsUrl: 'https://docs.expo.dev/eas/environment-variables/#file-environment-variables' }),
69
69
  },
70
70
  {
71
71
  platform: eas_build_job_1.Platform.IOS,
@@ -78,7 +78,7 @@ exports.userErrorHandlers = [
78
78
  // Error: Compatible versions of some pods could not be resolved.
79
79
  regexp: /Specs satisfying the `(.*)` dependency were found, but they required a higher minimum deployment target/,
80
80
  createError: (_, { job }) => {
81
- return new UserFacingError('EAS_BUILD_HIGHER_MINIMUM_DEPLOYMENT_TARGET_ERROR', `Some pods require a higher minimum deployment target.
81
+ return new UserError('EAS_BUILD_HIGHER_MINIMUM_DEPLOYMENT_TARGET_ERROR', `Some pods require a higher minimum deployment target.
82
82
  ${'type' in job && job.type === eas_build_job_1.Workflow.MANAGED
83
83
  ? 'You can use the expo-build-properties config plugin (https://docs.expo.dev/versions/latest/sdk/build-properties/) to override the default native build properties and set a different minimum deployment target.'
84
84
  : 'You need to manually update the minimum deployment target in your project to resolve this issue.'}
@@ -101,7 +101,7 @@ ${'type' in job && job.type === eas_build_job_1.Workflow.MANAGED
101
101
  // You should run `pod update Firebase/Core` to apply changes you've made.
102
102
  regexp: /CocoaPods could not find compatible versions for pod /,
103
103
  createError: () => {
104
- return new UserFacingError('EAS_BUILD_INCOMPATIBLE_PODS_ERROR', `Compatible versions of some pods could not be resolved.
104
+ return new UserError('EAS_BUILD_INCOMPATIBLE_PODS_ERROR', `Compatible versions of some pods could not be resolved.
105
105
  You are seeing this error because either:
106
106
  - Some of the pods used in your project depend on different versions of the same pod. See logs for more information.
107
107
  - If you are caching Podfile.lock using "cache" field in eas.json, then versions there might not match required values in Podspecs of some installed libraries. To fix this, you can re-run build command with "--clear-cache" option, or select "Clear cache and retry build" on the build page.
@@ -117,7 +117,7 @@ You are seeing this error because either:
117
117
  regexp: /Fix the upstream dependency conflict, or retry.*\s.*this command with --force, or --legacy-peer-deps/,
118
118
  createError: (matchResult) => {
119
119
  if (matchResult.length >= 2) {
120
- return new UserFacingError('EAS_BUILD_NPM_CONFLICTING_PEER_DEPENDENCIES', `Some of your peer dependencies are not compatible. The recommended approach is to fix your dependencies by resolving any conflicts listed by "npm install". As a temporary workaround you can:
120
+ return new UserError('EAS_BUILD_NPM_CONFLICTING_PEER_DEPENDENCIES', `Some of your peer dependencies are not compatible. The recommended approach is to fix your dependencies by resolving any conflicts listed by "npm install". As a temporary workaround you can:
121
121
  - Add ".npmrc" file with "legacy-peer-deps=true" and commit that to your repo.
122
122
  - Delete package-lock.json and use yarn instead. It does not enforce peer dependencies.
123
123
  - Downgrade to older version of npm on EAS Build, by adding "npm install -g npm@version" in "eas-build-pre-install" script in package.json.`);
@@ -132,7 +132,7 @@ You are seeing this error because either:
132
132
  regexp: /Integrity check failed for "(.*)" \(computed integrity doesn't match our records, got/,
133
133
  createError: (matchResult) => {
134
134
  if (matchResult.length >= 2) {
135
- return new UserFacingError('EAS_BUILD_YARN_LOCK_CHECKSUM_ERROR', `Checksum for package "${matchResult[1]}" does not match value in registry. To fix that:
135
+ return new UserError('EAS_BUILD_YARN_LOCK_CHECKSUM_ERROR', `Checksum for package "${matchResult[1]}" does not match value in registry. To fix that:
136
136
  - run "yarn cache clean"
137
137
  - remove yarn.lock (or only the section for that package)
138
138
  - run "yarn install --force"`);
@@ -152,7 +152,7 @@ You are seeing this error because either:
152
152
  regexp: /\[1\/4\] Resolving packages...\s*\[2\/4\] Fetching packages...\s*\[1\/4\] Resolving packages...\s*\[2\/4\] Fetching packages.../,
153
153
  createError: (matchResult) => {
154
154
  if (matchResult) {
155
- return new UserFacingError('EAS_BUILD_YARN_MULTIPLE_INSTANCES_ERROR', `One of project dependencies is starting new install process while the main one is still in progress, which might result in corrupted packages. Most likely the reason for error is "prepare" script in git-referenced dependency of your project. Learn more: https://github.com/yarnpkg/yarn/issues/7212#issuecomment-493720324`);
155
+ return new UserError('EAS_BUILD_YARN_MULTIPLE_INSTANCES_ERROR', `One of project dependencies is starting new install process while the main one is still in progress, which might result in corrupted packages. Most likely the reason for error is "prepare" script in git-referenced dependency of your project. Learn more: https://github.com/yarnpkg/yarn/issues/7212#issuecomment-493720324`);
156
156
  }
157
157
  return undefined;
158
158
  },
@@ -175,11 +175,11 @@ You are seeing this error because either:
175
175
  // /Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "EXUpdates-EXUpdates" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'EXUpdates-EXUpdates' from project 'Pods')
176
176
  regexp: /error: Signing for "[a-zA-Z-0-9_]+" requires a development team/,
177
177
  createError: (_, { job }) => 'type' in job && job.type === eas_build_job_1.Workflow.MANAGED
178
- ? new UserFacingError('XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR', `Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
178
+ ? new UserError('XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR', `Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
179
179
  To resolve this issue, downgrade to an older Xcode version using the "image" field in eas.json, or upgrade to SDK 46 or higher.`, {
180
180
  docsUrl: 'https://docs.expo.dev/build-reference/infrastructure/#ios-build-server-configurations',
181
181
  })
182
- : new UserFacingError('XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR', `Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
182
+ : new UserError('XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR', `Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
183
183
  To resolve this issue, downgrade to an older Xcode version using the "image" field in eas.json, or turn off signing resource bundles in your Podfile: https://expo.fyi/r/disable-bundle-resource-signing`, {
184
184
  docsUrl: 'https://docs.expo.dev/build-reference/infrastructure/#ios-build-server-configurations',
185
185
  }),
@@ -188,21 +188,21 @@ To resolve this issue, downgrade to an older Xcode version using the "image" fie
188
188
  platform: eas_build_job_1.Platform.ANDROID,
189
189
  phase: eas_build_job_1.BuildPhase.RUN_GRADLEW,
190
190
  regexp: /.*/,
191
- createError: () => new UserFacingError(eas_build_job_1.errors.ErrorCode.UNKNOWN_GRADLE_ERROR, 'Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.'),
191
+ createError: () => new UserError(eas_build_job_1.errors.ErrorCode.UNKNOWN_GRADLE_ERROR, 'Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.'),
192
192
  },
193
193
  {
194
194
  platform: eas_build_job_1.Platform.IOS,
195
195
  phase: eas_build_job_1.BuildPhase.RUN_FASTLANE,
196
196
  mode: eas_build_job_1.BuildMode.RESIGN,
197
197
  regexp: /No provisioning profile for application: '(.+)' with bundle identifier '(.+)'/,
198
- createError: () => new UserFacingError('EAS_BUILD_RESIGN_PROVISIONING_PROFILE_MISMATCH_ERROR', `The bundle identifier in provisioning profile used to resign the app does not match the bundle identifier of the app selected to be resigned. See logs above for more information.`),
198
+ createError: () => new UserError('EAS_BUILD_RESIGN_PROVISIONING_PROFILE_MISMATCH_ERROR', `The bundle identifier in provisioning profile used to resign the app does not match the bundle identifier of the app selected to be resigned. See logs above for more information.`),
199
199
  },
200
200
  {
201
201
  platform: eas_build_job_1.Platform.IOS,
202
202
  phase: eas_build_job_1.BuildPhase.RUN_FASTLANE,
203
203
  mode: eas_build_job_1.BuildMode.RESIGN,
204
204
  regexp: /.*/,
205
- createError: () => new UserFacingError(eas_build_job_1.errors.ErrorCode.UNKNOWN_FASTLANE_RESIGN_ERROR, `The "Run fastlane" step failed with an unknown error.`),
205
+ createError: () => new UserError(eas_build_job_1.errors.ErrorCode.UNKNOWN_FASTLANE_RESIGN_ERROR, `The "Run fastlane" step failed with an unknown error.`),
206
206
  },
207
207
  {
208
208
  platform: eas_build_job_1.Platform.IOS,
@@ -219,7 +219,7 @@ To resolve this issue, downgrade to an older Xcode version using the "image" fie
219
219
  // file modified: /Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework/ios-arm64_x86_64-simulator/ProgrammaticAccessLibrary.framework/ProgrammaticAccessLibrary
220
220
  // file modified: /Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework/ios-arm64/ProgrammaticAccessLibrary.framework/ProgrammaticAccessLibrary
221
221
  regexp: /error: .+/g,
222
- createError: matchResult => new UserFacingError('XCODE_BUILD_ERROR', `The "Run fastlane" step failed because of an error in the Xcode build process. We automatically detected following errors in your Xcode build logs:\n${matchResult
222
+ createError: matchResult => new UserError('XCODE_BUILD_ERROR', `The "Run fastlane" step failed because of an error in the Xcode build process. We automatically detected following errors in your Xcode build logs:\n${matchResult
223
223
  .map(match => `- ${match.replace('error: ', '')}`)
224
224
  .join('\n')}\nRefer to "Xcode Logs" below for additional, more detailed logs.`),
225
225
  },
@@ -227,6 +227,6 @@ To resolve this issue, downgrade to an older Xcode version using the "image" fie
227
227
  platform: eas_build_job_1.Platform.IOS,
228
228
  phase: eas_build_job_1.BuildPhase.RUN_FASTLANE,
229
229
  regexp: /.*/,
230
- createError: () => new UserFacingError(eas_build_job_1.errors.ErrorCode.UNKNOWN_FASTLANE_ERROR, `The "Run fastlane" step failed with an unknown error. Refer to "Xcode Logs" below for additional, more detailed logs.`),
230
+ createError: () => new UserError(eas_build_job_1.errors.ErrorCode.UNKNOWN_FASTLANE_ERROR, `The "Run fastlane" step failed with an unknown error. Refer to "Xcode Logs" below for additional, more detailed logs.`),
231
231
  },
232
232
  ];
@@ -11,13 +11,13 @@ const common_1 = require("./common");
11
11
  const custom_1 = require("./custom");
12
12
  const credentials_1 = require("../android/credentials");
13
13
  const gradle_1 = require("../android/gradle");
14
- const gradleConfig_1 = require("../android/gradleConfig");
15
14
  const eagerBundle_1 = require("../common/eagerBundle");
16
15
  const prebuild_1 = require("../common/prebuild");
17
16
  const setup_1 = require("../common/setup");
18
17
  const context_1 = require("../context");
19
18
  const restoreBuildCache_1 = require("../steps/functions/restoreBuildCache");
20
19
  const saveBuildCache_1 = require("../steps/functions/saveBuildCache");
20
+ const gradleConfig_1 = require("../steps/utils/android/gradleConfig");
21
21
  const artifacts_1 = require("../utils/artifacts");
22
22
  const expoUpdates_1 = require("../utils/expoUpdates");
23
23
  const hooks_1 = require("../utils/hooks");
@@ -87,8 +87,18 @@ async function buildAsync(ctx) {
87
87
  });
88
88
  if ((0, nullthrows_1.default)(ctx.job.secrets, 'Secrets must be defined for non-custom builds').buildCredentials) {
89
89
  await ctx.runBuildPhase(eas_build_job_1.BuildPhase.PREPARE_CREDENTIALS, async () => {
90
+ await (0, gradleConfig_1.warnIfLegacyEasBuildGradleExists)(ctx);
90
91
  await (0, credentials_1.restoreCredentials)(ctx);
91
- await (0, gradleConfig_1.configureBuildGradle)(ctx);
92
+ await (0, gradleConfig_1.injectCredentialsGradleConfig)(ctx.logger, ctx.getReactNativeProjectDirectory());
93
+ });
94
+ }
95
+ if (ctx.job.version?.versionCode || ctx.job.version?.versionName) {
96
+ await ctx.runBuildPhase(eas_build_job_1.BuildPhase.CONFIGURE_ANDROID_VERSION, async () => {
97
+ await (0, gradleConfig_1.warnIfLegacyEasBuildGradleExists)(ctx);
98
+ await (0, gradleConfig_1.injectConfigureVersionGradleConfig)(ctx.logger, ctx.getReactNativeProjectDirectory(), {
99
+ versionCode: ctx.job.version?.versionCode,
100
+ versionName: ctx.job.version?.versionName,
101
+ });
92
102
  });
93
103
  }
94
104
  await ctx.runBuildPhase(eas_build_job_1.BuildPhase.CONFIGURE_EXPO_UPDATES, async () => {
@@ -83,6 +83,7 @@ async function runCustomBuildAsync(ctx) {
83
83
  // do nothing, it's a non-breaking error.
84
84
  }
85
85
  }
86
+ await customBuildCtx.drainPendingMetricUploads();
86
87
  }
87
88
  }
88
89
  catch (err) {
@@ -5,8 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.setupAsync = setupAsync;
7
7
  const eas_build_job_1 = require("@expo/eas-build-job");
8
- const common_1 = require("@expo/eas-build-job/dist/common");
9
- const errors_1 = require("@expo/eas-build-job/dist/errors");
10
8
  const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
11
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
12
10
  const nullthrows_1 = __importDefault(require("nullthrows"));
@@ -44,7 +42,7 @@ async function setupAsync(ctx) {
44
42
  if (ctx.job.platform === eas_build_job_1.Platform.IOS && ctx.env.EAS_BUILD_RUNNER === 'eas-build') {
45
43
  await (0, xcodeEnv_1.deleteXcodeEnvLocalIfExistsAsync)(ctx);
46
44
  }
47
- if (ctx.job.triggeredBy === common_1.BuildTrigger.GIT_BASED_INTEGRATION) {
45
+ if (ctx.job.triggeredBy === eas_build_job_1.BuildTrigger.GIT_BASED_INTEGRATION) {
48
46
  // We need to setup envs from eas.json before
49
47
  // eas-build-pre-install hook is called.
50
48
  const env = await (0, easBuildInternal_1.resolveEnvFromBuildProfileAsync)(ctx, {
@@ -97,7 +95,7 @@ async function setupAsync(ctx) {
97
95
  ctx.logger.info(JSON.stringify(appConfig, null, 2));
98
96
  await validateAppConfigAsync(ctx, appConfig);
99
97
  });
100
- if (ctx.job.triggeredBy === common_1.BuildTrigger.GIT_BASED_INTEGRATION) {
98
+ if (ctx.job.triggeredBy === eas_build_job_1.BuildTrigger.GIT_BASED_INTEGRATION) {
101
99
  await ctx.runBuildPhase(eas_build_job_1.BuildPhase.EAS_BUILD_INTERNAL, async () => {
102
100
  if (!ctx.appConfig.ios?.bundleIdentifier && ctx.job.platform === eas_build_job_1.Platform.IOS) {
103
101
  throw new Error('The "ios.bundleIdentifier" is required to be set in app config for builds triggered by GitHub integration. Learn more: https://docs.expo.dev/versions/latest/config/app/#bundleidentifier.');
@@ -228,7 +226,7 @@ async function validateAppConfigAsync(ctx, appConfig) {
228
226
  appConfig.extra.eas.projectId !== ctx.env.EAS_BUILD_PROJECT_ID) {
229
227
  const isUsingDynamicConfig = (await fs_extra_1.default.pathExists(path_1.default.join(ctx.getReactNativeProjectDirectory(), 'app.config.ts'))) ||
230
228
  (await fs_extra_1.default.pathExists(path_1.default.join(ctx.getReactNativeProjectDirectory(), 'app.config.js')));
231
- const isGitHubBuild = ctx.job.triggeredBy === common_1.BuildTrigger.GIT_BASED_INTEGRATION;
229
+ const isGitHubBuild = ctx.job.triggeredBy === eas_build_job_1.BuildTrigger.GIT_BASED_INTEGRATION;
232
230
  let extraMessage = '';
233
231
  if (isGitHubBuild && isUsingDynamicConfig) {
234
232
  extraMessage =
@@ -241,7 +239,7 @@ async function validateAppConfigAsync(ctx, appConfig) {
241
239
  extraMessage =
242
240
  'If you are using environment variables to switch between projects in app.config.js/app.config.ts, make sure those variables are also set inside EAS Build. You can do that using "env" field in eas.json or EAS environment variables. ';
243
241
  }
244
- throw new errors_1.UserFacingError('EAS_BUILD_PROJECT_ID_MISMATCH', `The value of the "extra.eas.projectId" field (${appConfig.extra.eas.projectId}) in the app config does not match the current project id (${ctx.env.EAS_BUILD_PROJECT_ID}). ${extraMessage}Learn more: https://expo.fyi/eas-config-mismatch.`);
242
+ throw new eas_build_job_1.UserError('EAS_BUILD_PROJECT_ID_MISMATCH', `The value of the "extra.eas.projectId" field (${appConfig.extra.eas.projectId}) in the app config does not match the current project id (${ctx.env.EAS_BUILD_PROJECT_ID}). ${extraMessage}Learn more: https://expo.fyi/eas-config-mismatch.`);
245
243
  }
246
244
  else if (ctx.env.EAS_BUILD_PROJECT_ID && !appConfig?.extra?.eas?.projectId) {
247
245
  ctx.logger.error(`The "extra.eas.projectId" field is missing from your app config.`);
package/dist/context.d.ts CHANGED
@@ -47,6 +47,7 @@ export interface BuildContextOptions {
47
47
  reportBuildPhaseStats?: (stats: BuildPhaseStats) => void;
48
48
  skipNativeBuild?: boolean;
49
49
  metadata?: Metadata;
50
+ expoApiV2BaseUrl?: string;
50
51
  }
51
52
  export declare class SkipNativeBuildError extends Error {
52
53
  }
@@ -60,6 +61,7 @@ export declare class BuildContext<TJob extends Job = Job> {
60
61
  extras?: Record<string, string>;
61
62
  }) => void;
62
63
  readonly skipNativeBuild?: boolean;
64
+ readonly expoApiV2BaseUrl?: string;
63
65
  artifacts: Artifacts;
64
66
  private readonly _isLocal;
65
67
  private _env;
package/dist/context.js CHANGED
@@ -23,6 +23,7 @@ class BuildContext {
23
23
  cacheManager;
24
24
  reportError;
25
25
  skipNativeBuild;
26
+ expoApiV2BaseUrl;
26
27
  artifacts = {};
27
28
  _isLocal;
28
29
  _env;
@@ -47,6 +48,7 @@ class BuildContext {
47
48
  this._job = job;
48
49
  this._metadata = options.metadata;
49
50
  this.skipNativeBuild = options.skipNativeBuild;
51
+ this.expoApiV2BaseUrl = options.expoApiV2BaseUrl;
50
52
  this.reportBuildPhaseStats = options.reportBuildPhaseStats;
51
53
  const environmentSecrets = this.getEnvironmentSecrets(job);
52
54
  this._env = {
@@ -1,6 +1,6 @@
1
1
  import { BuildJob, Env, Job, Metadata, StaticJobInterpolationContext } from '@expo/eas-build-job';
2
2
  import { bunyan } from '@expo/logger';
3
- import { BuildRuntimePlatform, ExternalBuildContextProvider } from '@expo/steps';
3
+ import { BuildRuntimePlatform, ExternalBuildContextProvider, StepMetric } from '@expo/steps';
4
4
  import { Client } from '@urql/core';
5
5
  import { ArtifactToUpload, BuildContext } from './context';
6
6
  export interface BuilderRuntimeApi {
@@ -26,6 +26,8 @@ export declare class CustomBuildContext<TJob extends Job = Job> implements Exter
26
26
  job: TJob;
27
27
  metadata?: Metadata;
28
28
  private _env;
29
+ private readonly expoApiV2BaseUrl?;
30
+ private readonly pendingMetricUploads;
29
31
  constructor(buildCtx: BuildContext<TJob>);
30
32
  hasBuildJob(): this is CustomBuildContext<BuildJob>;
31
33
  get runtimePlatform(): BuildRuntimePlatform;
@@ -33,4 +35,6 @@ export declare class CustomBuildContext<TJob extends Job = Job> implements Exter
33
35
  staticContext(): Omit<StaticJobInterpolationContext, 'steps'>;
34
36
  updateEnv(env: Env): void;
35
37
  updateJobInformation(job: TJob, metadata: Metadata): void;
38
+ reportStepMetric(metric: StepMetric): void;
39
+ drainPendingMetricUploads(): Promise<void>;
36
40
  }
@@ -8,6 +8,7 @@ const eas_build_job_1 = require("@expo/eas-build-job");
8
8
  const steps_1 = require("@expo/steps");
9
9
  const assert_1 = __importDefault(require("assert"));
10
10
  const path_1 = __importDefault(require("path"));
11
+ const stepMetrics_1 = require("./utils/stepMetrics");
11
12
  const platformToBuildRuntimePlatform = {
12
13
  [eas_build_job_1.Platform.ANDROID]: steps_1.BuildRuntimePlatform.LINUX,
13
14
  [eas_build_job_1.Platform.IOS]: steps_1.BuildRuntimePlatform.DARWIN,
@@ -39,6 +40,8 @@ class CustomBuildContext {
39
40
  job;
40
41
  metadata;
41
42
  _env;
43
+ expoApiV2BaseUrl;
44
+ pendingMetricUploads = [];
42
45
  constructor(buildCtx) {
43
46
  this._env = buildCtx.env;
44
47
  this.job = buildCtx.job;
@@ -52,6 +55,7 @@ class CustomBuildContext {
52
55
  this.runtimeApi = {
53
56
  uploadArtifact: (...args) => buildCtx['uploadArtifact'](...args),
54
57
  };
58
+ this.expoApiV2BaseUrl = buildCtx.expoApiV2BaseUrl;
55
59
  this.startTime = new Date();
56
60
  }
57
61
  hasBuildJob() {
@@ -106,5 +110,23 @@ class CustomBuildContext {
106
110
  };
107
111
  this.metadata = metadata;
108
112
  }
113
+ reportStepMetric(metric) {
114
+ const workflowJobId = this._env.__WORKFLOW_JOB_ID;
115
+ const robotAccessToken = this.job.secrets?.robotAccessToken;
116
+ if (!workflowJobId || !robotAccessToken || !this.expoApiV2BaseUrl) {
117
+ return;
118
+ }
119
+ const p = (0, stepMetrics_1.uploadStepMetricsToWwwAsync)({
120
+ workflowJobId,
121
+ robotAccessToken,
122
+ expoApiV2BaseUrl: this.expoApiV2BaseUrl,
123
+ stepMetrics: [metric],
124
+ logger: this.logger,
125
+ });
126
+ this.pendingMetricUploads.push(p);
127
+ }
128
+ async drainPendingMetricUploads() {
129
+ await Promise.allSettled(this.pendingMetricUploads);
130
+ }
109
131
  }
110
132
  exports.CustomBuildContext = CustomBuildContext;
package/dist/generic.d.ts CHANGED
@@ -2,9 +2,7 @@ import { Generic } from '@expo/eas-build-job';
2
2
  import { Result } from '@expo/results';
3
3
  import { BuildWorkflow } from '@expo/steps';
4
4
  import { BuildContext } from './context';
5
- export declare function runGenericJobAsync(ctx: BuildContext<Generic.Job>, { expoApiV2BaseUrl }: {
6
- expoApiV2BaseUrl: string;
7
- }): Promise<{
5
+ export declare function runGenericJobAsync(ctx: BuildContext<Generic.Job>): Promise<{
8
6
  runResult: Result<void>;
9
7
  buildWorkflow: BuildWorkflow;
10
8
  }>;
package/dist/generic.js CHANGED
@@ -8,14 +8,17 @@ const eas_build_job_1 = require("@expo/eas-build-job");
8
8
  const results_1 = require("@expo/results");
9
9
  const steps_1 = require("@expo/steps");
10
10
  const promises_1 = __importDefault(require("fs/promises"));
11
+ const nullthrows_1 = __importDefault(require("nullthrows"));
11
12
  const projectSources_1 = require("./common/projectSources");
12
13
  const customBuildContext_1 = require("./customBuildContext");
13
14
  const easFunctionGroups_1 = require("./steps/easFunctionGroups");
14
15
  const easFunctions_1 = require("./steps/easFunctions");
15
16
  const outputs_1 = require("./utils/outputs");
16
17
  const retry_1 = require("./utils/retry");
17
- const stepMetrics_1 = require("./utils/stepMetrics");
18
- async function runGenericJobAsync(ctx, { expoApiV2BaseUrl }) {
18
+ async function runGenericJobAsync(ctx) {
19
+ // expoApiV2BaseUrl is empty when running a local build, but generic jobs
20
+ // are never executed locally, so it is always present here.
21
+ const expoApiV2BaseUrl = (0, nullthrows_1.default)(ctx.expoApiV2BaseUrl, 'expoApiV2BaseUrl is required for generic jobs');
19
22
  const customBuildCtx = new customBuildContext_1.CustomBuildContext(ctx);
20
23
  await ctx.runBuildPhase(eas_build_job_1.BuildPhase.PREPARE_PROJECT, async () => {
21
24
  await (0, retry_1.retryAsync)(async () => {
@@ -51,20 +54,15 @@ async function runGenericJobAsync(ctx, { expoApiV2BaseUrl }) {
51
54
  });
52
55
  const runResult = await (0, results_1.asyncResult)(workflow.executeAsync());
53
56
  await ctx.runBuildPhase(eas_build_job_1.BuildPhase.COMPLETE_JOB, async () => {
54
- await (0, outputs_1.uploadJobOutputsToWwwAsync)(globalContext, {
55
- logger: ctx.logger,
56
- expoApiV2BaseUrl,
57
- });
58
- const workflowJobId = globalContext.env.__WORKFLOW_JOB_ID;
59
- const robotAccessToken = ctx.job.secrets?.robotAccessToken;
60
- if (workflowJobId && robotAccessToken) {
61
- await (0, stepMetrics_1.uploadStepMetricsToWwwAsync)({
62
- workflowJobId,
63
- robotAccessToken,
64
- expoApiV2BaseUrl,
65
- stepMetrics: globalContext.stepMetrics,
57
+ const results = await Promise.allSettled([
58
+ (0, outputs_1.uploadJobOutputsToWwwAsync)(globalContext, {
66
59
  logger: ctx.logger,
67
- });
60
+ expoApiV2BaseUrl,
61
+ }),
62
+ customBuildCtx.drainPendingMetricUploads(),
63
+ ]);
64
+ if (results[0].status === 'rejected') {
65
+ throw results[0].reason;
68
66
  }
69
67
  });
70
68
  return { runResult, buildWorkflow: workflow };
@@ -25,11 +25,12 @@ export default class ProvisioningProfile<TJob extends Ios.Job> {
25
25
  get data(): ProvisioningProfileData;
26
26
  private readonly profilePath;
27
27
  private profileData?;
28
+ private developerCertificates;
28
29
  constructor(ctx: BuildContext<TJob>, profile: Buffer, keychainPath: string, target: string, certificateCommonName: string);
29
30
  init(): Promise<void>;
30
31
  destroy(): Promise<void>;
31
32
  verifyCertificate(fingerprint: string): void;
32
33
  private load;
33
34
  private resolveDistributionType;
34
- private genDerCertFingerprint;
35
+ private getAllDerCertFingerprints;
35
36
  }
@@ -35,6 +35,7 @@ class ProvisioningProfile {
35
35
  }
36
36
  profilePath;
37
37
  profileData;
38
+ developerCertificates = [];
38
39
  constructor(ctx, profile, keychainPath, target, certificateCommonName) {
39
40
  this.ctx = ctx;
40
41
  this.profile = profile;
@@ -60,10 +61,11 @@ class ProvisioningProfile {
60
61
  await fs_extra_1.default.remove(this.profilePath);
61
62
  }
62
63
  verifyCertificate(fingerprint) {
63
- const devCertFingerprint = this.genDerCertFingerprint();
64
- if (devCertFingerprint !== fingerprint) {
65
- throw new eas_build_job_1.errors.CredentialsDistCertMismatchError(`Provisioning profile and distribution certificate don't match.
66
- Profile's certificate fingerprint = ${devCertFingerprint}, distribution certificate fingerprint = ${fingerprint}`);
64
+ const devCertFingerprints = this.getAllDerCertFingerprints();
65
+ if (!devCertFingerprints.includes(fingerprint)) {
66
+ throw new eas_build_job_1.errors.CredentialsDistCertMismatchError(`Provisioning profile and distribution certificate don't match.\n` +
67
+ `Profile's certificate fingerprints = [${devCertFingerprints.join(', ')}], ` +
68
+ `distribution certificate fingerprint = ${fingerprint}`);
67
69
  }
68
70
  }
69
71
  async load() {
@@ -87,6 +89,7 @@ Profile's certificate fingerprint = ${devCertFingerprint}, distribution certific
87
89
  }
88
90
  const applicationIdentifier = plistData.Entitlements['application-identifier'];
89
91
  const bundleIdentifier = applicationIdentifier.replace(/^.+?\./, '');
92
+ this.developerCertificates = plistData.DeveloperCertificates.map((cert) => Buffer.from(cert, 'base64'));
90
93
  this.profileData = {
91
94
  path: this.profilePath,
92
95
  target: this.target,
@@ -94,7 +97,7 @@ Profile's certificate fingerprint = ${devCertFingerprint}, distribution certific
94
97
  teamId: plistData.TeamIdentifier[0],
95
98
  uuid: plistData.UUID,
96
99
  name: plistData.Name,
97
- developerCertificate: Buffer.from(plistData.DeveloperCertificates[0], 'base64'),
100
+ developerCertificate: this.developerCertificates[0],
98
101
  certificateCommonName: this.certificateCommonName,
99
102
  distributionType: this.resolveDistributionType(plistData),
100
103
  };
@@ -110,12 +113,8 @@ Profile's certificate fingerprint = ${devCertFingerprint}, distribution certific
110
113
  return DistributionType.APP_STORE;
111
114
  }
112
115
  }
113
- genDerCertFingerprint() {
114
- return crypto_1.default
115
- .createHash('sha1')
116
- .update(new Uint8Array(this.data.developerCertificate))
117
- .digest('hex')
118
- .toUpperCase();
116
+ getAllDerCertFingerprints() {
117
+ return this.developerCertificates.map(cert => crypto_1.default.createHash('sha1').update(new Uint8Array(cert)).digest('hex').toUpperCase());
119
118
  }
120
119
  }
121
120
  exports.default = ProvisioningProfile;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createDownloadArtifactFunction = createDownloadArtifactFunction;
7
7
  exports.downloadArtifactAsync = downloadArtifactAsync;
8
- const errors_1 = require("@expo/eas-build-job/dist/errors");
8
+ const eas_build_job_1 = require("@expo/eas-build-job");
9
9
  const results_1 = require("@expo/results");
10
10
  const steps_1 = require("@expo/steps");
11
11
  const node_fetch_1 = __importDefault(require("node-fetch"));
@@ -52,11 +52,11 @@ function createDownloadArtifactFunction() {
52
52
  });
53
53
  const interpolationContext = stepsCtx.global.getInterpolationContext();
54
54
  if (!('workflow' in interpolationContext)) {
55
- throw new errors_1.UserFacingError('EAS_DOWNLOAD_ARTIFACT_NO_WORKFLOW', 'No workflow found in the interpolation context.');
55
+ throw new eas_build_job_1.UserError('EAS_DOWNLOAD_ARTIFACT_NO_WORKFLOW', 'No workflow found in the interpolation context.');
56
56
  }
57
57
  const robotAccessToken = stepsCtx.global.staticContext.job.secrets?.robotAccessToken;
58
58
  if (!robotAccessToken) {
59
- throw new errors_1.UserFacingError('EAS_DOWNLOAD_ARTIFACT_NO_ROBOT_ACCESS_TOKEN', 'No robot access token found in the job secrets.');
59
+ throw new eas_build_job_1.UserError('EAS_DOWNLOAD_ARTIFACT_NO_ROBOT_ACCESS_TOKEN', 'No robot access token found in the job secrets.');
60
60
  }
61
61
  const workflowRunId = interpolationContext.workflow.id;
62
62
  const { logger } = stepsCtx;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createDownloadBuildFunction = createDownloadBuildFunction;
7
7
  exports.downloadBuildAsync = downloadBuildAsync;
8
- const errors_1 = require("@expo/eas-build-job/dist/errors");
8
+ const eas_build_job_1 = require("@expo/eas-build-job");
9
9
  const results_1 = require("@expo/results");
10
10
  const steps_1 = require("@expo/steps");
11
11
  const fast_glob_1 = require("fast-glob");
@@ -98,7 +98,7 @@ async function downloadBuildAsync({ logger, buildId, expoApiServerURL, robotAcce
98
98
  onlyDirectories: false,
99
99
  });
100
100
  if (matchingFiles.length === 0) {
101
- throw new errors_1.UserFacingError('EAS_DOWNLOAD_BUILD_NO_MATCHING_FILES', `No ${extensions.map(ext => `.${ext}`).join(', ')} entries found in the archive.`);
101
+ throw new eas_build_job_1.UserError('EAS_DOWNLOAD_BUILD_NO_MATCHING_FILES', `No ${extensions.map(ext => `.${ext}`).join(', ')} entries found in the archive.`);
102
102
  }
103
103
  logger.info(`Found ${matchingFiles.length} matching ${(0, strings_1.pluralize)(matchingFiles.length, 'entry')}:\n${matchingFiles.map(f => `- ${node_path_1.default.relative(extractionDirectory, f)}`).join('\n')}`);
104
104
  return { artifactPath: matchingFiles[0] };