eas-cli 0.55.1 → 0.58.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 (113) hide show
  1. package/README.md +58 -49
  2. package/build/branch/queries.d.ts +5 -0
  3. package/build/branch/queries.js +87 -0
  4. package/build/build/android/build.js +17 -3
  5. package/build/build/android/graphql.js +2 -0
  6. package/build/build/android/prepareJob.js +5 -0
  7. package/build/build/android/syncProjectConfiguration.d.ts +3 -4
  8. package/build/build/android/syncProjectConfiguration.js +2 -3
  9. package/build/build/android/version.d.ts +16 -0
  10. package/build/build/android/version.js +86 -9
  11. package/build/build/build.js +8 -3
  12. package/build/build/context.d.ts +7 -3
  13. package/build/build/createContext.d.ts +5 -2
  14. package/build/build/createContext.js +9 -1
  15. package/build/build/ios/build.js +18 -17
  16. package/build/build/ios/graphql.js +2 -0
  17. package/build/build/ios/prepareJob.js +5 -0
  18. package/build/build/ios/syncProjectConfiguration.d.ts +5 -6
  19. package/build/build/ios/syncProjectConfiguration.js +3 -4
  20. package/build/build/ios/version.d.ts +23 -3
  21. package/build/build/ios/version.js +128 -28
  22. package/build/build/local.d.ts +2 -2
  23. package/build/build/local.js +7 -7
  24. package/build/build/metadata.d.ts +1 -0
  25. package/build/build/metadata.js +32 -6
  26. package/build/build/runBuildAndSubmit.d.ts +1 -0
  27. package/build/build/runBuildAndSubmit.js +29 -7
  28. package/build/build/utils/printBuildInfo.d.ts +1 -1
  29. package/build/build/utils/printBuildInfo.js +7 -13
  30. package/build/commandUtils/pagination.d.ts +13 -0
  31. package/build/commandUtils/pagination.js +42 -0
  32. package/build/commands/branch/list.d.ts +3 -4
  33. package/build/commands/branch/list.js +6 -69
  34. package/build/commands/branch/view.d.ts +3 -0
  35. package/build/commands/branch/view.js +15 -63
  36. package/build/commands/build/index.d.ts +1 -0
  37. package/build/commands/build/index.js +9 -0
  38. package/build/commands/build/version/set.d.ts +9 -0
  39. package/build/commands/build/version/set.js +81 -0
  40. package/build/commands/build/version/sync.d.ts +11 -0
  41. package/build/commands/build/version/sync.js +123 -0
  42. package/build/commands/submit.js +4 -1
  43. package/build/commands/update/index.d.ts +2 -2
  44. package/build/commands/update/index.js +24 -6
  45. package/build/commands/update/list.js +13 -18
  46. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +2 -2
  47. package/build/credentials/ios/types.d.ts +2 -0
  48. package/build/devices/actions/create/action.d.ts +5 -2
  49. package/build/devices/actions/create/action.js +12 -2
  50. package/build/devices/actions/create/developerPortalMethod.d.ts +6 -0
  51. package/build/devices/actions/create/developerPortalMethod.js +90 -0
  52. package/build/devices/manager.js +4 -4
  53. package/build/graphql/generated.d.ts +501 -59
  54. package/build/graphql/generated.js +10 -1
  55. package/build/graphql/mutations/AppVersionMutation.d.ts +11 -0
  56. package/build/graphql/mutations/AppVersionMutation.js +28 -0
  57. package/build/graphql/mutations/PublishMutation.d.ts +2 -4
  58. package/build/graphql/queries/AppVersionQuery.d.ts +4 -0
  59. package/build/graphql/queries/AppVersionQuery.js +37 -0
  60. package/build/graphql/queries/BranchQuery.d.ts +2 -1
  61. package/build/graphql/queries/BranchQuery.js +26 -0
  62. package/build/graphql/queries/BuildQuery.d.ts +4 -1
  63. package/build/graphql/queries/BuildQuery.js +19 -0
  64. package/build/graphql/queries/PublishQuery.d.ts +2 -1
  65. package/build/graphql/queries/PublishQuery.js +16 -0
  66. package/build/graphql/queries/UpdateQuery.d.ts +6 -8
  67. package/build/graphql/queries/UpdateQuery.js +27 -23
  68. package/build/graphql/types/Build.d.ts +1 -0
  69. package/build/graphql/types/Build.js +16 -1
  70. package/build/metadata/apple/config/reader.d.ts +3 -2
  71. package/build/metadata/apple/config/reader.js +22 -5
  72. package/build/metadata/apple/config/writer.d.ts +3 -2
  73. package/build/metadata/apple/config/writer.js +22 -6
  74. package/build/metadata/apple/tasks/app-version.d.ts +5 -1
  75. package/build/metadata/apple/tasks/app-version.js +109 -8
  76. package/build/metadata/apple/tasks/index.d.ts +6 -1
  77. package/build/metadata/apple/tasks/index.js +7 -2
  78. package/build/metadata/apple/types.d.ts +3 -7
  79. package/build/metadata/upload.js +6 -1
  80. package/build/platform.d.ts +1 -0
  81. package/build/platform.js +17 -1
  82. package/build/project/android/applicationId.js +2 -2
  83. package/build/project/android/versions.d.ts +3 -0
  84. package/build/project/android/versions.js +23 -0
  85. package/build/project/applicationIdentifier.d.ts +4 -0
  86. package/build/project/applicationIdentifier.js +37 -0
  87. package/build/project/ios/bundleIdentifier.js +2 -2
  88. package/build/project/ios/target.js +14 -1
  89. package/build/project/ios/versions.d.ts +3 -0
  90. package/build/project/ios/versions.js +17 -0
  91. package/build/project/publish.d.ts +3 -2
  92. package/build/project/publish.js +23 -18
  93. package/build/project/remoteVersionSource.d.ts +8 -0
  94. package/build/project/remoteVersionSource.js +61 -0
  95. package/build/submit/submit.d.ts +2 -1
  96. package/build/submit/submit.js +3 -2
  97. package/build/submit/utils/files.d.ts +0 -6
  98. package/build/submit/utils/files.js +3 -16
  99. package/build/update/queries.d.ts +3 -0
  100. package/build/update/queries.js +72 -0
  101. package/build/update/utils.d.ts +14 -0
  102. package/build/update/utils.js +26 -9
  103. package/build/uploads.d.ts +8 -2
  104. package/build/uploads.js +19 -4
  105. package/build/utils/expodash/chunk.d.ts +1 -0
  106. package/build/utils/expodash/chunk.js +16 -0
  107. package/build/utils/queries.d.ts +25 -0
  108. package/build/utils/queries.js +67 -0
  109. package/build/vcs/clients/gitNoCommit.d.ts +1 -0
  110. package/build/vcs/clients/gitNoCommit.js +14 -0
  111. package/oclif.manifest.json +1 -1
  112. package/package.json +10 -5
  113. package/schema/metadata-0.json +38 -233
@@ -11,12 +11,13 @@ const retry_1 = require("../../utils/retry");
11
11
  const task_1 = require("../task");
12
12
  class AppVersionTask extends task_1.AppleTask {
13
13
  constructor(options = {}) {
14
- var _a, _b;
14
+ var _a, _b, _c;
15
15
  super();
16
16
  this.name = () => (this.options.editLive ? 'live app version' : 'editable app version');
17
17
  this.options = {
18
18
  platform: (_a = options.platform) !== null && _a !== void 0 ? _a : apple_utils_1.Platform.IOS,
19
19
  editLive: (_b = options.editLive) !== null && _b !== void 0 ? _b : false,
20
+ version: (_c = options.version) !== null && _c !== void 0 ? _c : null,
20
21
  };
21
22
  }
22
23
  async prepareAsync({ context }) {
@@ -26,24 +27,39 @@ class AppVersionTask extends task_1.AppleTask {
26
27
  context.versionIsFirst = versionIsFirst;
27
28
  context.versionIsLive = versionIsLive;
28
29
  context.versionLocales = await version.getLocalizationsAsync();
30
+ context.versionPhasedRelease = await version.getPhasedReleaseAsync();
29
31
  }
30
32
  async downloadAsync({ config, context }) {
33
+ var _a;
31
34
  (0, assert_1.default)(context.version, `App version not initialized, can't download version`);
32
35
  config.setVersion(context.version.attributes);
33
- config.setVersionRelease(context.version.attributes);
36
+ config.setVersionReleaseType(context.version.attributes);
37
+ config.setVersionReleasePhased((_a = context.versionPhasedRelease) === null || _a === void 0 ? void 0 : _a.attributes);
34
38
  for (const locale of context.versionLocales) {
35
39
  config.setVersionLocale(locale.attributes);
36
40
  }
37
41
  }
38
42
  async uploadAsync({ config, context }) {
39
- (0, assert_1.default)(context.version, `App version not initialized, can't update version`);
40
43
  const version = config.getVersion();
41
- const release = config.getVersionRelease();
44
+ if (!context.version && (version === null || version === void 0 ? void 0 : version.versionString)) {
45
+ context.version = await (0, log_2.logAsync)(() => {
46
+ return context.app.createVersionAsync({
47
+ versionString: version.versionString,
48
+ platform: this.options.platform,
49
+ });
50
+ }, {
51
+ pending: `Creating new version ${chalk_1.default.bold(version.versionString)}...`,
52
+ success: `Created new version ${chalk_1.default.bold(version.versionString)}`,
53
+ failure: `Failed creating new version ${chalk_1.default.bold(version.versionString)}`,
54
+ });
55
+ }
56
+ (0, assert_1.default)(context.version, `App version not initialized, can't update version`);
57
+ const { versionString } = context.version.attributes;
58
+ const release = config.getVersionReleaseType();
42
59
  if (!version && !release) {
43
60
  log_1.default.log((0, chalk_1.default) `{dim - Skipped version and release update, not configured}`);
44
61
  }
45
62
  else {
46
- const { versionString } = context.version.attributes;
47
63
  const description = [version && 'version', release && 'release']
48
64
  .filter(Boolean)
49
65
  .join(' and ');
@@ -53,6 +69,24 @@ class AppVersionTask extends task_1.AppleTask {
53
69
  failure: `Failed updating ${description} info for ${chalk_1.default.bold(versionString)}`,
54
70
  });
55
71
  }
72
+ const phasedRelease = config.getVersionReleasePhased();
73
+ if (!phasedRelease && shouldDeletePhasedRelease(context.versionPhasedRelease)) {
74
+ // if phased release was enabled, but now disabled, we need to remove it
75
+ await (0, log_2.logAsync)(() => context.versionPhasedRelease.deleteAsync(), {
76
+ pending: `Disabling phased release for ${chalk_1.default.bold(versionString)}...`,
77
+ success: `Disabled phased release for ${chalk_1.default.bold(versionString)}`,
78
+ failure: `Failed disabling phased release for ${chalk_1.default.bold(versionString)}`,
79
+ });
80
+ context.versionPhasedRelease = null;
81
+ }
82
+ else if (phasedRelease && !context.versionPhasedRelease) {
83
+ // if phased release was not yet set, but now enabled, we need to create it
84
+ context.versionPhasedRelease = await (0, log_2.logAsync)(() => context.version.createPhasedReleaseAsync({ state: phasedRelease.phasedReleaseState }), {
85
+ pending: `Enabling phased release for ${chalk_1.default.bold(versionString)}...`,
86
+ success: `Enabled phased release for ${chalk_1.default.bold(versionString)}`,
87
+ failure: `Failed enabling phased release for ${chalk_1.default.bold(versionString)}`,
88
+ });
89
+ }
56
90
  const locales = config.getLocales();
57
91
  if (locales.length <= 0) {
58
92
  log_1.default.log((0, chalk_1.default) `{dim - Skipped localized version update, no locales configured}`);
@@ -80,13 +114,23 @@ class AppVersionTask extends task_1.AppleTask {
80
114
  }
81
115
  exports.AppVersionTask = AppVersionTask;
82
116
  /**
83
- * Resolve the AppStoreVersion instance, either from live or editable version.
117
+ * Resolve the AppStoreVersion instance, either from the store config, live, or editable version.
84
118
  * This also checks if this is the first version, which disallow release notes.
85
119
  */
86
- async function resolveVersionAsync(app, { editLive, platform }) {
120
+ async function resolveVersionAsync(app, { editLive, platform, version: versionString }) {
87
121
  let version = null;
88
122
  let versionIsLive = false;
89
- if (editLive) {
123
+ if (versionString) {
124
+ version = await findEditAppStoreVersionAsync(app, { platform, version: versionString });
125
+ if (!version) {
126
+ version = await createOrUpdateEditAppStoreVersionAsync(app, {
127
+ platform,
128
+ version: versionString,
129
+ });
130
+ }
131
+ versionIsLive = (version === null || version === void 0 ? void 0 : version.attributes.appStoreState) === apple_utils_1.AppStoreState.READY_FOR_SALE;
132
+ }
133
+ if (!version && editLive) {
90
134
  version = await app.getLiveAppStoreVersionAsync({ platform });
91
135
  versionIsLive = !!version;
92
136
  }
@@ -102,3 +146,60 @@ async function resolveVersionAsync(app, { editLive, platform }) {
102
146
  versionIsFirst: versions.length === 1,
103
147
  };
104
148
  }
149
+ /**
150
+ * Determine if we can, and should, delete the phased release instance.
151
+ * This returns true if the instance exist, and has one of the states below:
152
+ * - PhasedReleaseState.INACTIVE
153
+ * - PhasedReleaseState.ACTIVE
154
+ * - PhasedReleaseState.PAUSED
155
+ */
156
+ function shouldDeletePhasedRelease(phasedRelease) {
157
+ if (!phasedRelease ||
158
+ phasedRelease.attributes.phasedReleaseState === apple_utils_1.PhasedReleaseState.COMPLETE) {
159
+ return false;
160
+ }
161
+ return true;
162
+ }
163
+ /*
164
+ * Search for editable app store versions that matches the `versionString` option.
165
+ * When nothing is found, it will return `null`, and a new version should be created.
166
+ */
167
+ async function findEditAppStoreVersionAsync(app, options) {
168
+ if (options.version) {
169
+ const versions = await app.getAppStoreVersionsAsync({
170
+ query: {
171
+ limit: 200,
172
+ filter: {
173
+ platform: options.platform,
174
+ appStoreState: [
175
+ apple_utils_1.AppStoreState.PREPARE_FOR_SUBMISSION,
176
+ apple_utils_1.AppStoreState.DEVELOPER_REJECTED,
177
+ apple_utils_1.AppStoreState.REJECTED,
178
+ apple_utils_1.AppStoreState.METADATA_REJECTED,
179
+ apple_utils_1.AppStoreState.WAITING_FOR_REVIEW,
180
+ apple_utils_1.AppStoreState.INVALID_BINARY,
181
+ ].join(','),
182
+ },
183
+ },
184
+ });
185
+ const version = versions.find(model => model.attributes.versionString === options.version);
186
+ if (version) {
187
+ return version;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+ /**
193
+ * Check if we can reuse an existing editable app version that has not been published yet.
194
+ * If not, it creates a new version based on the version string.
195
+ */
196
+ async function createOrUpdateEditAppStoreVersionAsync(app, options) {
197
+ const version = await app.getEditAppStoreVersionAsync({ platform: options.platform });
198
+ if (version) {
199
+ return await version.updateAsync({ versionString: options.version });
200
+ }
201
+ return await app.createVersionAsync({
202
+ versionString: options.version,
203
+ platform: options.platform,
204
+ });
205
+ }
@@ -1,6 +1,11 @@
1
1
  import { MetadataContext } from '../../context';
2
2
  import { AppleTask } from '../task';
3
+ import { AppVersionOptions } from './app-version';
4
+ declare type AppleTaskOptions = {
5
+ version?: AppVersionOptions['version'];
6
+ };
3
7
  /**
4
8
  * List of all eligible tasks to sync local store configuration to the App store.
5
9
  */
6
- export declare function createAppleTasks(_ctx: MetadataContext): AppleTask[];
10
+ export declare function createAppleTasks(_ctx: MetadataContext, { version }?: AppleTaskOptions): AppleTask[];
11
+ export {};
@@ -8,7 +8,12 @@ const app_version_1 = require("./app-version");
8
8
  /**
9
9
  * List of all eligible tasks to sync local store configuration to the App store.
10
10
  */
11
- function createAppleTasks(_ctx) {
12
- return [new app_version_1.AppVersionTask(), new app_info_1.AppInfoTask(), new age_rating_1.AgeRatingTask(), new app_review_detail_1.AppReviewDetailTask()];
11
+ function createAppleTasks(_ctx, { version } = {}) {
12
+ return [
13
+ new app_version_1.AppVersionTask({ version }),
14
+ new app_info_1.AppInfoTask(),
15
+ new age_rating_1.AgeRatingTask(),
16
+ new app_review_detail_1.AppReviewDetailTask(),
17
+ ];
13
18
  }
14
19
  exports.createAppleTasks = createAppleTasks;
@@ -2,6 +2,7 @@
2
2
  import type { AgeRatingDeclarationProps } from '@expo/apple-utils';
3
3
  export declare type AppleLocale = string;
4
4
  export interface AppleMetadata {
5
+ version?: string;
5
6
  copyright?: string;
6
7
  info?: Record<AppleLocale, AppleInfo>;
7
8
  categories?: AppleCategory;
@@ -14,13 +15,8 @@ export declare type AppleAdvisory = Partial<AgeRatingDeclarationProps>;
14
15
  /** Apps can define up to two categories, or categories with up to two subcategories */
15
16
  export declare type AppleCategory = (string | string[])[];
16
17
  export interface AppleRelease {
17
- isPhasedReleaseEnabled?: boolean;
18
- shouldResetRatings?: boolean;
19
- autoReleaseDate?: number | string;
20
- automaticRelease?: boolean;
21
- usesThirdPartyContent?: boolean;
22
- /** Alternative to setting `ITSAppUsesNonExemptEncryption` in the binary's `Info.plist`. */
23
- usesNonExemptEncryption?: boolean;
18
+ automaticRelease?: boolean | string;
19
+ phasedRelease?: boolean;
24
20
  }
25
21
  export interface AppleInfo {
26
22
  title: string;
@@ -17,6 +17,7 @@ const telemetry_1 = require("./utils/telemetry");
17
17
  * Note, only App Store is supported at this time.
18
18
  */
19
19
  async function uploadMetadataAsync(metadataCtx) {
20
+ var _a;
20
21
  const filePath = path_1.default.resolve(metadataCtx.projectDir, metadataCtx.metadataPath);
21
22
  if (!(await fs_extra_1.default.pathExists(filePath))) {
22
23
  throw new errors_1.MetadataValidationError(`Store configuration file not found "${filePath}"`);
@@ -41,7 +42,11 @@ async function uploadMetadataAsync(metadataCtx) {
41
42
  log_1.default.log('Uploading App Store configuration...');
42
43
  const errors = [];
43
44
  const config = (0, config_1.createAppleReader)(fileData);
44
- const tasks = (0, tasks_1.createAppleTasks)(metadataCtx);
45
+ const tasks = (0, tasks_1.createAppleTasks)(metadataCtx, {
46
+ // We need to resolve a different version as soon as possible.
47
+ // This version is the parent model of all changes we are going to push.
48
+ version: (_a = config.getVersion()) === null || _a === void 0 ? void 0 : _a.versionString,
49
+ });
45
50
  const taskCtx = { app };
46
51
  for (const task of tasks) {
47
52
  try {
@@ -12,4 +12,5 @@ export declare enum RequestedPlatform {
12
12
  }
13
13
  export declare const requestedPlatformDisplayNames: Record<RequestedPlatform, string>;
14
14
  export declare function selectRequestedPlatformAsync(platform?: string): Promise<RequestedPlatform>;
15
+ export declare function selectPlatformAsync(platform?: string): Promise<Platform>;
15
16
  export declare function toPlatforms(requestedPlatform: RequestedPlatform): Platform[];
package/build/platform.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toPlatforms = exports.selectRequestedPlatformAsync = exports.requestedPlatformDisplayNames = exports.RequestedPlatform = exports.appPlatformEmojis = exports.appPlatformDisplayNames = void 0;
3
+ exports.toPlatforms = exports.selectPlatformAsync = exports.selectRequestedPlatformAsync = exports.requestedPlatformDisplayNames = exports.RequestedPlatform = exports.appPlatformEmojis = exports.appPlatformDisplayNames = void 0;
4
4
  const eas_build_job_1 = require("@expo/eas-build-job");
5
5
  const generated_1 = require("./graphql/generated");
6
6
  const prompts_1 = require("./prompts");
@@ -42,6 +42,22 @@ async function selectRequestedPlatformAsync(platform) {
42
42
  return requestedPlatform;
43
43
  }
44
44
  exports.selectRequestedPlatformAsync = selectRequestedPlatformAsync;
45
+ async function selectPlatformAsync(platform) {
46
+ if (platform && Object.values(eas_build_job_1.Platform).includes(platform.toLowerCase())) {
47
+ return platform.toLowerCase();
48
+ }
49
+ const { resolvedPlatform } = await (0, prompts_1.promptAsync)({
50
+ type: 'select',
51
+ message: 'Select platform',
52
+ name: 'resolvedPlatform',
53
+ choices: [
54
+ { title: 'Android', value: eas_build_job_1.Platform.ANDROID },
55
+ { title: 'iOS', value: eas_build_job_1.Platform.IOS },
56
+ ],
57
+ });
58
+ return resolvedPlatform;
59
+ }
60
+ exports.selectPlatformAsync = selectPlatformAsync;
45
61
  function toPlatforms(requestedPlatform) {
46
62
  if (requestedPlatform === RequestedPlatform.All) {
47
63
  return [eas_build_job_1.Platform.ANDROID, eas_build_job_1.Platform.IOS];
@@ -120,8 +120,8 @@ exports.isApplicationIdValid = isApplicationIdValid;
120
120
  let warnPrinted = false;
121
121
  function warnIfAndroidPackageDefinedInAppConfigForBareWorkflowProject(projectDir, exp) {
122
122
  if (config_plugins_1.AndroidConfig.Package.getPackage(exp) && !warnPrinted) {
123
- log_1.default.warn(`Specifying "android.package" in ${(0, projectUtils_1.getProjectConfigDescription)(projectDir)} is deprecated for bare workflow projects.\n` +
124
- 'EAS Build depends only on the value in the native code. Please remove the deprecated configuration.');
123
+ log_1.default.warn(`Specified value for "android.package" in ${(0, projectUtils_1.getProjectConfigDescription)(projectDir)} is ignored because an ${chalk_1.default.bold('android')} directory was detected in the project.\n` +
124
+ 'EAS Build will use the value found in the native code.');
125
125
  warnPrinted = true;
126
126
  }
127
127
  }
@@ -0,0 +1,3 @@
1
+ export declare const VERSION_CODE_REQUIREMENTS: string;
2
+ export declare function isValidVersionCode(versionCode: string | number): boolean;
3
+ export declare function getNextVersionCode(versionCode: string | number): number;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNextVersionCode = exports.isValidVersionCode = exports.VERSION_CODE_REQUIREMENTS = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const assert_1 = tslib_1.__importDefault(require("assert"));
6
+ const MAX_VERSION_CODE = 2000000000;
7
+ exports.VERSION_CODE_REQUIREMENTS = `versionCode needs to be a positive integer smaller or equal to ${MAX_VERSION_CODE}`;
8
+ function isValidVersionCode(versionCode) {
9
+ const numericVersionCode = typeof versionCode === 'string' ? Number(versionCode) : versionCode;
10
+ return (Number.isInteger(numericVersionCode) &&
11
+ numericVersionCode <= MAX_VERSION_CODE &&
12
+ numericVersionCode > 0);
13
+ }
14
+ exports.isValidVersionCode = isValidVersionCode;
15
+ function getNextVersionCode(versionCode) {
16
+ (0, assert_1.default)(isValidVersionCode(versionCode), `Invalid versionCode ${versionCode}`);
17
+ const numericVersionCode = typeof versionCode === 'string' ? Number(versionCode) : versionCode;
18
+ if (numericVersionCode >= MAX_VERSION_CODE) {
19
+ throw new Error(`Invalid value: ${exports.VERSION_CODE_REQUIREMENTS}.`);
20
+ }
21
+ return numericVersionCode + 1;
22
+ }
23
+ exports.getNextVersionCode = getNextVersionCode;
@@ -0,0 +1,4 @@
1
+ import { ExpoConfig } from '@expo/config';
2
+ import { Platform } from '@expo/eas-build-job';
3
+ import { BuildProfile } from '@expo/eas-json';
4
+ export declare function getApplicationIdentifierAsync(projectDir: string, exp: ExpoConfig, buildProfile: BuildProfile, platform: Platform): Promise<string>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getApplicationIdentifierAsync = void 0;
4
+ const eas_build_job_1 = require("@expo/eas-build-job");
5
+ const applicationId_1 = require("./android/applicationId");
6
+ const gradle_1 = require("./android/gradle");
7
+ const bundleIdentifier_1 = require("./ios/bundleIdentifier");
8
+ const scheme_1 = require("./ios/scheme");
9
+ const target_1 = require("./ios/target");
10
+ const workflow_1 = require("./workflow");
11
+ async function getApplicationIdentifierAsync(projectDir, exp, buildProfile, platform) {
12
+ if (platform === eas_build_job_1.Platform.ANDROID) {
13
+ const profile = buildProfile;
14
+ const workflow = await (0, workflow_1.resolveWorkflowAsync)(projectDir, eas_build_job_1.Platform.ANDROID);
15
+ const gradleContext = await (0, gradle_1.resolveGradleBuildContextAsync)(projectDir, profile);
16
+ if (workflow === eas_build_job_1.Workflow.MANAGED) {
17
+ await (0, applicationId_1.ensureApplicationIdIsDefinedForManagedProjectAsync)(projectDir, exp);
18
+ }
19
+ return await (0, applicationId_1.getApplicationIdAsync)(projectDir, exp, gradleContext);
20
+ }
21
+ else {
22
+ const profile = buildProfile;
23
+ const xcodeBuildContext = await (0, scheme_1.resolveXcodeBuildContextAsync)({ exp, projectDir, nonInteractive: false }, profile);
24
+ const targets = await (0, target_1.resolveTargetsAsync)({
25
+ projectDir,
26
+ exp,
27
+ xcodeBuildContext,
28
+ env: profile.env,
29
+ });
30
+ const applicationTarget = (0, target_1.findApplicationTarget)(targets);
31
+ return await (0, bundleIdentifier_1.getBundleIdentifierAsync)(projectDir, exp, {
32
+ targetName: applicationTarget.targetName,
33
+ buildConfiguration: applicationTarget.buildConfiguration,
34
+ });
35
+ }
36
+ }
37
+ exports.getApplicationIdentifierAsync = getApplicationIdentifierAsync;
@@ -104,8 +104,8 @@ exports.isBundleIdentifierValid = isBundleIdentifierValid;
104
104
  let warnPrinted = false;
105
105
  function warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject(projectDir, exp) {
106
106
  if (config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifier(exp) && !warnPrinted) {
107
- log_1.default.warn(`Specifying "ios.bundleIdentifier" in ${(0, projectUtils_1.getProjectConfigDescription)(projectDir)} is deprecated for bare workflow projects.\n` +
108
- 'EAS Build depends only on the value in the native code. Please remove the deprecated configuration.');
107
+ log_1.default.warn(`Specified value for "ios.bundleIdentifier" in ${(0, projectUtils_1.getProjectConfigDescription)(projectDir)} is ignored because an ${chalk_1.default.bold('ios')} directory was detected in the project.\n` +
108
+ 'EAS Build will use the value found in the native code.');
109
109
  warnPrinted = true;
110
110
  }
111
111
  }
@@ -55,6 +55,7 @@ exports.resolveMangedProjectTargetsAsync = resolveMangedProjectTargetsAsync;
55
55
  async function resolveBareProjectTargetsAsync({ exp, projectDir, xcodeBuildContext, }) {
56
56
  const { buildScheme, buildConfiguration } = xcodeBuildContext;
57
57
  const result = [];
58
+ const pbxProject = config_plugins_1.IOSConfig.XcodeUtils.getPbxproj(projectDir);
58
59
  const applicationTarget = await config_plugins_1.IOSConfig.Target.findApplicationTargetWithDependenciesAsync(projectDir, buildScheme);
59
60
  const bundleIdentifier = await (0, bundleIdentifier_1.getBundleIdentifierAsync)(projectDir, exp, {
60
61
  targetName: applicationTarget.name,
@@ -69,6 +70,7 @@ async function resolveBareProjectTargetsAsync({ exp, projectDir, xcodeBuildConte
69
70
  bundleIdentifier,
70
71
  buildConfiguration,
71
72
  entitlements: entitlements !== null && entitlements !== void 0 ? entitlements : {},
73
+ buildSettings: resolveBareProjectBuildSettings(pbxProject, applicationTarget.name, buildConfiguration),
72
74
  });
73
75
  const dependencies = await resolveBareProjectDependenciesAsync({
74
76
  exp,
@@ -76,6 +78,7 @@ async function resolveBareProjectTargetsAsync({ exp, projectDir, xcodeBuildConte
76
78
  buildConfiguration,
77
79
  target: applicationTarget,
78
80
  bundleIdentifier,
81
+ pbxProject,
79
82
  });
80
83
  if (dependencies.length > 0) {
81
84
  result.push(...dependencies);
@@ -96,7 +99,7 @@ async function resolveTargetsAsync(opts) {
96
99
  }
97
100
  }
98
101
  exports.resolveTargetsAsync = resolveTargetsAsync;
99
- async function resolveBareProjectDependenciesAsync({ exp, projectDir, buildConfiguration, target, bundleIdentifier, }) {
102
+ async function resolveBareProjectDependenciesAsync({ exp, projectDir, buildConfiguration, target, bundleIdentifier, pbxProject, }) {
100
103
  const result = [];
101
104
  if (target.dependencies && target.dependencies.length > 0) {
102
105
  for (const dependency of target.dependencies) {
@@ -114,6 +117,7 @@ async function resolveBareProjectDependenciesAsync({ exp, projectDir, buildConfi
114
117
  bundleIdentifier: dependencyBundleIdentifier,
115
118
  parentBundleIdentifier: bundleIdentifier,
116
119
  entitlements: entitlements !== null && entitlements !== void 0 ? entitlements : {},
120
+ buildSettings: resolveBareProjectBuildSettings(pbxProject, dependency.name, buildConfiguration),
117
121
  });
118
122
  const dependencyDependencies = await resolveBareProjectDependenciesAsync({
119
123
  exp,
@@ -121,6 +125,7 @@ async function resolveBareProjectDependenciesAsync({ exp, projectDir, buildConfi
121
125
  buildConfiguration,
122
126
  target: dependency,
123
127
  bundleIdentifier: dependencyBundleIdentifier,
128
+ pbxProject,
124
129
  });
125
130
  if (dependencyDependencies.length > 0) {
126
131
  result.push(...dependencyDependencies);
@@ -145,3 +150,11 @@ function findTargetByName(targets, name) {
145
150
  return target;
146
151
  }
147
152
  exports.findTargetByName = findTargetByName;
153
+ function resolveBareProjectBuildSettings(project, targetName, buildConfiguration) {
154
+ var _a;
155
+ const xcBuildConfiguration = config_plugins_1.IOSConfig.Target.getXCBuildConfigurationFromPbxproj(project, {
156
+ targetName,
157
+ buildConfiguration,
158
+ });
159
+ return (_a = xcBuildConfiguration === null || xcBuildConfiguration === void 0 ? void 0 : xcBuildConfiguration.buildSettings) !== null && _a !== void 0 ? _a : {};
160
+ }
@@ -0,0 +1,3 @@
1
+ export declare const BUILD_NUMBER_REQUIREMENTS = "buildNumber needs to consist only of up to 3 dot-separated positive integers";
2
+ export declare function isValidBuildNumber(buildNumber: string): boolean;
3
+ export declare function getNextBuildNumber(buildNumber: string): string;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNextBuildNumber = exports.isValidBuildNumber = exports.BUILD_NUMBER_REQUIREMENTS = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const assert_1 = tslib_1.__importDefault(require("assert"));
6
+ exports.BUILD_NUMBER_REQUIREMENTS = `buildNumber needs to consist only of up to 3 dot-separated positive integers`;
7
+ function isValidBuildNumber(buildNumber) {
8
+ return !!buildNumber.match(/^\d+(\.\d+)?(\.\d+)?$/);
9
+ }
10
+ exports.isValidBuildNumber = isValidBuildNumber;
11
+ function getNextBuildNumber(buildNumber) {
12
+ (0, assert_1.default)(isValidBuildNumber(buildNumber), `Invalid buildNumber ${buildNumber}`);
13
+ const comps = buildNumber.split('.');
14
+ comps[comps.length - 1] = String(Number(comps[comps.length - 1]) + 1);
15
+ return comps.join('.');
16
+ }
17
+ exports.getNextBuildNumber = getNextBuildNumber;
@@ -2,7 +2,6 @@
2
2
  import { ExpoConfig, Platform } from '@expo/config';
3
3
  import Joi from 'joi';
4
4
  import { PartialManifestAsset } from '../graphql/generated';
5
- export declare const TIMEOUT_LIMIT = 60000;
6
5
  export declare type PublishPlatform = Extract<'android' | 'ios', Platform>;
7
6
  declare type Metadata = {
8
7
  version: number;
@@ -77,6 +76,8 @@ declare type AssetUploadResult = {
77
76
  assetCount: number;
78
77
  uniqueAssetCount: number;
79
78
  uniqueUploadedAssetCount: number;
79
+ assetLimitPerUpdateGroup: number;
80
80
  };
81
- export declare function uploadAssetsAsync(assetsForUpdateInfoGroup: CollectedAssets, updateSpinnerText?: (updatedText: string) => void): Promise<AssetUploadResult>;
81
+ export declare function uploadAssetsAsync(assetsForUpdateInfoGroup: CollectedAssets, projectId: string, updateSpinnerText?: (totalAssets: number, missingAssets: number) => void): Promise<AssetUploadResult>;
82
+ export declare function isUploadedAssetCountAboveWarningThreshold(uploadedAssetCount: number, assetLimitPerUpdateGroup: number): boolean;
82
83
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = exports.TIMEOUT_LIMIT = void 0;
3
+ exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const json_file_1 = tslib_1.__importDefault(require("@expo/json-file"));
6
6
  const crypto_1 = tslib_1.__importDefault(require("crypto"));
@@ -15,7 +15,6 @@ const PublishQuery_1 = require("../graphql/queries/PublishQuery");
15
15
  const uploads_1 = require("../uploads");
16
16
  const expoCli_1 = require("../utils/expoCli");
17
17
  const uniqBy_1 = tslib_1.__importDefault(require("../utils/expodash/uniqBy"));
18
- exports.TIMEOUT_LIMIT = 60000; // 1 minute
19
18
  const fileMetadataJoi = joi_1.default.object({
20
19
  assets: joi_1.default.array()
21
20
  .required()
@@ -113,6 +112,7 @@ async function buildBundlesAsync({ projectDir, inputDir, }) {
113
112
  inputDir,
114
113
  '--experimental-bundle',
115
114
  '--non-interactive',
115
+ '--dump-sourcemap',
116
116
  ]);
117
117
  }
118
118
  exports.buildBundlesAsync = buildBundlesAsync;
@@ -184,7 +184,7 @@ async function filterOutAssetsThatAlreadyExistAsync(uniqueAssetsWithStorageKey)
184
184
  return missingAssets;
185
185
  }
186
186
  exports.filterOutAssetsThatAlreadyExistAsync = filterOutAssetsThatAlreadyExistAsync;
187
- async function uploadAssetsAsync(assetsForUpdateInfoGroup, updateSpinnerText) {
187
+ async function uploadAssetsAsync(assetsForUpdateInfoGroup, projectId, updateSpinnerText) {
188
188
  let assets = [];
189
189
  let platform;
190
190
  for (platform in assetsForUpdateInfoGroup) {
@@ -194,7 +194,6 @@ async function uploadAssetsAsync(assetsForUpdateInfoGroup, updateSpinnerText) {
194
194
  ...assetsForUpdateInfoGroup[platform].assets,
195
195
  ];
196
196
  }
197
- updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(`${assets.length} ${assets.length === 1 ? 'asset' : 'assets'} present`);
198
197
  const assetsWithStorageKey = await Promise.all(assets.map(async (asset) => {
199
198
  return {
200
199
  ...asset,
@@ -202,34 +201,40 @@ async function uploadAssetsAsync(assetsForUpdateInfoGroup, updateSpinnerText) {
202
201
  };
203
202
  }));
204
203
  const uniqueAssets = (0, uniqBy_1.default)(assetsWithStorageKey, asset => asset.storageKey);
205
- updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(`${uniqueAssets.length} unique ${uniqueAssets.length === 1 ? 'asset' : 'assets'} found`);
204
+ const totalAssets = uniqueAssets.length;
205
+ updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(totalAssets, totalAssets);
206
206
  let missingAssets = await filterOutAssetsThatAlreadyExistAsync(uniqueAssets);
207
207
  const uniqueUploadedAssetCount = missingAssets.length;
208
208
  const { specifications } = await PublishMutation_1.PublishMutation.getUploadURLsAsync(missingAssets.map(ma => ma.contentType));
209
+ updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(totalAssets, missingAssets.length);
209
210
  const assetUploadPromiseLimit = (0, promise_limit_1.default)(15);
210
- await Promise.all(missingAssets.map((missingAsset, i) => {
211
- assetUploadPromiseLimit(async () => {
212
- const presignedPost = JSON.parse(specifications[i]);
213
- await (0, uploads_1.uploadWithPresignedPostAsync)(missingAsset.path, presignedPost);
214
- });
215
- }));
216
- updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(`${missingAssets.length} new ${missingAssets.length === 1 ? 'asset' : 'assets'} uploading`);
217
- // Wait up to TIMEOUT_LIMIT for assets to be uploaded and processed
218
- const start = Date.now();
211
+ const [assetLimitPerUpdateGroup] = await Promise.all([
212
+ PublishQuery_1.PublishQuery.getAssetLimitPerUpdateGroupAsync(projectId),
213
+ missingAssets.map((missingAsset, i) => {
214
+ assetUploadPromiseLimit(async () => {
215
+ const presignedPost = JSON.parse(specifications[i]);
216
+ await (0, uploads_1.uploadWithPresignedPostAsync)(missingAsset.path, presignedPost);
217
+ });
218
+ }),
219
+ ]);
219
220
  let timeout = 1;
220
221
  while (missingAssets.length > 0) {
221
- const timeoutPromise = new Promise(resolve => setTimeout(resolve, timeout * 1000)); // linear backoff
222
+ const timeoutPromise = new Promise(resolve => setTimeout(resolve, Math.min(timeout * 1000, 5000))); // linear backoff
222
223
  missingAssets = await filterOutAssetsThatAlreadyExistAsync(missingAssets);
223
224
  await timeoutPromise; // await after filterOutAssetsThatAlreadyExistAsync for easy mocking with jest.runAllTimers
224
225
  timeout += 1;
225
- if (Date.now() - start > exports.TIMEOUT_LIMIT) {
226
- throw new Error('Asset upload timed out. Please try again.');
227
- }
226
+ updateSpinnerText === null || updateSpinnerText === void 0 ? void 0 : updateSpinnerText(totalAssets, missingAssets.length);
228
227
  }
229
228
  return {
230
229
  assetCount: assets.length,
231
230
  uniqueAssetCount: uniqueAssets.length,
232
231
  uniqueUploadedAssetCount,
232
+ assetLimitPerUpdateGroup,
233
233
  };
234
234
  }
235
235
  exports.uploadAssetsAsync = uploadAssetsAsync;
236
+ function isUploadedAssetCountAboveWarningThreshold(uploadedAssetCount, assetLimitPerUpdateGroup) {
237
+ const warningThreshold = Math.floor(assetLimitPerUpdateGroup * 0.75);
238
+ return uploadedAssetCount > warningThreshold;
239
+ }
240
+ exports.isUploadedAssetCountAboveWarningThreshold = isUploadedAssetCountAboveWarningThreshold;
@@ -0,0 +1,8 @@
1
+ import { ExpoConfig } from '@expo/config';
2
+ import { Platform } from '@expo/eas-build-job';
3
+ import { EasJson, EasJsonReader } from '@expo/eas-json';
4
+ import { ProfileData } from '../utils/profiles';
5
+ export declare function ensureVersionSourceIsRemoteAsync(projectDir: string, easJsonReader: EasJsonReader): Promise<void>;
6
+ export declare function validateBuildProfileVersionSettings(profileInfo: ProfileData<'build'>, cliConfig: EasJson['cli']): void;
7
+ export declare function validateAppConfigForRemoteVersionSource(exp: ExpoConfig, platform: Platform): void;
8
+ export declare function getBuildVersionName(platform: Platform): string;