eas-cli 2.6.0 → 2.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.
Files changed (41) hide show
  1. package/README.md +6 -1133
  2. package/build/branch/queries.d.ts +8 -1
  3. package/build/branch/queries.js +50 -1
  4. package/build/build/android/build.js +1 -0
  5. package/build/build/ios/build.js +1 -0
  6. package/build/build/local.js +1 -1
  7. package/build/build/validate.d.ts +1 -0
  8. package/build/build/validate.js +121 -1
  9. package/build/channel/queries.d.ts +11 -0
  10. package/build/channel/queries.js +46 -1
  11. package/build/commandUtils/context/contextUtils/getProjectIdAsync.js +1 -1
  12. package/build/commands/branch/create.d.ts +0 -3
  13. package/build/commands/branch/create.js +2 -27
  14. package/build/commands/channel/create.d.ts +0 -7
  15. package/build/commands/channel/create.js +4 -31
  16. package/build/commands/update/configure.d.ts +1 -0
  17. package/build/commands/update/configure.js +10 -218
  18. package/build/commands/update/index.d.ts +3 -9
  19. package/build/commands/update/index.js +136 -143
  20. package/build/graphql/generated.d.ts +26 -17
  21. package/build/graphql/types/Build.js +1 -0
  22. package/build/log.d.ts +1 -0
  23. package/build/log.js +3 -0
  24. package/build/project/projectUtils.d.ts +3 -1
  25. package/build/project/projectUtils.js +10 -3
  26. package/build/project/publish.d.ts +13 -10
  27. package/build/project/publish.js +68 -38
  28. package/build/project/workflow.d.ts +1 -0
  29. package/build/project/workflow.js +9 -1
  30. package/build/submit/ArchiveSource.js +12 -16
  31. package/build/update/configure.d.ts +22 -0
  32. package/build/update/configure.js +200 -0
  33. package/build/utils/expoCli.d.ts +6 -0
  34. package/build/utils/expoCli.js +46 -1
  35. package/build/utils/expodash/memoize.d.ts +2 -0
  36. package/build/utils/expodash/memoize.js +17 -0
  37. package/build/utils/image.d.ts +6 -0
  38. package/build/utils/image.js +107 -0
  39. package/build/utils/statuspageService.js +1 -0
  40. package/oclif.manifest.json +1 -1
  41. package/package.json +7 -3
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.truncatePublishUpdateMessage = exports.ensureBranchExistsAsync = exports.defaultPublishPlatforms = void 0;
4
+ exports.defaultPublishPlatforms = void 0;
5
5
  const tslib_1 = require("tslib");
6
6
  const config_plugins_1 = require("@expo/config-plugins");
7
7
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -9,125 +9,76 @@ const core_1 = require("@oclif/core");
9
9
  const assert_1 = tslib_1.__importDefault(require("assert"));
10
10
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
11
11
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
12
- const api_1 = require("../../api");
13
12
  const queries_1 = require("../../branch/queries");
14
13
  const utils_1 = require("../../branch/utils");
15
14
  const url_1 = require("../../build/utils/url");
15
+ const queries_2 = require("../../channel/queries");
16
16
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
17
17
  const flags_1 = require("../../commandUtils/flags");
18
18
  const pagination_1 = require("../../commandUtils/pagination");
19
19
  const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
20
20
  const generated_1 = require("../../graphql/generated");
21
21
  const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
22
- const BranchQuery_1 = require("../../graphql/queries/BranchQuery");
23
22
  const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
24
23
  const log_1 = tslib_1.__importStar(require("../../log"));
25
24
  const ora_1 = require("../../ora");
25
+ const platform_1 = require("../../platform");
26
26
  const projectUtils_1 = require("../../project/projectUtils");
27
27
  const publish_1 = require("../../project/publish");
28
28
  const workflow_1 = require("../../project/workflow");
29
29
  const prompts_1 = require("../../prompts");
30
- const queries_2 = require("../../update/queries");
30
+ const configure_1 = require("../../update/configure");
31
+ const queries_3 = require("../../update/queries");
31
32
  const utils_2 = require("../../update/utils");
32
33
  const code_signing_1 = require("../../utils/code-signing");
34
+ const uniqBy_1 = tslib_1.__importDefault(require("../../utils/expodash/uniqBy"));
33
35
  const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
34
36
  const json_1 = require("../../utils/json");
35
37
  const statuspageService_1 = require("../../utils/statuspageService");
36
38
  const vcs_1 = require("../../vcs");
37
- const create_1 = require("../branch/create");
38
- const create_2 = require("../channel/create");
39
39
  exports.defaultPublishPlatforms = ['android', 'ios'];
40
- async function ensureChannelExistsAsync(graphqlClient, { appId, branchId, channelName, }) {
41
- var _b;
42
- try {
43
- await (0, create_2.createUpdateChannelOnAppAsync)(graphqlClient, {
44
- appId,
45
- channelName,
46
- branchId,
47
- });
48
- log_1.default.withTick(`Created a channel: ${chalk_1.default.bold(channelName)} pointed at branch: ${chalk_1.default.bold(channelName)}.`);
49
- }
50
- catch (e) {
51
- const isIgnorableError = ((_b = e.graphQLErrors) === null || _b === void 0 ? void 0 : _b.length) === 1 &&
52
- e.graphQLErrors[0].extensions.errorCode === 'CHANNEL_ALREADY_EXISTS';
53
- if (!isIgnorableError) {
54
- throw e;
55
- }
40
+ function getRequestedPlatform(platform) {
41
+ switch (platform) {
42
+ case 'android':
43
+ return platform_1.RequestedPlatform.Android;
44
+ case 'ios':
45
+ return platform_1.RequestedPlatform.Ios;
46
+ case 'web':
47
+ return null;
48
+ case 'all':
49
+ return platform_1.RequestedPlatform.All;
50
+ default:
51
+ throw new Error(`Unsupported platform: ${platform}`);
56
52
  }
57
53
  }
58
- async function ensureBranchExistsAsync(graphqlClient, { appId, name: branchName }) {
59
- try {
60
- const updateBranch = await BranchQuery_1.BranchQuery.getBranchByNameAsync(graphqlClient, {
61
- appId,
62
- name: branchName,
63
- });
64
- const { id } = updateBranch;
65
- await ensureChannelExistsAsync(graphqlClient, { appId, branchId: id, channelName: branchName });
66
- return { branchId: id };
67
- }
68
- catch (error) {
69
- if (error instanceof utils_1.BranchNotFoundError) {
70
- const newUpdateBranch = await (0, create_1.createUpdateBranchOnAppAsync)(graphqlClient, {
71
- appId,
72
- name: branchName,
73
- });
74
- log_1.default.withTick(`Created branch: ${chalk_1.default.bold(branchName)}`);
75
- await ensureChannelExistsAsync(graphqlClient, {
76
- appId,
77
- branchId: newUpdateBranch.id,
78
- channelName: branchName,
79
- });
80
- return { branchId: newUpdateBranch.id };
81
- }
82
- else {
83
- throw error;
84
- }
85
- }
86
- }
87
- exports.ensureBranchExistsAsync = ensureBranchExistsAsync;
88
54
  class UpdatePublish extends EasCommand_1.default {
89
55
  async runAsync() {
90
56
  var _b, _c, _d;
91
- const { flags } = await this.parse(UpdatePublish);
92
- const paginatedQueryOptions = (0, pagination_1.getPaginatedQueryOptions)(flags);
93
- let { branch: branchName, auto: autoFlag, message, republish, group, 'input-dir': inputDir, 'skip-bundler': skipBundler, platform, 'private-key-path': privateKeyPath, 'non-interactive': nonInteractive, json: jsonFlag, } = flags;
57
+ const { flags: rawFlags } = await this.parse(UpdatePublish);
58
+ const paginatedQueryOptions = (0, pagination_1.getPaginatedQueryOptions)(rawFlags);
59
+ let { auto: autoFlag, platform: platformFlag, branchName, updateMessage, republish, groupId, inputDir, skipBundler, privateKeyPath, json: jsonFlag, nonInteractive, } = this.sanitizeFlags(rawFlags);
94
60
  const { getDynamicProjectConfigAsync, loggedIn: { graphqlClient }, } = await this.getContextAsync(UpdatePublish, {
95
61
  nonInteractive,
96
62
  });
97
63
  if (jsonFlag) {
98
64
  (0, json_1.enableJsonOutput)();
99
65
  }
100
- const platformFlag = platform;
101
- // If a group was specified, that means we are republishing it.
102
- republish = republish || !!group;
103
- const { exp, projectId, projectDir } = await getDynamicProjectConfigAsync({
66
+ const { exp: expPossiblyWithoutEasUpdateConfigured, projectId, projectDir, } = await getDynamicProjectConfigAsync({
104
67
  isPublicConfig: true,
105
68
  });
106
69
  const { exp: expPrivate } = await getDynamicProjectConfigAsync({
107
70
  isPublicConfig: false,
108
71
  });
109
72
  await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)(graphqlClient, [generated_1.StatuspageServiceName.EasUpdate]);
73
+ await (0, configure_1.ensureEASUpdatesIsConfiguredAsync)(graphqlClient, {
74
+ exp: expPossiblyWithoutEasUpdateConfigured,
75
+ platform: getRequestedPlatform(platformFlag),
76
+ projectDir,
77
+ projectId,
78
+ });
79
+ const { exp } = await getDynamicProjectConfigAsync();
110
80
  const codeSigningInfo = await (0, code_signing_1.getCodeSigningInfoAsync)(expPrivate, privateKeyPath);
111
- const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, exp.sdkVersion);
112
- if (!hasExpoUpdates && nonInteractive) {
113
- core_1.Errors.error(`${chalk_1.default.bold('expo-updates')} must already be installed when executing in non-interactive mode`, { exit: 1 });
114
- }
115
- if (!hasExpoUpdates) {
116
- const install = await (0, prompts_1.confirmAsync)({
117
- message: (0, chalk_1.default) `The module {cyan expo-updates} must be installed to load EAS updates in-app. Install?`,
118
- instructions: 'The command will abort unless you agree.',
119
- });
120
- if (install) {
121
- await (0, projectUtils_1.installExpoUpdatesAsync)(projectDir);
122
- }
123
- else {
124
- core_1.Errors.error(`Install ${chalk_1.default.bold('expo-updates')} and try again.`, {
125
- exit: 1,
126
- });
127
- }
128
- }
129
- const runtimeVersions = await getRuntimeVersionObjectAsync(exp, platformFlag, projectDir);
130
- await checkEASUpdateURLIsSetAsync(exp, projectId);
81
+ let realizedPlatforms = [];
131
82
  if (!branchName) {
132
83
  if (autoFlag) {
133
84
  branchName = await (0, utils_1.getDefaultBranchNameAsync)();
@@ -166,9 +117,9 @@ class UpdatePublish extends EasCommand_1.default {
166
117
  // If we are republishing, we don't need to worry about building the bundle or uploading the assets.
167
118
  // Instead we get the `updateInfoGroup` from the update we wish to republish.
168
119
  let updatesToRepublish;
169
- if (group) {
120
+ if (groupId) {
170
121
  const updatesByGroup = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
171
- groupId: group,
122
+ groupId,
172
123
  });
173
124
  updatesToRepublish = updatesByGroup;
174
125
  }
@@ -176,7 +127,7 @@ class UpdatePublish extends EasCommand_1.default {
176
127
  if (nonInteractive) {
177
128
  throw new Error('Must supply --group when in non-interactive mode');
178
129
  }
179
- updatesToRepublish = await (0, queries_2.selectUpdateGroupOnBranchAsync)(graphqlClient, {
130
+ updatesToRepublish = await (0, queries_3.selectUpdateGroupOnBranchAsync)(graphqlClient, {
180
131
  projectId,
181
132
  branchName,
182
133
  paginatedQueryOptions,
@@ -186,14 +137,14 @@ class UpdatePublish extends EasCommand_1.default {
186
137
  // Only republish to the specified platforms
187
138
  update => platformFlag === 'all' || update.platform === platformFlag);
188
139
  if (updatesToRepublishFilteredByPlatform.length === 0) {
189
- throw new Error(`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${group ? group : updatesToRepublish[0].group}". Did you mean to publish a new update instead?`);
140
+ throw new Error(`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${groupId ? groupId : updatesToRepublish[0].group}". Did you mean to publish a new update instead?`);
190
141
  }
191
142
  let publicationPlatformMessage;
192
143
  if (platformFlag === 'all') {
193
- if (updatesToRepublishFilteredByPlatform.length !== exports.defaultPublishPlatforms.length) {
144
+ if (updatesToRepublishFilteredByPlatform.length < exports.defaultPublishPlatforms.length) {
194
145
  log_1.default.warn(`You are republishing an update that wasn't published for all platforms.`);
195
146
  }
196
- publicationPlatformMessage = `The republished update will appear on the same plaforms it was originally published on: ${updatesToRepublishFilteredByPlatform
147
+ publicationPlatformMessage = `The republished update will appear on the same platforms it was originally published on: ${updatesToRepublishFilteredByPlatform
197
148
  .map(update => update.platform)
198
149
  .join(', ')}`;
199
150
  }
@@ -206,11 +157,12 @@ class UpdatePublish extends EasCommand_1.default {
206
157
  const platform = update.platform;
207
158
  unsortedUpdateInfoGroups[platform] = JSON.parse(manifestFragment);
208
159
  }
160
+ realizedPlatforms = updatesToRepublishFilteredByPlatform.map(update => update.platform);
209
161
  // These are the same for each member of an update group
210
- group = updatesToRepublishFilteredByPlatform[0].group;
162
+ groupId = updatesToRepublishFilteredByPlatform[0].group;
211
163
  oldMessage = (_b = updatesToRepublishFilteredByPlatform[0].message) !== null && _b !== void 0 ? _b : '';
212
164
  oldRuntimeVersion = updatesToRepublishFilteredByPlatform[0].runtimeVersion;
213
- if (!message) {
165
+ if (!updateMessage) {
214
166
  if (nonInteractive) {
215
167
  throw new Error('Must supply --message when in non-interactive mode');
216
168
  }
@@ -218,20 +170,20 @@ class UpdatePublish extends EasCommand_1.default {
218
170
  if (jsonFlag) {
219
171
  throw new Error(validationMessage);
220
172
  }
221
- ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
173
+ ({ updateMessage } = await (0, prompts_1.promptAsync)({
222
174
  type: 'text',
223
- name: 'publishMessage',
175
+ name: 'updateMessage',
224
176
  message: `Provide an update message.`,
225
- initial: `Republish "${oldMessage}" - group: ${group}`,
177
+ initial: `Republish "${oldMessage}" - group: ${groupId}`,
226
178
  validate: (value) => (value ? true : validationMessage),
227
179
  }));
228
180
  }
229
181
  }
230
182
  else {
231
- if (!message && autoFlag) {
232
- message = (_c = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _c === void 0 ? void 0 : _c.trim();
183
+ if (!updateMessage && autoFlag) {
184
+ updateMessage = (_c = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _c === void 0 ? void 0 : _c.trim();
233
185
  }
234
- if (!message) {
186
+ if (!updateMessage) {
235
187
  if (nonInteractive) {
236
188
  throw new Error('Must supply --message or use --auto when in non-interactive mode');
237
189
  }
@@ -239,9 +191,9 @@ class UpdatePublish extends EasCommand_1.default {
239
191
  if (jsonFlag) {
240
192
  throw new Error(validationMessage);
241
193
  }
242
- ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
194
+ ({ updateMessage } = await (0, prompts_1.promptAsync)({
243
195
  type: 'text',
244
- name: 'publishMessage',
196
+ name: 'updateMessage',
245
197
  message: `Provide an update message.`,
246
198
  initial: (_d = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _d === void 0 ? void 0 : _d.trim(),
247
199
  validate: (value) => (value ? true : validationMessage),
@@ -249,49 +201,66 @@ class UpdatePublish extends EasCommand_1.default {
249
201
  }
250
202
  // build bundle and upload assets for a new publish
251
203
  if (!skipBundler) {
252
- const bundleSpinner = (0, ora_1.ora)().start('Building bundle...');
204
+ const bundleSpinner = (0, ora_1.ora)().start('Exporting...');
253
205
  try {
254
- await (0, publish_1.buildBundlesAsync)({ projectDir, inputDir });
255
- bundleSpinner.succeed('Built bundle!');
206
+ await (0, publish_1.buildBundlesAsync)({ projectDir, inputDir, exp, platformFlag });
207
+ bundleSpinner.succeed('Exported bundle(s)');
256
208
  }
257
209
  catch (e) {
258
- bundleSpinner.fail('Failed to build bundle!');
210
+ bundleSpinner.fail('Export failed');
259
211
  throw e;
260
212
  }
261
213
  }
262
- const assetSpinner = (0, ora_1.ora)().start('Uploading assets...');
214
+ // After possibly bundling, assert that the input directory can be found.
215
+ const distRoot = await (0, publish_1.resolveInputDirectoryAsync)(inputDir, { skipBundler });
216
+ const assetSpinner = (0, ora_1.ora)().start('Uploading...');
263
217
  try {
264
- const platforms = platformFlag === 'all' ? exports.defaultPublishPlatforms : [platformFlag];
265
- const assets = await (0, publish_1.collectAssetsAsync)({ inputDir: inputDir, platforms });
218
+ const collectedAssets = await (0, publish_1.collectAssetsAsync)(distRoot);
219
+ const assets = (0, publish_1.filterExportedPlatformsByFlag)(collectedAssets, platformFlag);
220
+ realizedPlatforms = Object.keys(assets);
266
221
  const uploadResults = await (0, publish_1.uploadAssetsAsync)(graphqlClient, assets, projectId, (totalAssets, missingAssets) => {
267
- assetSpinner.text = `Uploading assets. Finished (${totalAssets - missingAssets}/${totalAssets})`;
222
+ assetSpinner.text = `Uploading (${totalAssets - missingAssets}/${totalAssets})`;
268
223
  });
269
224
  uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
270
225
  assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
271
226
  unsortedUpdateInfoGroups = await (0, publish_1.buildUnsortedUpdateInfoGroupAsync)(assets, exp);
272
227
  const uploadAssetSuccessMessage = uploadedAssetCount
273
- ? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'asset' : 'assets'}!`
274
- : `Uploading assets skipped -- no new assets found!`;
228
+ ? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
229
+ : `Uploaded: No changes detected`;
275
230
  assetSpinner.succeed(uploadAssetSuccessMessage);
276
231
  }
277
232
  catch (e) {
278
- assetSpinner.fail('Failed to upload assets');
233
+ assetSpinner.fail('Failed to upload');
279
234
  throw e;
280
235
  }
281
236
  }
282
- const truncatedMessage = (0, exports.truncatePublishUpdateMessage)(message);
283
- const runtimeToPlatformMapping = {};
284
- for (const runtime of new Set(Object.values(runtimeVersions))) {
285
- runtimeToPlatformMapping[runtime] = Object.entries(runtimeVersions)
286
- .filter(pair => pair[1] === runtime)
287
- .map(pair => pair[0]);
237
+ const truncatedMessage = (0, utils_2.truncateString)(updateMessage, 1024);
238
+ if (truncatedMessage !== updateMessage) {
239
+ log_1.default.warn('Update message exceeds the allowed 1024 character limit. Truncating message...');
288
240
  }
289
- const { branchId } = await ensureBranchExistsAsync(graphqlClient, {
241
+ const runtimeVersions = await getRuntimeVersionObjectAsync(exp, realizedPlatforms, projectDir);
242
+ const runtimeToPlatformMapping = [];
243
+ for (const runtime of runtimeVersions) {
244
+ const platforms = runtimeVersions
245
+ .filter(({ runtimeVersion }) => runtimeVersion === runtime.runtimeVersion)
246
+ .map(({ platform }) => platform);
247
+ if (!runtimeToPlatformMapping.find(item => item.runtimeVersion === runtime.runtimeVersion)) {
248
+ runtimeToPlatformMapping.push({ runtimeVersion: runtime.runtimeVersion, platforms });
249
+ }
250
+ }
251
+ const { branchId } = await (0, queries_1.ensureBranchExistsAsync)(graphqlClient, {
290
252
  appId: projectId,
291
- name: branchName,
253
+ branchName,
292
254
  });
255
+ await (0, queries_2.ensureChannelExistsAsync)(graphqlClient, {
256
+ appId: projectId,
257
+ branchId,
258
+ channelName: branchName,
259
+ });
260
+ log_1.default.withTick(`Channel: ${chalk_1.default.bold(branchName)} pointed at branch: ${chalk_1.default.bold(branchName)}`);
261
+ const gitCommitHash = await (0, vcs_1.getVcsClient)().getCommitHashAsync();
293
262
  // Sort the updates into different groups based on their platform specific runtime versions
294
- const updateGroups = Object.entries(runtimeToPlatformMapping).map(([runtime, platforms]) => {
263
+ const updateGroups = runtimeToPlatformMapping.map(({ runtimeVersion, platforms }) => {
295
264
  const localUpdateInfoGroup = Object.fromEntries(platforms.map(platform => [
296
265
  platform,
297
266
  unsortedUpdateInfoGroups[platform],
@@ -302,8 +271,9 @@ class UpdatePublish extends EasCommand_1.default {
302
271
  return {
303
272
  branchId,
304
273
  updateInfoGroup: localUpdateInfoGroup,
305
- runtimeVersion: republish ? oldRuntimeVersion : runtime,
274
+ runtimeVersion: republish ? oldRuntimeVersion : runtimeVersion,
306
275
  message: truncatedMessage,
276
+ gitCommitHash,
307
277
  awaitingCodeSigningInfo: !!codeSigningInfo,
308
278
  };
309
279
  });
@@ -353,10 +323,10 @@ class UpdatePublish extends EasCommand_1.default {
353
323
  log_1.default.log('👉 Since multiple runtime versions are defined, multiple update groups have been published.');
354
324
  }
355
325
  log_1.default.addNewLineIfNone();
356
- for (const runtime of new Set(Object.values(runtimeVersions))) {
357
- const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime);
326
+ for (const runtime of (0, uniqBy_1.default)(runtimeVersions, version => version.runtimeVersion)) {
327
+ const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
358
328
  if (newUpdatesForRuntimeVersion.length === 0) {
359
- throw new Error(`Publish response is missing updates with runtime ${runtime}.`);
329
+ throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
360
330
  }
361
331
  const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
362
332
  const newAndroidUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'android');
@@ -368,7 +338,7 @@ class UpdatePublish extends EasCommand_1.default {
368
338
  const updateGroupLink = (0, log_1.link)(updateGroupUrl, { dim: false });
369
339
  log_1.default.log((0, formatFields_1.default)([
370
340
  { label: 'Branch', value: branchName },
371
- { label: 'Runtime version', value: runtime },
341
+ { label: 'Runtime version', value: runtime.runtimeVersion },
372
342
  { label: 'Platform', value: platforms.join(', ') },
373
343
  { label: 'Update group ID', value: updateGroupId },
374
344
  ...(newAndroidUpdate
@@ -376,6 +346,7 @@ class UpdatePublish extends EasCommand_1.default {
376
346
  : []),
377
347
  ...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
378
348
  { label: 'Message', value: truncatedMessage },
349
+ ...(gitCommitHash ? [{ label: 'Commit', value: gitCommitHash }] : []),
379
350
  { label: 'Website link', value: updateGroupLink },
380
351
  ]));
381
352
  log_1.default.addNewLineIfNone();
@@ -390,6 +361,32 @@ class UpdatePublish extends EasCommand_1.default {
390
361
  }
391
362
  }
392
363
  }
364
+ sanitizeFlags(flags) {
365
+ var _b, _c;
366
+ const nonInteractive = (_b = flags['non-interactive']) !== null && _b !== void 0 ? _b : false;
367
+ const { auto, branch: branchName, message: updateMessage } = flags;
368
+ if (nonInteractive && !auto && !(branchName && updateMessage)) {
369
+ core_1.Errors.error('--auto or both --branch and --message are required when updating in non-interactive mode', { exit: 1 });
370
+ }
371
+ const groupId = flags.group;
372
+ const republish = flags.republish || !!groupId; // When --group is defined, we are republishing
373
+ if (nonInteractive && republish && !groupId) {
374
+ core_1.Errors.error(`--group is required when updating in non-interactive mode`, { exit: 1 });
375
+ }
376
+ return {
377
+ auto,
378
+ branchName,
379
+ updateMessage,
380
+ groupId,
381
+ republish,
382
+ inputDir: flags['input-dir'],
383
+ skipBundler: flags['skip-bundler'],
384
+ platform: flags.platform,
385
+ privateKeyPath: flags['private-key-path'],
386
+ nonInteractive,
387
+ json: (_c = flags.json) !== null && _c !== void 0 ? _c : false,
388
+ };
389
+ }
393
390
  }
394
391
  exports.default = UpdatePublish;
395
392
  _a = UpdatePublish;
@@ -422,7 +419,11 @@ UpdatePublish.flags = {
422
419
  }),
423
420
  platform: core_1.Flags.enum({
424
421
  char: 'p',
425
- options: [...exports.defaultPublishPlatforms, 'all'],
422
+ options: [
423
+ // TODO: Add web when it's fully supported
424
+ ...exports.defaultPublishPlatforms,
425
+ 'all',
426
+ ],
426
427
  default: 'all',
427
428
  required: false,
428
429
  }),
@@ -440,10 +441,13 @@ UpdatePublish.contextDefinition = {
440
441
  ..._a.ContextOptions.DynamicProjectConfig,
441
442
  ..._a.ContextOptions.LoggedIn,
442
443
  };
443
- async function getRuntimeVersionObjectAsync(exp, platformFlag, projectDir) {
444
+ /** Get runtime versions grouped by platform. Runtime version is always `null` on web where the platform is always backwards compatible. */
445
+ async function getRuntimeVersionObjectAsync(exp, platforms, projectDir) {
444
446
  var _b, _c;
445
- const platforms = (platformFlag === 'all' ? ['android', 'ios'] : [platformFlag]);
446
447
  for (const platform of platforms) {
448
+ if (platform === 'web') {
449
+ continue;
450
+ }
447
451
  const isPolicy = typeof ((_c = (_b = exp[platform]) === null || _b === void 0 ? void 0 : _b.runtimeVersion) !== null && _c !== void 0 ? _c : exp.runtimeVersion) === 'object';
448
452
  if (isPolicy) {
449
453
  const isManaged = (await (0, workflow_1.resolveWorkflowAsync)(projectDir, platform)) === eas_build_job_1.Workflow.MANAGED;
@@ -452,24 +456,13 @@ async function getRuntimeVersionObjectAsync(exp, platformFlag, projectDir) {
452
456
  }
453
457
  }
454
458
  }
455
- return Object.fromEntries(platforms.map(platform => [
456
- platform,
457
- (0, nullthrows_1.default)(config_plugins_1.Updates.getRuntimeVersion(exp, platform), `Unable to determine runtime version for ${platform}`),
458
- ]));
459
- }
460
- async function checkEASUpdateURLIsSetAsync(exp, projectId) {
461
- var _b;
462
- const configuredURL = (_b = exp.updates) === null || _b === void 0 ? void 0 : _b.url;
463
- const expectedURL = (0, api_1.getEASUpdateURL)(projectId);
464
- if (configuredURL !== expectedURL) {
465
- throw new Error(`The update URL is incorrectly configured for EAS Update. Set updates.url to ${expectedURL} in your ${chalk_1.default.bold('app.json')}.`);
466
- }
459
+ return [...new Set(platforms)].map(platform => {
460
+ if (platform === 'web') {
461
+ return { platform: 'web', runtimeVersion: 'UNVERSIONED' };
462
+ }
463
+ return {
464
+ platform,
465
+ runtimeVersion: (0, nullthrows_1.default)(config_plugins_1.Updates.getRuntimeVersion(exp, platform), `Unable to determine runtime version for ${platform_1.requestedPlatformDisplayNames[platform]}. ${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/runtime-versions/')}`),
466
+ };
467
+ });
467
468
  }
468
- const truncatePublishUpdateMessage = (originalMessage) => {
469
- if (originalMessage.length > 1024) {
470
- log_1.default.warn('Update message exceeds the allowed 1024 character limit. Truncating message...');
471
- return originalMessage.substring(0, 1021) + '...';
472
- }
473
- return originalMessage;
474
- };
475
- exports.truncatePublishUpdateMessage = truncatePublishUpdateMessage;
@@ -2774,6 +2774,7 @@ export declare type PublicArtifacts = {
2774
2774
  export declare type PublishUpdateGroupInput = {
2775
2775
  awaitingCodeSigningInfo?: InputMaybe<Scalars['Boolean']>;
2776
2776
  branchId: Scalars['String'];
2777
+ gitCommitHash?: InputMaybe<Scalars['String']>;
2777
2778
  message?: InputMaybe<Scalars['String']>;
2778
2779
  runtimeVersion: Scalars['String'];
2779
2780
  updateInfoGroup: UpdateInfoGroup;
@@ -3344,6 +3345,7 @@ export declare type Update = ActivityTimelineProjectActivity & {
3344
3345
  branchId: Scalars['ID'];
3345
3346
  codeSigningInfo?: Maybe<CodeSigningInfo>;
3346
3347
  createdAt: Scalars['DateTime'];
3348
+ gitCommitHash?: Maybe<Scalars['String']>;
3347
3349
  group: Scalars['String'];
3348
3350
  id: Scalars['ID'];
3349
3351
  manifestFragment: Scalars['String'];
@@ -3803,6 +3805,23 @@ export declare type CreateUpdateBranchForAppMutation = {
3803
3805
  };
3804
3806
  };
3805
3807
  };
3808
+ export declare type CreateUpdateChannelOnAppMutationVariables = Exact<{
3809
+ appId: Scalars['ID'];
3810
+ name: Scalars['String'];
3811
+ branchMapping: Scalars['String'];
3812
+ }>;
3813
+ export declare type CreateUpdateChannelOnAppMutation = {
3814
+ __typename?: 'RootMutation';
3815
+ updateChannel: {
3816
+ __typename?: 'UpdateChannelMutation';
3817
+ createUpdateChannelForApp: {
3818
+ __typename?: 'UpdateChannel';
3819
+ id: string;
3820
+ name: string;
3821
+ branchMapping: string;
3822
+ };
3823
+ };
3824
+ };
3806
3825
  export declare type GetBranchInfoQueryVariables = Exact<{
3807
3826
  appId: Scalars['String'];
3808
3827
  name: Scalars['String'];
@@ -3863,23 +3882,6 @@ export declare type CancelBuildMutation = {
3863
3882
  };
3864
3883
  };
3865
3884
  };
3866
- export declare type CreateUpdateChannelOnAppMutationVariables = Exact<{
3867
- appId: Scalars['ID'];
3868
- name: Scalars['String'];
3869
- branchMapping: Scalars['String'];
3870
- }>;
3871
- export declare type CreateUpdateChannelOnAppMutation = {
3872
- __typename?: 'RootMutation';
3873
- updateChannel: {
3874
- __typename?: 'UpdateChannelMutation';
3875
- createUpdateChannelForApp: {
3876
- __typename?: 'UpdateChannel';
3877
- id: string;
3878
- name: string;
3879
- branchMapping: string;
3880
- };
3881
- };
3882
- };
3883
3885
  export declare type DeleteUpdateChannelMutationVariables = Exact<{
3884
3886
  channelId: Scalars['ID'];
3885
3887
  }>;
@@ -6687,6 +6689,7 @@ export declare type CreateAndroidBuildMutation = {
6687
6689
  appBuildVersion?: string | null;
6688
6690
  runtimeVersion?: string | null;
6689
6691
  gitCommitHash?: string | null;
6692
+ gitCommitMessage?: string | null;
6690
6693
  initialQueuePosition?: number | null;
6691
6694
  queuePosition?: number | null;
6692
6695
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -6766,6 +6769,7 @@ export declare type CreateIosBuildMutation = {
6766
6769
  appBuildVersion?: string | null;
6767
6770
  runtimeVersion?: string | null;
6768
6771
  gitCommitHash?: string | null;
6772
+ gitCommitMessage?: string | null;
6769
6773
  initialQueuePosition?: number | null;
6770
6774
  queuePosition?: number | null;
6771
6775
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -7303,6 +7307,7 @@ export declare type BuildsByIdQuery = {
7303
7307
  appBuildVersion?: string | null;
7304
7308
  runtimeVersion?: string | null;
7305
7309
  gitCommitHash?: string | null;
7310
+ gitCommitMessage?: string | null;
7306
7311
  initialQueuePosition?: number | null;
7307
7312
  queuePosition?: number | null;
7308
7313
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -7371,6 +7376,7 @@ export declare type BuildsWithSubmissionsByIdQuery = {
7371
7376
  appBuildVersion?: string | null;
7372
7377
  runtimeVersion?: string | null;
7373
7378
  gitCommitHash?: string | null;
7379
+ gitCommitMessage?: string | null;
7374
7380
  initialQueuePosition?: number | null;
7375
7381
  queuePosition?: number | null;
7376
7382
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -7479,6 +7485,7 @@ export declare type ViewBuildsOnAppQuery = {
7479
7485
  appBuildVersion?: string | null;
7480
7486
  runtimeVersion?: string | null;
7481
7487
  gitCommitHash?: string | null;
7488
+ gitCommitMessage?: string | null;
7482
7489
  initialQueuePosition?: number | null;
7483
7490
  queuePosition?: number | null;
7484
7491
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -8076,6 +8083,7 @@ export declare type BuildFragment = {
8076
8083
  appBuildVersion?: string | null;
8077
8084
  runtimeVersion?: string | null;
8078
8085
  gitCommitHash?: string | null;
8086
+ gitCommitMessage?: string | null;
8079
8087
  initialQueuePosition?: number | null;
8080
8088
  queuePosition?: number | null;
8081
8089
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -8135,6 +8143,7 @@ export declare type BuildWithSubmissionsFragment = {
8135
8143
  appBuildVersion?: string | null;
8136
8144
  runtimeVersion?: string | null;
8137
8145
  gitCommitHash?: string | null;
8146
+ gitCommitMessage?: string | null;
8138
8147
  initialQueuePosition?: number | null;
8139
8148
  queuePosition?: number | null;
8140
8149
  estimatedWaitTimeLeftSeconds?: number | null;
@@ -47,6 +47,7 @@ exports.BuildFragmentNode = (0, graphql_tag_1.default) `
47
47
  appBuildVersion
48
48
  runtimeVersion
49
49
  gitCommitHash
50
+ gitCommitMessage
50
51
  initialQueuePosition
51
52
  queuePosition
52
53
  estimatedWaitTimeLeftSeconds
package/build/log.d.ts CHANGED
@@ -8,6 +8,7 @@ export default class Log {
8
8
  static debug(...args: any[]): void;
9
9
  static gray(...args: any[]): void;
10
10
  static warnDeprecatedFlag(flag: string, message: string): void;
11
+ static fail(message: string): void;
11
12
  static succeed(message: string): void;
12
13
  static withTick(...args: any[]): void;
13
14
  private static consoleLog;
package/build/log.js CHANGED
@@ -36,6 +36,9 @@ class Log {
36
36
  static warnDeprecatedFlag(flag, message) {
37
37
  Log.warn(`› ${chalk_1.default.bold('--' + flag)} flag is deprecated. ${message}`);
38
38
  }
39
+ static fail(message) {
40
+ Log.log(`${chalk_1.default.red(log_symbols_1.default.error)} ${message}`);
41
+ }
39
42
  static succeed(message) {
40
43
  Log.log(`${chalk_1.default.green(log_symbols_1.default.success)} ${message}`);
41
44
  }
@@ -15,6 +15,8 @@ export declare function getProjectConfigDescription(projectDir: string): string;
15
15
  export declare function isExpoUpdatesInstalled(projectDir: string): boolean;
16
16
  export declare function isExpoUpdatesInstalledOrAvailable(projectDir: string, sdkVersion?: string): boolean;
17
17
  export declare function validateAppVersionRuntimePolicySupportAsync(projectDir: string, exp: ExpoConfig): Promise<void>;
18
- export declare function installExpoUpdatesAsync(projectDir: string): Promise<void>;
18
+ export declare function installExpoUpdatesAsync(projectDir: string, options?: {
19
+ silent: boolean;
20
+ }): Promise<void>;
19
21
  export declare function getOwnerAccountForProjectIdAsync(graphqlClient: ExpoGraphqlClient, projectId: string): Promise<AccountFragment>;
20
22
  export declare function getDisplayNameForProjectIdAsync(graphqlClient: ExpoGraphqlClient, projectId: string): Promise<string>;