eas-cli 3.6.0 → 3.7.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.
@@ -6,6 +6,7 @@ const eas_build_job_1 = require("@expo/eas-build-job");
6
6
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
7
7
  const path_1 = tslib_1.__importDefault(require("path"));
8
8
  const slash_1 = tslib_1.__importDefault(require("slash"));
9
+ const customBuildConfig_1 = require("../../project/customBuildConfig");
9
10
  const projectUtils_1 = require("../../project/projectUtils");
10
11
  const vcs_1 = require("../../vcs");
11
12
  const cacheDefaults = {
@@ -15,8 +16,9 @@ const cacheDefaults = {
15
16
  };
16
17
  async function prepareJobAsync(ctx, jobData) {
17
18
  var _a;
18
- const projectRootDirectory = (0, slash_1.default)(path_1.default.relative(await (0, vcs_1.getVcsClient)().getRootPathAsync(), ctx.projectDir)) || '.';
19
19
  const username = (0, projectUtils_1.getUsername)(ctx.exp, ctx.user);
20
+ const buildProfile = ctx.buildProfile;
21
+ const projectRootDirectory = (0, slash_1.default)(path_1.default.relative(await (0, vcs_1.getVcsClient)().getRootPathAsync(), ctx.projectDir)) || '.';
20
22
  const buildCredentials = {};
21
23
  if (jobData.credentials) {
22
24
  const targetNames = Object.keys(jobData.credentials);
@@ -24,37 +26,40 @@ async function prepareJobAsync(ctx, jobData) {
24
26
  buildCredentials[targetName] = prepareTargetCredentials(jobData.credentials[targetName]);
25
27
  }
26
28
  }
29
+ const maybeCustomBuildConfigPath = buildProfile.config
30
+ ? (0, customBuildConfig_1.getCustomBuildConfigPath)(buildProfile.config)
31
+ : undefined;
27
32
  const job = {
28
33
  type: ctx.workflow,
29
34
  platform: eas_build_job_1.Platform.IOS,
30
35
  projectArchive: jobData.projectArchive,
31
36
  projectRootDirectory,
32
37
  builderEnvironment: {
33
- image: ctx.buildProfile.image,
34
- node: ctx.buildProfile.node,
35
- yarn: ctx.buildProfile.yarn,
36
- bundler: ctx.buildProfile.bundler,
37
- cocoapods: ctx.buildProfile.cocoapods,
38
- fastlane: ctx.buildProfile.fastlane,
39
- expoCli: ctx.buildProfile.expoCli,
40
- env: ctx.buildProfile.env,
38
+ image: buildProfile.image,
39
+ node: buildProfile.node,
40
+ yarn: buildProfile.yarn,
41
+ bundler: buildProfile.bundler,
42
+ cocoapods: buildProfile.cocoapods,
43
+ fastlane: buildProfile.fastlane,
44
+ expoCli: buildProfile.expoCli,
45
+ env: buildProfile.env,
41
46
  },
42
47
  cache: {
43
48
  ...cacheDefaults,
44
- ...ctx.buildProfile.cache,
49
+ ...buildProfile.cache,
45
50
  clear: ctx.clearCache,
46
51
  },
47
52
  secrets: {
48
53
  buildCredentials,
49
54
  },
50
- releaseChannel: ctx.buildProfile.releaseChannel,
51
- updates: { channel: ctx.buildProfile.channel },
52
- developmentClient: ctx.buildProfile.developmentClient,
53
- simulator: ctx.buildProfile.simulator,
55
+ releaseChannel: buildProfile.releaseChannel,
56
+ updates: { channel: buildProfile.channel },
57
+ developmentClient: buildProfile.developmentClient,
58
+ simulator: buildProfile.simulator,
54
59
  scheme: jobData.buildScheme,
55
- buildConfiguration: ctx.buildProfile.buildConfiguration,
56
- applicationArchivePath: (_a = ctx.buildProfile.applicationArchivePath) !== null && _a !== void 0 ? _a : ctx.buildProfile.artifactPath,
57
- buildArtifactPaths: ctx.buildProfile.buildArtifactPaths,
60
+ buildConfiguration: buildProfile.buildConfiguration,
61
+ applicationArchivePath: (_a = buildProfile.applicationArchivePath) !== null && _a !== void 0 ? _a : buildProfile.artifactPath,
62
+ buildArtifactPaths: buildProfile.buildArtifactPaths,
58
63
  username,
59
64
  ...(ctx.ios.buildNumberOverride && {
60
65
  version: {
@@ -62,10 +67,15 @@ async function prepareJobAsync(ctx, jobData) {
62
67
  },
63
68
  }),
64
69
  experimental: {
65
- prebuildCommand: ctx.buildProfile.prebuildCommand,
70
+ prebuildCommand: buildProfile.prebuildCommand,
66
71
  },
67
- mode: eas_build_job_1.BuildMode.BUILD,
72
+ mode: buildProfile.config ? eas_build_job_1.BuildMode.CUSTOM : eas_build_job_1.BuildMode.BUILD,
68
73
  triggeredBy: eas_build_job_1.BuildTrigger.EAS_CLI,
74
+ ...(maybeCustomBuildConfigPath && {
75
+ customBuildConfig: {
76
+ path: maybeCustomBuildConfigPath,
77
+ },
78
+ }),
69
79
  };
70
80
  return (0, eas_build_job_1.sanitizeJob)(job);
71
81
  }
@@ -45,6 +45,7 @@ async function collectMetadataAsync(ctx) {
45
45
  }),
46
46
  runWithNoWaitFlag: ctx.noWait,
47
47
  runFromCI: ctx.runFromCI,
48
+ buildMode: ctx.buildProfile.config ? eas_build_job_1.BuildMode.CUSTOM : eas_build_job_1.BuildMode.BUILD,
48
49
  };
49
50
  return (0, eas_build_job_1.sanitizeMetadata)(metadata);
50
51
  }
@@ -66,23 +66,33 @@ async function listAndSelectBuildOnAppAsync(graphqlClient, { projectId, title, f
66
66
  }
67
67
  }
68
68
  exports.listAndSelectBuildOnAppAsync = listAndSelectBuildOnAppAsync;
69
- function formatBuildChoiceValue(value) {
70
- return value ? chalk_1.default.bold(value) : 'Unknown';
71
- }
72
69
  function createBuildToPartialChoiceMaker(selectPromptDisabledFunction) {
73
70
  return (build) => {
74
71
  var _a;
75
72
  const splitCommitMessage = (_a = build.gitCommitMessage) === null || _a === void 0 ? void 0 : _a.split('\n');
76
73
  const formattedCommitData = build.gitCommitHash && splitCommitMessage && splitCommitMessage.length > 0
77
74
  ? `${build.gitCommitHash.slice(0, 7)} "${chalk_1.default.bold(splitCommitMessage[0] + (splitCommitMessage.length > 1 ? '…' : ''))}"`
78
- : 'Unknown';
75
+ : null;
76
+ const descriptionItems = [
77
+ { name: 'Version', value: build.appVersion ? chalk_1.default.bold(build.appVersion) : null },
78
+ { name: 'Commit', value: formattedCommitData },
79
+ {
80
+ name: 'Message',
81
+ value: build.message
82
+ ? chalk_1.default.bold(build.message.length > 200 ? `${build.message.slice(0, 200)}...` : build.message)
83
+ : null,
84
+ },
85
+ {
86
+ name: build.platform === generated_1.AppPlatform.Ios ? 'Build number' : 'Version code',
87
+ value: build.appBuildVersion ? chalk_1.default.bold(build.appBuildVersion) : null,
88
+ },
89
+ ];
90
+ const filteredDescriptionArray = descriptionItems
91
+ .filter(item => item.value)
92
+ .map(item => `${chalk_1.default.bold(item.name)}: ${item.value}`);
79
93
  return {
80
94
  title: `${chalk_1.default.bold(`ID:`)} ${build.id} (${chalk_1.default.bold(`${(0, date_1.fromNow)(new Date(build.completedAt))} ago`)})`,
81
- description: [
82
- `\t${chalk_1.default.bold(`Version:`)} ${formatBuildChoiceValue(build.appVersion)}`,
83
- `\t${chalk_1.default.bold(build.platform === generated_1.AppPlatform.Ios ? 'Build number:' : 'Version code:')} ${formatBuildChoiceValue(build.appBuildVersion)}`,
84
- `\t${chalk_1.default.bold(`Commit:`)} ${formattedCommitData}`,
85
- ].join('\n'),
95
+ description: filteredDescriptionArray.length > 0 ? filteredDescriptionArray.join('\n') : '',
86
96
  disabled: selectPromptDisabledFunction === null || selectPromptDisabledFunction === void 0 ? void 0 : selectPromptDisabledFunction(build),
87
97
  };
88
98
  };
@@ -12,6 +12,7 @@ const BuildQuery_1 = require("../graphql/queries/BuildQuery");
12
12
  const AppPlatform_1 = require("../graphql/types/AppPlatform");
13
13
  const log_1 = tslib_1.__importDefault(require("../log"));
14
14
  const platform_1 = require("../platform");
15
+ const customBuildConfig_1 = require("../project/customBuildConfig");
15
16
  const expoSdk_1 = require("../project/expoSdk");
16
17
  const metroConfig_1 = require("../project/metroConfig");
17
18
  const projectUtils_1 = require("../project/projectUtils");
@@ -62,6 +63,7 @@ async function runBuildAndSubmitAsync(graphqlClient, analytics, projectDir, flag
62
63
  });
63
64
  for (const buildProfile of buildProfiles) {
64
65
  (0, remoteVersionSource_1.validateBuildProfileVersionSettings)(buildProfile, easJsonCliConfig);
66
+ await (0, customBuildConfig_1.validateCustomBuildConfigAsync)(projectDir, buildProfile.profile);
65
67
  }
66
68
  const startedBuilds = [];
67
69
  const buildCtxByPlatform = {};
@@ -2,4 +2,4 @@ import { BuildError, BuildFragment, EasBuildDeprecationInfo } from '../../graphq
2
2
  export declare function printLogsUrls(builds: BuildFragment[]): void;
3
3
  export declare function printBuildResults(builds: (BuildFragment | null)[]): void;
4
4
  export declare function printDeprecationWarnings(deprecationInfo?: EasBuildDeprecationInfo | null): void;
5
- export declare function printUserError(error: BuildError): void;
5
+ export declare function printUserError(error: BuildError, build: BuildFragment): void;
@@ -9,6 +9,22 @@ const generated_1 = require("../../graphql/generated");
9
9
  const log_1 = tslib_1.__importStar(require("../../log"));
10
10
  const platform_1 = require("../../platform");
11
11
  const url_1 = require("./url");
12
+ function terminalLinkFallback(url, text) {
13
+ return `${text} (${url})`;
14
+ }
15
+ const errorCodeToErrorMessageOverride = {
16
+ EAS_BUILD_UNKNOWN_FASTLANE_ERROR: build => `The ${(0, log_1.link)((0, url_1.getBuildLogsUrl)(build, 'run-fastlane'), {
17
+ text: '"Run fastlane"',
18
+ fallback: terminalLinkFallback((0, url_1.getBuildLogsUrl)(build, 'run-fastlane'), '"Run fastlane"'),
19
+ })} step failed with an unknown error. Refer to the ${(0, log_1.link)((0, url_1.getBuildLogsUrl)(build, 'xcode-logs'), {
20
+ text: '"Xcode logs"',
21
+ fallback: terminalLinkFallback((0, url_1.getBuildLogsUrl)(build, 'xcode-logs'), '"Xcode logs"'),
22
+ })} phase for additional, more detailed logs`,
23
+ EAS_BUILD_UNKNOWN_GRADLE_ERROR: build => `Gradle build failed with unknown error. See logs for the ${(0, log_1.link)((0, url_1.getBuildLogsUrl)(build, 'run-gradlew'), {
24
+ text: '"Run gradlew"',
25
+ fallback: terminalLinkFallback((0, url_1.getBuildLogsUrl)(build, 'run-gradlew'), '"Run gradlew"'),
26
+ })} phase for more information.`,
27
+ };
12
28
  function printLogsUrls(builds) {
13
29
  if (builds.length === 1) {
14
30
  log_1.default.log(`Build details: ${(0, log_1.link)((0, url_1.getBuildLogsUrl)(builds[0]))}`);
@@ -22,7 +38,6 @@ function printLogsUrls(builds) {
22
38
  }
23
39
  exports.printLogsUrls = printLogsUrls;
24
40
  function printBuildResults(builds) {
25
- log_1.default.newLine();
26
41
  if (builds.length === 1) {
27
42
  const [build] = builds;
28
43
  (0, assert_1.default)(build, 'Build should be defined');
@@ -34,21 +49,23 @@ function printBuildResults(builds) {
34
49
  }
35
50
  exports.printBuildResults = printBuildResults;
36
51
  function printBuildResult(build) {
37
- var _a, _b;
38
- log_1.default.addNewLineIfNone();
52
+ var _a;
39
53
  if (build.status === generated_1.BuildStatus.Errored) {
54
+ log_1.default.addNewLineIfNone();
40
55
  const userError = build.error;
41
56
  log_1.default.error(`${platform_1.appPlatformEmojis[build.platform]} ${platform_1.appPlatformDisplayNames[build.platform]} build failed${userError ? ':' : ''}`);
42
57
  if (userError) {
43
- printUserError(userError);
58
+ printUserError(userError, build);
44
59
  }
45
60
  return;
46
61
  }
47
62
  if (build.status === generated_1.BuildStatus.Canceled) {
63
+ log_1.default.addNewLineIfNone();
48
64
  log_1.default.error(`${platform_1.appPlatformEmojis[build.platform]} ${platform_1.appPlatformDisplayNames[build.platform]} build was canceled`);
49
65
  return;
50
66
  }
51
67
  if (build.distribution === generated_1.DistributionType.Internal) {
68
+ log_1.default.addNewLineIfNone();
52
69
  const logsUrl = (0, url_1.getBuildLogsUrl)(build);
53
70
  // It's tricky to install the .apk file directly on Android so let's fallback
54
71
  // to the build details page and let people press the button to download there
@@ -60,9 +77,12 @@ function printBuildResult(build) {
60
77
  else {
61
78
  // TODO: it looks like buildUrl could possibly be undefined, based on the code below.
62
79
  // we should account for this case better if it is possible
63
- const url = (_b = (_a = build.artifacts) === null || _a === void 0 ? void 0 : _a.buildUrl) !== null && _b !== void 0 ? _b : '';
64
- log_1.default.log(`${platform_1.appPlatformEmojis[build.platform]} ${platform_1.appPlatformDisplayNames[build.platform]} app:`);
65
- log_1.default.log(`${(0, log_1.link)(url)}`);
80
+ const url = (_a = build.artifacts) === null || _a === void 0 ? void 0 : _a.buildUrl;
81
+ if (url) {
82
+ log_1.default.addNewLineIfNone();
83
+ log_1.default.log(`${platform_1.appPlatformEmojis[build.platform]} ${platform_1.appPlatformDisplayNames[build.platform]} app:`);
84
+ log_1.default.log((0, log_1.link)(url));
85
+ }
66
86
  }
67
87
  }
68
88
  function printDeprecationWarnings(deprecationInfo) {
@@ -84,10 +104,22 @@ function printDeprecationWarnings(deprecationInfo) {
84
104
  }
85
105
  }
86
106
  exports.printDeprecationWarnings = printDeprecationWarnings;
87
- function printUserError(error) {
88
- log_1.default.error(error.message);
89
- if (error.docsUrl) {
90
- log_1.default.error((0, log_1.learnMore)(error.docsUrl, { dim: false }));
107
+ function printUserError(error, build) {
108
+ const maybeErrorMessageOverride = maybeGetErrorMessageOverride(error, build);
109
+ if (maybeErrorMessageOverride) {
110
+ log_1.default.error(maybeErrorMessageOverride);
111
+ }
112
+ else {
113
+ log_1.default.error(error.message);
114
+ if (error.docsUrl) {
115
+ log_1.default.error((0, log_1.learnMore)(error.docsUrl, { dim: false }));
116
+ }
91
117
  }
92
118
  }
93
119
  exports.printUserError = printUserError;
120
+ function maybeGetErrorMessageOverride(error, build) {
121
+ if (!(error.errorCode in errorCodeToErrorMessageOverride)) {
122
+ return null;
123
+ }
124
+ return errorCodeToErrorMessageOverride[error.errorCode](build);
125
+ }
@@ -1,6 +1,6 @@
1
1
  import { BuildFragment } from '../../graphql/generated';
2
2
  export declare function getProjectDashboardUrl(accountName: string, projectName: string): string;
3
- export declare function getBuildLogsUrl(build: BuildFragment): string;
3
+ export declare function getBuildLogsUrl(build: BuildFragment, hash?: string): string;
4
4
  export declare function getArtifactUrl(artifactId: string): string;
5
5
  export declare function getInternalDistributionInstallUrl(build: BuildFragment): string;
6
6
  export declare function getUpdateGroupUrl(accountName: string, projectName: string, updateGroupId: string): string;
@@ -9,11 +9,11 @@ function getProjectDashboardUrl(accountName, projectName) {
9
9
  return new URL(`/accounts/${accountName}/projects/${projectName}`, (0, api_1.getExpoWebsiteBaseUrl)()).toString();
10
10
  }
11
11
  exports.getProjectDashboardUrl = getProjectDashboardUrl;
12
- function getBuildLogsUrl(build) {
12
+ function getBuildLogsUrl(build, hash) {
13
13
  const { project } = build;
14
14
  const url = project.__typename !== 'App'
15
15
  ? `/builds/${build.id}`
16
- : `/accounts/${project.ownerAccount.name}/projects/${project.slug}/builds/${build.id}`;
16
+ : `/accounts/${project.ownerAccount.name}/projects/${project.slug}/builds/${build.id}${hash ? `#${hash}` : ''}`;
17
17
  return new URL(url, (0, api_1.getExpoWebsiteBaseUrl)()).toString();
18
18
  }
19
19
  exports.getBuildLogsUrl = getBuildLogsUrl;
@@ -73,7 +73,13 @@ async function getProjectIdAsync(sessionManager, exp, options) {
73
73
  }
74
74
  const actorUsername = (0, User_1.getActorUsername)(actor);
75
75
  if (!exp.owner && appForProjectId.ownerAccount.name !== actorUsername) {
76
- throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) does not match the logged in user (${actorUsername}) and the "owner" field is not specified. To ensure all libraries work correctly, "owner": "${appForProjectId.ownerAccount.name}" should be added to the project config, which can be done automatically by re-running "eas init". ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
76
+ if (actorUsername) {
77
+ throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) does not match the logged in user (${actorUsername}) and the "owner" field is not specified. To ensure all libraries work correctly, "owner": "${appForProjectId.ownerAccount.name}" should be added to the project config, which can be done automatically by re-running "eas init". ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
78
+ }
79
+ else {
80
+ // robot caller
81
+ throw new Error(`Project config: Owner of project identified by "extra.eas.projectId" (${appForProjectId.ownerAccount.name}) must be specified in "owner" field when using a robot access token. To ensure all libraries work correctly, "owner": "${appForProjectId.ownerAccount.name}" should be added to the project config, which can be done automatically by re-running "eas init". ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
82
+ }
77
83
  }
78
84
  if (exp.slug && exp.slug !== appForProjectId.slug) {
79
85
  throw new Error(`Project config: Slug for project identified by "extra.eas.projectId" (${appForProjectId.slug}) does not match the "slug" field (${exp.slug}). ${(0, log_1.learnMore)('https://expo.fyi/eas-project-id')}`);
@@ -104,6 +104,12 @@ class Build extends EasCommand_1.default {
104
104
  else if (process.platform !== 'darwin' && requestedPlatform === platform_1.RequestedPlatform.Ios) {
105
105
  core_1.Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
106
106
  }
107
+ else if (!['linux', 'darwin'].includes(process.platform) &&
108
+ requestedPlatform === platform_1.RequestedPlatform.Android) {
109
+ core_1.Errors.error('Unsupported platform, macOS or Linux is required to build apps for Android', {
110
+ exit: 1,
111
+ });
112
+ }
107
113
  }
108
114
  return {
109
115
  ...flags,
@@ -164,10 +164,27 @@ class UpdatePublish extends EasCommand_1.default {
164
164
  uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
165
165
  assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
166
166
  unsortedUpdateInfoGroups = await (0, publish_1.buildUnsortedUpdateInfoGroupAsync)(assets, exp);
167
- const uploadAssetSuccessMessage = uploadedAssetCount
168
- ? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
169
- : `Uploaded: No changes detected`;
170
- assetSpinner.succeed(uploadAssetSuccessMessage);
167
+ // NOTE(cedric): we assume that bundles are always uploaded, and always are part of
168
+ // `uploadedAssetCount`, perferably we don't assume. For that, we need to refactor the
169
+ // `uploadAssetsAsync` and be able to determine asset type from the uploaded assets.
170
+ const uploadedBundleCount = uploadResults.launchAssetCount;
171
+ const uploadedNormalAssetCount = Math.max(0, uploadedAssetCount - uploadedBundleCount);
172
+ const reusedNormalAssetCount = uploadResults.uniqueAssetCount - uploadedNormalAssetCount;
173
+ assetSpinner.stop();
174
+ log_1.default.withTick(`Uploaded ${uploadedBundleCount} app ${uploadedBundleCount === 1 ? 'bundle' : 'bundles'}`);
175
+ if (uploadedNormalAssetCount === 0) {
176
+ log_1.default.withTick(`Uploading assets skipped - no new assets found`);
177
+ }
178
+ else {
179
+ let message = `Uploaded ${uploadedNormalAssetCount} ${uploadedNormalAssetCount === 1 ? 'asset' : 'assets'}`;
180
+ if (reusedNormalAssetCount > 0) {
181
+ message += ` (reused ${reusedNormalAssetCount} ${reusedNormalAssetCount === 1 ? 'asset' : 'assets'})`;
182
+ }
183
+ log_1.default.withTick(message);
184
+ }
185
+ for (const uploadedAssetPath of uploadResults.uniqueUploadedAssetPaths) {
186
+ log_1.default.debug(chalk_1.default.dim(`- ${uploadedAssetPath}`));
187
+ }
171
188
  }
172
189
  catch (e) {
173
190
  assetSpinner.fail('Failed to upload');
@@ -123,11 +123,15 @@ export type Account = {
123
123
  subscription?: Maybe<SubscriptionDetails>;
124
124
  /** @deprecated No longer needed */
125
125
  subscriptionChangesPending?: Maybe<Scalars['Boolean']>;
126
+ /** Coalesced project activity for an app using pagination */
127
+ timelineActivity: TimelineActivityConnection;
126
128
  /** @deprecated See isCurrent */
127
129
  unlimitedBuilds: Scalars['Boolean'];
128
130
  updatedAt: Scalars['DateTime'];
129
131
  /** Account query object for querying EAS usage metrics */
130
132
  usageMetrics: AccountUsageMetrics;
133
+ /** Owning UserActor of this account if personal account */
134
+ userActorOwner?: Maybe<UserActor>;
131
135
  /** Pending user invitations for this account */
132
136
  userInvitations: Array<UserInvitation>;
133
137
  /** Actors associated with this account and permissions they hold */
@@ -234,6 +238,17 @@ export type AccountSnacksArgs = {
234
238
  limit: Scalars['Int'];
235
239
  offset: Scalars['Int'];
236
240
  };
241
+ /**
242
+ * An account is a container owning projects, credentials, billing and other organization
243
+ * data and settings. Actors may own and be members of accounts.
244
+ */
245
+ export type AccountTimelineActivityArgs = {
246
+ after?: InputMaybe<Scalars['String']>;
247
+ before?: InputMaybe<Scalars['String']>;
248
+ filter?: InputMaybe<TimelineActivityFilterInput>;
249
+ first?: InputMaybe<Scalars['Int']>;
250
+ last?: InputMaybe<Scalars['Int']>;
251
+ };
237
252
  export type AccountDataInput = {
238
253
  name: Scalars['String'];
239
254
  };
@@ -666,6 +681,7 @@ export type AndroidJobInput = {
666
681
  buildType?: InputMaybe<AndroidBuildType>;
667
682
  builderEnvironment?: InputMaybe<AndroidBuilderEnvironmentInput>;
668
683
  cache?: InputMaybe<BuildCacheInput>;
684
+ customBuildConfig?: InputMaybe<CustomBuildConfigInput>;
669
685
  developmentClient?: InputMaybe<Scalars['Boolean']>;
670
686
  experimental?: InputMaybe<Scalars['JSONObject']>;
671
687
  gradleCommand?: InputMaybe<Scalars['String']>;
@@ -794,10 +810,8 @@ export type App = Project & {
794
810
  /** Classic update release channel names that have at least one build */
795
811
  buildsReleaseChannels: Array<Scalars['String']>;
796
812
  deployment?: Maybe<Deployment>;
797
- deploymentNew?: Maybe<DeploymentNew>;
798
813
  /** Deployments associated with this app */
799
- deployments: Array<Deployment>;
800
- deploymentsNew: DeploymentsConnection;
814
+ deployments: DeploymentsConnection;
801
815
  description: Scalars['String'];
802
816
  /** Environment secrets for an app */
803
817
  environmentSecrets: Array<EnvironmentSecret>;
@@ -909,23 +923,11 @@ export type AppBuildsArgs = {
909
923
  };
910
924
  /** Represents an Exponent App (or Experience in legacy terms) */
911
925
  export type AppDeploymentArgs = {
912
- channel: Scalars['String'];
913
- options?: InputMaybe<DeploymentOptions>;
914
- runtimeVersion: Scalars['String'];
915
- };
916
- /** Represents an Exponent App (or Experience in legacy terms) */
917
- export type AppDeploymentNewArgs = {
918
926
  channel: Scalars['String'];
919
927
  runtimeVersion: Scalars['String'];
920
928
  };
921
929
  /** Represents an Exponent App (or Experience in legacy terms) */
922
930
  export type AppDeploymentsArgs = {
923
- limit: Scalars['Int'];
924
- mostRecentlyUpdatedAt?: InputMaybe<Scalars['DateTime']>;
925
- options?: InputMaybe<DeploymentOptions>;
926
- };
927
- /** Represents an Exponent App (or Experience in legacy terms) */
928
- export type AppDeploymentsNewArgs = {
929
931
  after?: InputMaybe<Scalars['String']>;
930
932
  before?: InputMaybe<Scalars['String']>;
931
933
  first?: InputMaybe<Scalars['Int']>;
@@ -1606,6 +1608,7 @@ export declare enum BuildIosEnterpriseProvisioning {
1606
1608
  /** Represents an Standalone App build job */
1607
1609
  export type BuildJob = ActivityTimelineProjectActivity & BuildOrBuildJob & {
1608
1610
  __typename?: 'BuildJob';
1611
+ accountUserActor?: Maybe<UserActor>;
1609
1612
  activityTimestamp: Scalars['DateTime'];
1610
1613
  actor?: Maybe<Actor>;
1611
1614
  app?: Maybe<App>;
@@ -1701,6 +1704,7 @@ export type BuildMetrics = {
1701
1704
  };
1702
1705
  export declare enum BuildMode {
1703
1706
  Build = "BUILD",
1707
+ Custom = "CUSTOM",
1704
1708
  Resign = "RESIGN"
1705
1709
  }
1706
1710
  export type BuildMutation = {
@@ -1846,6 +1850,8 @@ export declare enum BuildResourceClass {
1846
1850
  IosLarge = "IOS_LARGE",
1847
1851
  IosM1Large = "IOS_M1_LARGE",
1848
1852
  IosM1Medium = "IOS_M1_MEDIUM",
1853
+ IosM2Medium = "IOS_M2_MEDIUM",
1854
+ IosM2ProMedium = "IOS_M2_PRO_MEDIUM",
1849
1855
  IosMedium = "IOS_MEDIUM",
1850
1856
  Legacy = "LEGACY"
1851
1857
  }
@@ -1981,6 +1987,9 @@ export type CreateSubmissionResult = {
1981
1987
  /** Created submission */
1982
1988
  submission: Submission;
1983
1989
  };
1990
+ export type CustomBuildConfigInput = {
1991
+ path: Scalars['String'];
1992
+ };
1984
1993
  export type DeleteAccessTokenResult = {
1985
1994
  __typename?: 'DeleteAccessTokenResult';
1986
1995
  id: Scalars['ID'];
@@ -2052,16 +2061,17 @@ export type DeployServerlessFunctionResult = {
2052
2061
  /** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
2053
2062
  export type Deployment = {
2054
2063
  __typename?: 'Deployment';
2055
- channel?: Maybe<UpdateChannel>;
2056
- /**
2057
- * The name of this deployment's associated channel. It is specified separately from the `channel`
2058
- * field to allow specifying a deployment before an EAS Update channel has been created.
2059
- */
2060
- channelName: Scalars['String'];
2064
+ builds: DeploymentBuildsConnection;
2065
+ channel: UpdateChannel;
2061
2066
  id: Scalars['ID'];
2062
- mostRecentlyUpdatedAt: Scalars['DateTime'];
2063
- recentBuilds: Array<Build>;
2064
- runtimeVersion: Scalars['String'];
2067
+ runtime: Runtime;
2068
+ };
2069
+ /** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
2070
+ export type DeploymentBuildsArgs = {
2071
+ after?: InputMaybe<Scalars['String']>;
2072
+ before?: InputMaybe<Scalars['String']>;
2073
+ first?: InputMaybe<Scalars['Int']>;
2074
+ last?: InputMaybe<Scalars['Int']>;
2065
2075
  };
2066
2076
  export type DeploymentBuildEdge = {
2067
2077
  __typename?: 'DeploymentBuildEdge';
@@ -2077,28 +2087,9 @@ export type DeploymentBuildsConnection = {
2077
2087
  export type DeploymentEdge = {
2078
2088
  __typename?: 'DeploymentEdge';
2079
2089
  cursor: Scalars['String'];
2080
- node: DeploymentNew;
2081
- };
2082
- /** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
2083
- export type DeploymentNew = {
2084
- __typename?: 'DeploymentNew';
2085
- builds: DeploymentBuildsConnection;
2086
- channel: UpdateChannel;
2087
- id: Scalars['ID'];
2088
- runtime: Runtime;
2089
- };
2090
- /** Represents a Deployment - a set of Builds with the same Runtime Version and Channel */
2091
- export type DeploymentNewBuildsArgs = {
2092
- after?: InputMaybe<Scalars['String']>;
2093
- before?: InputMaybe<Scalars['String']>;
2094
- first?: InputMaybe<Scalars['Int']>;
2095
- last?: InputMaybe<Scalars['Int']>;
2096
- };
2097
- export type DeploymentOptions = {
2098
- /** Max number of associated builds to return */
2099
- buildListMaxSize?: InputMaybe<Scalars['Int']>;
2090
+ node: Deployment;
2100
2091
  };
2101
- /** Represents the connection over the deploymentsNew edge of an App */
2092
+ /** Represents the connection over the deployments edge of an App */
2102
2093
  export type DeploymentsConnection = {
2103
2094
  __typename?: 'DeploymentsConnection';
2104
2095
  edges: Array<DeploymentEdge>;
@@ -2604,6 +2595,7 @@ export type IosJobInput = {
2604
2595
  buildType?: InputMaybe<IosBuildType>;
2605
2596
  builderEnvironment?: InputMaybe<IosBuilderEnvironmentInput>;
2606
2597
  cache?: InputMaybe<BuildCacheInput>;
2598
+ customBuildConfig?: InputMaybe<CustomBuildConfigInput>;
2607
2599
  developmentClient?: InputMaybe<Scalars['Boolean']>;
2608
2600
  /** @deprecated */
2609
2601
  distribution?: InputMaybe<DistributionType>;
@@ -118,6 +118,7 @@ var BuildJobStatus;
118
118
  var BuildMode;
119
119
  (function (BuildMode) {
120
120
  BuildMode["Build"] = "BUILD";
121
+ BuildMode["Custom"] = "CUSTOM";
121
122
  BuildMode["Resign"] = "RESIGN";
122
123
  })(BuildMode = exports.BuildMode || (exports.BuildMode = {}));
123
124
  var BuildPriority;
@@ -137,6 +138,8 @@ var BuildResourceClass;
137
138
  BuildResourceClass["IosLarge"] = "IOS_LARGE";
138
139
  BuildResourceClass["IosM1Large"] = "IOS_M1_LARGE";
139
140
  BuildResourceClass["IosM1Medium"] = "IOS_M1_MEDIUM";
141
+ BuildResourceClass["IosM2Medium"] = "IOS_M2_MEDIUM";
142
+ BuildResourceClass["IosM2ProMedium"] = "IOS_M2_PRO_MEDIUM";
140
143
  BuildResourceClass["IosMedium"] = "IOS_MEDIUM";
141
144
  BuildResourceClass["Legacy"] = "LEGACY";
142
145
  })(BuildResourceClass = exports.BuildResourceClass || (exports.BuildResourceClass = {}));
package/build/log.d.ts CHANGED
@@ -22,9 +22,10 @@ export default class Log {
22
22
  *
23
23
  * @example https://expo.dev
24
24
  */
25
- export declare function link(url: string, { text, dim }?: {
25
+ export declare function link(url: string, { text, fallback, dim }?: {
26
26
  text?: string;
27
27
  dim?: boolean;
28
+ fallback?: string;
28
29
  }): string;
29
30
  /**
30
31
  * Provide a consistent "Learn more" link experience.
package/build/log.js CHANGED
@@ -77,10 +77,10 @@ Log.isLastLineNewLine = false;
77
77
  *
78
78
  * @example https://expo.dev
79
79
  */
80
- function link(url, { text = url, dim = true } = {}) {
80
+ function link(url, { text = url, fallback, dim = true } = {}) {
81
81
  // Links can be disabled via env variables https://github.com/jamestalmage/supports-hyperlinks/blob/master/index.js
82
82
  const output = (0, terminal_link_1.default)(text, url, {
83
- fallback: () => (text === url ? chalk_1.default.underline(url) : `${text}: ${chalk_1.default.underline(url)}`),
83
+ fallback: () => fallback !== null && fallback !== void 0 ? fallback : (text === url ? chalk_1.default.underline(url) : `${text}: ${chalk_1.default.underline(url)}`),
84
84
  });
85
85
  return dim ? chalk_1.default.dim(output) : output;
86
86
  }
@@ -43,7 +43,7 @@ function parseGradleCommand(cmd, buildGradle) {
43
43
  // separate moduleName and rest of the definition
44
44
  const splitCmd = rawCmd.split(':');
45
45
  const [moduleName, taskName] = splitCmd.length > 1 ? [splitCmd[0], splitCmd[1]] : [undefined, splitCmd[0]];
46
- const matchResult = taskName.match(/(build|bundle|assemble)(.*)(Release|Debug)/);
46
+ const matchResult = taskName.match(/(build|bundle|assemble|package)(.*)(Release|Debug)/);
47
47
  if (!matchResult) {
48
48
  throw new Error(`Failed to parse gradle command: ${cmd}`);
49
49
  }
@@ -0,0 +1,4 @@
1
+ import { Platform } from '@expo/eas-build-job';
2
+ import { BuildProfile } from '@expo/eas-json';
3
+ export declare function validateCustomBuildConfigAsync(projectDir: string, profile: BuildProfile<Platform>): Promise<void>;
4
+ export declare function getCustomBuildConfigPath(configFilename: string): string;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCustomBuildConfigPath = exports.validateCustomBuildConfigAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ async function validateCustomBuildConfigAsync(projectDir, profile) {
9
+ if (!profile.config) {
10
+ return;
11
+ }
12
+ const relativeBuildConfigPath = getCustomBuildConfigPath(profile.config);
13
+ const buildConfigPath = path_1.default.join(projectDir, relativeBuildConfigPath);
14
+ if (!(await fs_extra_1.default.pathExists(buildConfigPath))) {
15
+ throw new Error(`Custom build configuration file ${chalk_1.default.bold(relativeBuildConfigPath)} does not exist.`);
16
+ }
17
+ }
18
+ exports.validateCustomBuildConfigAsync = validateCustomBuildConfigAsync;
19
+ function getCustomBuildConfigPath(configFilename) {
20
+ return path_1.default.join('.eas/build', configFilename);
21
+ }
22
+ exports.getCustomBuildConfigPath = getCustomBuildConfigPath;