eas-cli 4.1.1 → 5.0.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 (38) hide show
  1. package/README.md +55 -55
  2. package/build/build/context.d.ts +1 -0
  3. package/build/build/createContext.js +5 -0
  4. package/build/build/local.js +1 -1
  5. package/build/build/metadata.js +1 -0
  6. package/build/build/runBuildAndSubmit.js +33 -8
  7. package/build/channel/branch-mapping.d.ts +6 -5
  8. package/build/channel/branch-mapping.js +8 -1
  9. package/build/channel/queries.d.ts +18 -0
  10. package/build/channel/queries.js +85 -5
  11. package/build/channel/utils.d.ts +13 -2
  12. package/build/commands/build/version/get.js +1 -0
  13. package/build/commands/build/version/sync.js +1 -0
  14. package/build/commands/channel/create.js +5 -53
  15. package/build/commands/metadata/lint.js +1 -0
  16. package/build/commands/metadata/pull.js +1 -0
  17. package/build/commands/metadata/push.js +1 -0
  18. package/build/commands/submit.js +1 -0
  19. package/build/commands/update/index.js +9 -0
  20. package/build/commands/update/republish.js +55 -12
  21. package/build/commands/update/roll-back-to-embedded.js +5 -1
  22. package/build/commands/update/rollback.d.ts +9 -0
  23. package/build/commands/update/rollback.js +40 -0
  24. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +10 -1
  25. package/build/log.d.ts +1 -0
  26. package/build/log.js +3 -0
  27. package/build/project/publish.d.ts +1 -0
  28. package/build/project/publish.js +9 -5
  29. package/build/rollout/actions/EndRollout.d.ts +4 -4
  30. package/build/rollout/branch-mapping.d.ts +12 -12
  31. package/build/rollout/branch-mapping.js +18 -6
  32. package/build/rollout/utils.d.ts +2 -2
  33. package/build/update/republish.d.ts +2 -2
  34. package/build/update/republish.js +23 -6
  35. package/build/utils/profiles.d.ts +2 -1
  36. package/build/utils/profiles.js +35 -3
  37. package/oclif.manifest.json +1 -1
  38. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- import { UpdateChannelBasicInfoFragment } from '../graphql/generated';
1
+ import { ChannelBasicInfo } from './utils';
2
2
  export type BranchMappingOperator = '==' | '!=' | '<' | '>' | '<=' | '>=' | 'in' | 'regex' | 'hash_lt' | 'hash_lte' | 'hash_gt' | 'hash_gte';
3
3
  export type BranchMappingObject = {
4
4
  clientKey: string;
@@ -28,10 +28,11 @@ export type EmptyBranchMapping = {
28
28
  version: number;
29
29
  data: [];
30
30
  };
31
+ export declare function getEmptyBranchMapping(): EmptyBranchMapping;
31
32
  export declare function getAlwaysTrueBranchMapping(branchId: string): AlwaysTrueBranchMapping;
32
- export declare function hasEmptyBranchMap(channelInfo: UpdateChannelBasicInfoFragment): boolean;
33
- export declare function hasStandardBranchMap(channelInfo: UpdateChannelBasicInfoFragment): boolean;
34
- export declare function getStandardBranchId(channelInfo: UpdateChannelBasicInfoFragment): string;
33
+ export declare function hasEmptyBranchMap(channelInfo: ChannelBasicInfo): boolean;
34
+ export declare function hasStandardBranchMap(channelInfo: ChannelBasicInfo): boolean;
35
+ export declare function getStandardBranchId(channelInfo: ChannelBasicInfo): string;
35
36
  export declare function isEmptyBranchMapping(branchMapping: BranchMapping): branchMapping is EmptyBranchMapping;
36
37
  export declare function isAlwaysTrueBranchMapping(branchMapping: BranchMapping): branchMapping is AlwaysTrueBranchMapping;
37
38
  export declare function getBranchIds(branchMapping: BranchMapping): string[];
@@ -45,7 +46,7 @@ export declare function isAlwaysTrue(node: BranchMappingNode): boolean;
45
46
  export declare function alwaysTrue(): BranchMappingAlwaysTrue;
46
47
  export declare function equalsOperator(): BranchMappingOperator;
47
48
  export declare function hashLtOperator(): BranchMappingOperator;
48
- export declare function assertVersion(channelInfo: UpdateChannelBasicInfoFragment, version: number): void;
49
+ export declare function assertVersion(channelInfo: ChannelBasicInfo, version: number): void;
49
50
  export declare function assertStatement(node: BranchMappingNode): asserts node is BranchMappingStatement;
50
51
  export declare function assertNodeObject(node: BranchMappingNode): asserts node is BranchMappingObject;
51
52
  export declare function assertNumber(operand: string | number | string[]): asserts operand is number;
@@ -1,6 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BranchMappingValidationError = exports.assertString = exports.assertNumber = exports.assertNodeObject = exports.assertStatement = exports.assertVersion = exports.hashLtOperator = exports.equalsOperator = exports.alwaysTrue = exports.isAlwaysTrue = exports.andStatement = exports.isNodeObject = exports.isStatement = exports.isAndStatement = exports.getNodesFromStatement = exports.getBranchMapping = exports.getBranchIds = exports.isAlwaysTrueBranchMapping = exports.isEmptyBranchMapping = exports.getStandardBranchId = exports.hasStandardBranchMap = exports.hasEmptyBranchMap = exports.getAlwaysTrueBranchMapping = void 0;
3
+ exports.BranchMappingValidationError = exports.assertString = exports.assertNumber = exports.assertNodeObject = exports.assertStatement = exports.assertVersion = exports.hashLtOperator = exports.equalsOperator = exports.alwaysTrue = exports.isAlwaysTrue = exports.andStatement = exports.isNodeObject = exports.isStatement = exports.isAndStatement = exports.getNodesFromStatement = exports.getBranchMapping = exports.getBranchIds = exports.isAlwaysTrueBranchMapping = exports.isEmptyBranchMapping = exports.getStandardBranchId = exports.hasStandardBranchMap = exports.hasEmptyBranchMap = exports.getAlwaysTrueBranchMapping = exports.getEmptyBranchMapping = void 0;
4
+ function getEmptyBranchMapping() {
5
+ return {
6
+ version: 0,
7
+ data: [],
8
+ };
9
+ }
10
+ exports.getEmptyBranchMapping = getEmptyBranchMapping;
4
11
  function getAlwaysTrueBranchMapping(branchId) {
5
12
  return {
6
13
  version: 0,
@@ -2,6 +2,7 @@ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGr
2
2
  import { PaginatedQueryOptions } from '../commandUtils/pagination';
3
3
  import { CreateUpdateChannelOnAppMutation } from '../graphql/generated';
4
4
  import { UpdateChannelObject } from '../graphql/queries/ChannelQuery';
5
+ import { ChannelBasicInfo } from './utils';
5
6
  export declare const CHANNELS_LIMIT = 25;
6
7
  export declare function selectChannelOnAppAsync(graphqlClient: ExpoGraphqlClient, { projectId, selectionPromptTitle, paginatedQueryOptions, }: {
7
8
  projectId: string;
@@ -27,3 +28,20 @@ export declare function ensureChannelExistsAsync(graphqlClient: ExpoGraphqlClien
27
28
  branchId: string;
28
29
  channelName: string;
29
30
  }): Promise<void>;
31
+ export declare function doesChannelExistAsync(graphqlClient: ExpoGraphqlClient, { appId, channelName }: {
32
+ appId: string;
33
+ channelName: string;
34
+ }): Promise<boolean>;
35
+ /**
36
+ *
37
+ * Creates a channel and links it to a branch with the same name.
38
+ *
39
+ * @param appId the app ID, also known as the project ID
40
+ * @param channelName the name of the channel to create
41
+ * @param shouldPrintJson print only the JSON output
42
+ */
43
+ export declare function createAndLinkChannelAsync(graphqlClient: ExpoGraphqlClient, { appId, channelName, shouldPrintJson, }: {
44
+ appId: string;
45
+ channelName: string;
46
+ shouldPrintJson?: boolean;
47
+ }): Promise<ChannelBasicInfo>;
@@ -1,18 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureChannelExistsAsync = exports.createChannelOnAppAsync = exports.listAndRenderBranchesAndUpdatesOnChannelAsync = exports.listAndRenderChannelsOnAppAsync = exports.selectChannelOnAppAsync = exports.CHANNELS_LIMIT = void 0;
3
+ exports.createAndLinkChannelAsync = exports.doesChannelExistAsync = exports.ensureChannelExistsAsync = exports.createChannelOnAppAsync = exports.listAndRenderBranchesAndUpdatesOnChannelAsync = exports.listAndRenderChannelsOnAppAsync = exports.selectChannelOnAppAsync = exports.CHANNELS_LIMIT = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
6
  const graphql_1 = require("graphql");
7
7
  const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
8
+ const queries_1 = require("../branch/queries");
9
+ const utils_1 = require("../branch/utils");
8
10
  const client_1 = require("../graphql/client");
9
11
  const BranchQuery_1 = require("../graphql/queries/BranchQuery");
10
12
  const ChannelQuery_1 = require("../graphql/queries/ChannelQuery");
11
13
  const UpdateChannelBasicInfo_1 = require("../graphql/types/UpdateChannelBasicInfo");
12
14
  const log_1 = tslib_1.__importDefault(require("../log"));
15
+ const projectUtils_1 = require("../project/projectUtils");
13
16
  const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
14
17
  const json_1 = require("../utils/json");
15
- const queries_1 = require("../utils/queries");
18
+ const queries_2 = require("../utils/queries");
19
+ const errors_1 = require("./errors");
16
20
  const print_utils_1 = require("./print-utils");
17
21
  exports.CHANNELS_LIMIT = 25;
18
22
  async function selectChannelOnAppAsync(graphqlClient, { projectId, selectionPromptTitle, paginatedQueryOptions, }) {
@@ -20,7 +24,7 @@ async function selectChannelOnAppAsync(graphqlClient, { projectId, selectionProm
20
24
  if (paginatedQueryOptions.nonInteractive) {
21
25
  throw new Error('Unable to select a channel in non-interactive mode.');
22
26
  }
23
- const updateChannel = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
27
+ const updateChannel = await (0, queries_2.paginatedQueryWithSelectPromptAsync)({
24
28
  limit: (_a = paginatedQueryOptions.limit) !== null && _a !== void 0 ? _a : exports.CHANNELS_LIMIT,
25
29
  offset: paginatedQueryOptions.offset,
26
30
  queryToPerform: (limit, offset) => queryChannelsOnAppAsync(graphqlClient, { appId: projectId, limit, offset }),
@@ -47,7 +51,7 @@ async function listAndRenderChannelsOnAppAsync(graphqlClient, { projectId, pagin
47
51
  renderPageOfChannels(channels, paginatedQueryOptions);
48
52
  }
49
53
  else {
50
- await (0, queries_1.paginatedQueryWithConfirmPromptAsync)({
54
+ await (0, queries_2.paginatedQueryWithConfirmPromptAsync)({
51
55
  limit: (_b = paginatedQueryOptions.limit) !== null && _b !== void 0 ? _b : exports.CHANNELS_LIMIT,
52
56
  offset: paginatedQueryOptions.offset,
53
57
  queryToPerform: (limit, offset) => queryChannelsOnAppAsync(graphqlClient, { limit, offset, appId: projectId }),
@@ -73,7 +77,7 @@ async function listAndRenderBranchesAndUpdatesOnChannelAsync(graphqlClient, { pr
73
77
  renderPageOfBranchesOnChannel(channel, branches, paginatedQueryOptions);
74
78
  }
75
79
  else {
76
- await (0, queries_1.paginatedQueryWithConfirmPromptAsync)({
80
+ await (0, queries_2.paginatedQueryWithConfirmPromptAsync)({
77
81
  limit: (_b = paginatedQueryOptions.limit) !== null && _b !== void 0 ? _b : exports.CHANNELS_LIMIT,
78
82
  offset: paginatedQueryOptions.offset,
79
83
  queryToPerform: (limit, offset) => queryBranchesAndUpdateGroupsOnChannelAsync(graphqlClient, {
@@ -179,3 +183,79 @@ async function ensureChannelExistsAsync(graphqlClient, { appId, branchId, channe
179
183
  }
180
184
  }
181
185
  exports.ensureChannelExistsAsync = ensureChannelExistsAsync;
186
+ async function doesChannelExistAsync(graphqlClient, { appId, channelName }) {
187
+ try {
188
+ await ChannelQuery_1.ChannelQuery.viewUpdateChannelAsync(graphqlClient, {
189
+ appId,
190
+ channelName,
191
+ });
192
+ }
193
+ catch (err) {
194
+ if (err instanceof errors_1.ChannelNotFoundError) {
195
+ return false;
196
+ }
197
+ throw err;
198
+ }
199
+ return true;
200
+ }
201
+ exports.doesChannelExistAsync = doesChannelExistAsync;
202
+ /**
203
+ *
204
+ * Creates a channel and links it to a branch with the same name.
205
+ *
206
+ * @param appId the app ID, also known as the project ID
207
+ * @param channelName the name of the channel to create
208
+ * @param shouldPrintJson print only the JSON output
209
+ */
210
+ async function createAndLinkChannelAsync(graphqlClient, { appId, channelName, shouldPrintJson, }) {
211
+ let branchId;
212
+ let branchMessage;
213
+ try {
214
+ const branch = await BranchQuery_1.BranchQuery.getBranchByNameAsync(graphqlClient, {
215
+ appId,
216
+ name: channelName,
217
+ });
218
+ branchId = branch.id;
219
+ branchMessage = `We found a branch with the same name`;
220
+ }
221
+ catch (error) {
222
+ if (error instanceof utils_1.BranchNotFoundError) {
223
+ const newBranch = await (0, queries_1.createUpdateBranchOnAppAsync)(graphqlClient, {
224
+ appId,
225
+ name: channelName,
226
+ });
227
+ branchId = newBranch.id;
228
+ branchMessage = `We also went ahead and made a branch with the same name`;
229
+ }
230
+ else {
231
+ throw error;
232
+ }
233
+ }
234
+ const { updateChannel: { createUpdateChannelForApp: newChannel }, } = await createChannelOnAppAsync(graphqlClient, {
235
+ appId,
236
+ channelName,
237
+ branchId,
238
+ });
239
+ if (!newChannel) {
240
+ throw new Error(`Could not create channel with name ${channelName} on project with id ${appId}`);
241
+ }
242
+ if (shouldPrintJson) {
243
+ (0, json_1.printJsonOnlyOutput)(newChannel);
244
+ }
245
+ else {
246
+ log_1.default.addNewLineIfNone();
247
+ log_1.default.withTick(`Created a new channel on project ${chalk_1.default.bold(await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, appId))}`);
248
+ log_1.default.log((0, formatFields_1.default)([
249
+ { label: 'Name', value: newChannel.name },
250
+ { label: 'ID', value: newChannel.id },
251
+ ]));
252
+ log_1.default.addNewLineIfNone();
253
+ log_1.default.withTick(`${branchMessage} and have pointed the channel at it.`);
254
+ log_1.default.log((0, formatFields_1.default)([
255
+ { label: 'Name', value: newChannel.name },
256
+ { label: 'ID', value: branchId },
257
+ ]));
258
+ }
259
+ return newChannel;
260
+ }
261
+ exports.createAndLinkChannelAsync = createAndLinkChannelAsync;
@@ -1,2 +1,13 @@
1
- import { UpdateBranchObject, UpdateChannelObject } from '../graphql/queries/ChannelQuery';
2
- export declare function getUpdateBranch(channel: UpdateChannelObject, branchId: string): UpdateBranchObject;
1
+ export type ChannelBasicInfo = {
2
+ id: string;
3
+ name: string;
4
+ branchMapping: string;
5
+ };
6
+ export type BranchBasicInfo = {
7
+ id: string;
8
+ name: string;
9
+ };
10
+ export type UpdateChannelInfoWithBranches<Branch extends BranchBasicInfo> = ChannelBasicInfo & {
11
+ updateBranches: Branch[];
12
+ };
13
+ export declare function getUpdateBranch<Branch extends BranchBasicInfo>(channel: UpdateChannelInfoWithBranches<Branch>, branchId: string): Branch;
@@ -39,6 +39,7 @@ class BuildVersionGetView extends EasCommand_1.default {
39
39
  easJsonAccessor,
40
40
  platforms,
41
41
  profileName: (_b = flags.profile) !== null && _b !== void 0 ? _b : undefined,
42
+ projectDir,
42
43
  });
43
44
  const results = {};
44
45
  for (const { profile, platform } of buildProfiles) {
@@ -38,6 +38,7 @@ class BuildVersionSyncView extends EasCommand_1.default {
38
38
  easJsonAccessor,
39
39
  platforms,
40
40
  profileName: (_b = flags.profile) !== null && _b !== void 0 ? _b : undefined,
41
+ projectDir,
41
42
  });
42
43
  for (const profileInfo of buildProfiles) {
43
44
  const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({
@@ -3,16 +3,11 @@ var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const queries_1 = require("../../branch/queries");
7
- const utils_1 = require("../../branch/utils");
8
- const queries_2 = require("../../channel/queries");
6
+ const queries_1 = require("../../channel/queries");
9
7
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
10
8
  const flags_1 = require("../../commandUtils/flags");
11
- const BranchQuery_1 = require("../../graphql/queries/BranchQuery");
12
9
  const log_1 = tslib_1.__importDefault(require("../../log"));
13
- const projectUtils_1 = require("../../project/projectUtils");
14
10
  const prompts_1 = require("../../prompts");
15
- const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
16
11
  const json_1 = require("../../utils/json");
17
12
  class ChannelCreate extends EasCommand_1.default {
18
13
  async runAsync() {
@@ -35,56 +30,13 @@ class ChannelCreate extends EasCommand_1.default {
35
30
  validate: value => (value ? true : validationMessage),
36
31
  }));
37
32
  }
38
- let branchId;
39
- let branchMessage;
40
- try {
41
- const branch = await BranchQuery_1.BranchQuery.getBranchByNameAsync(graphqlClient, {
42
- appId: projectId,
43
- name: channelName,
44
- });
45
- branchId = branch.id;
46
- branchMessage = `We found a branch with the same name`;
47
- }
48
- catch (error) {
49
- if (error instanceof utils_1.BranchNotFoundError) {
50
- const newBranch = await (0, queries_1.createUpdateBranchOnAppAsync)(graphqlClient, {
51
- appId: projectId,
52
- name: channelName,
53
- });
54
- branchId = newBranch.id;
55
- branchMessage = `We also went ahead and made a branch with the same name`;
56
- }
57
- else {
58
- throw error;
59
- }
60
- }
61
- const { updateChannel: { createUpdateChannelForApp: newChannel }, } = await (0, queries_2.createChannelOnAppAsync)(graphqlClient, {
33
+ await (0, queries_1.createAndLinkChannelAsync)(graphqlClient, {
62
34
  appId: projectId,
63
35
  channelName,
64
- branchId,
36
+ shouldPrintJson: jsonFlag,
65
37
  });
66
- if (!newChannel) {
67
- throw new Error(`Could not create channel with name ${channelName} on project with id ${projectId}`);
68
- }
69
- if (jsonFlag) {
70
- (0, json_1.printJsonOnlyOutput)(newChannel);
71
- }
72
- else {
73
- log_1.default.addNewLineIfNone();
74
- log_1.default.withTick(`Created a new channel on project ${chalk_1.default.bold(await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId))}`);
75
- log_1.default.log((0, formatFields_1.default)([
76
- { label: 'Name', value: newChannel.name },
77
- { label: 'ID', value: newChannel.id },
78
- ]));
79
- log_1.default.addNewLineIfNone();
80
- log_1.default.withTick(`${branchMessage} and have pointed the channel at it.`);
81
- log_1.default.log((0, formatFields_1.default)([
82
- { label: 'Name', value: newChannel.name },
83
- { label: 'ID', value: branchId },
84
- ]));
85
- log_1.default.addNewLineIfNone();
86
- log_1.default.log(chalk_1.default.bold('You can now update your app by publishing!'));
87
- }
38
+ log_1.default.addNewLineIfNone();
39
+ log_1.default.log(chalk_1.default.bold('You can now update your app by publishing!'));
88
40
  }
89
41
  }
90
42
  exports.default = ChannelCreate;
@@ -28,6 +28,7 @@ class MetadataLint extends EasCommand_1.default {
28
28
  easJsonAccessor: eas_json_1.EasJsonAccessor.fromProjectPath(projectDir),
29
29
  platforms: [eas_build_job_1.Platform.IOS],
30
30
  profileName: flags.profile,
31
+ projectDir,
31
32
  });
32
33
  if (submitProfiles.length !== 1) {
33
34
  throw new Error('Metadata only supports iOS and a single submit profile.');
@@ -28,6 +28,7 @@ class MetadataPull extends EasCommand_1.default {
28
28
  easJsonAccessor: eas_json_1.EasJsonAccessor.fromProjectPath(projectDir),
29
29
  platforms: [eas_build_job_1.Platform.IOS],
30
30
  profileName: flags.profile,
31
+ projectDir,
31
32
  });
32
33
  if (submitProfiles.length !== 1) {
33
34
  throw new Error('Metadata only supports iOS and a single submit profile.');
@@ -26,6 +26,7 @@ class MetadataPush extends EasCommand_1.default {
26
26
  easJsonAccessor: eas_json_1.EasJsonAccessor.fromProjectPath(projectDir),
27
27
  platforms: [eas_build_job_1.Platform.IOS],
28
28
  profileName: flags.profile,
29
+ projectDir,
29
30
  });
30
31
  if (submitProfiles.length !== 1) {
31
32
  throw new Error('Metadata only supports iOS and a single submit profile.');
@@ -30,6 +30,7 @@ class Submit extends EasCommand_1.default {
30
30
  easJsonAccessor: eas_json_1.EasJsonAccessor.fromProjectPath(projectDir),
31
31
  platforms,
32
32
  profileName: flagsWithPlatform.profile,
33
+ projectDir,
33
34
  });
34
35
  const submissions = [];
35
36
  for (const submissionProfile of submissionProfiles) {
@@ -150,6 +150,15 @@ class UpdatePublish extends EasCommand_1.default {
150
150
  for (const uploadedAssetPath of uploadResults.uniqueUploadedAssetPaths) {
151
151
  log_1.default.debug(chalk_1.default.dim(`- ${uploadedAssetPath}`));
152
152
  }
153
+ const platformString = Object.keys(assets)
154
+ .map(platform => {
155
+ const collectedAssetForPlatform = (0, nullthrows_1.default)(assets[platform]);
156
+ const totalAssetsForPlatform = collectedAssetForPlatform.assets.length + 1; // launch asset
157
+ const assetString = totalAssetsForPlatform === 1 ? 'asset' : 'assets';
158
+ return `${totalAssetsForPlatform} ${publish_1.platformDisplayNames[platform]} ${assetString}`;
159
+ })
160
+ .join(', ');
161
+ log_1.default.withInfo(`${platformString} (maximum: ${assetLimitPerUpdateGroup} total per update). ${(0, log_1.learnMore)('https://expo.fyi/eas-update-asset-limits', { learnMoreMessage: 'Learn more about asset limits.' })}`);
153
162
  }
154
163
  catch (e) {
155
164
  assetSpinner.fail('Failed to upload');
@@ -3,6 +3,8 @@ var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
5
  const core_1 = require("@oclif/core");
6
+ const queries_1 = require("../../branch/queries");
7
+ const queries_2 = require("../../channel/queries");
6
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
7
9
  const flags_1 = require("../../commandUtils/flags");
8
10
  const pagination_1 = require("../../commandUtils/pagination");
@@ -10,7 +12,7 @@ const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
10
12
  const log_1 = tslib_1.__importDefault(require("../../log"));
11
13
  const prompts_1 = require("../../prompts");
12
14
  const getBranchNameFromChannelNameAsync_1 = require("../../update/getBranchNameFromChannelNameAsync");
13
- const queries_1 = require("../../update/queries");
15
+ const queries_3 = require("../../update/queries");
14
16
  const republish_1 = require("../../update/republish");
15
17
  const utils_1 = require("../../update/utils");
16
18
  const code_signing_1 = require("../../utils/code-signing");
@@ -67,9 +69,6 @@ class UpdateRepublish extends EasCommand_1.default {
67
69
  if (nonInteractive && !groupId) {
68
70
  throw new Error('Only --group can be used in non-interactive mode');
69
71
  }
70
- if (!groupId && !(branchName || channelName)) {
71
- throw new Error(`--channel, --branch, or --group must be specified`);
72
- }
73
72
  const platform = rawFlags.platform === 'all' ? defaultRepublishPlatforms : [rawFlags.platform];
74
73
  return {
75
74
  branchName,
@@ -133,6 +132,9 @@ async function getOrAskUpdatesAsync(graphqlClient, projectId, flags) {
133
132
  branchName: update.branch.name,
134
133
  }));
135
134
  }
135
+ if (flags.nonInteractive) {
136
+ throw new Error('Must supply --group when in non-interactive mode');
137
+ }
136
138
  if (flags.branchName) {
137
139
  return await askUpdatesFromBranchNameAsync(graphqlClient, {
138
140
  ...flags,
@@ -147,14 +149,58 @@ async function getOrAskUpdatesAsync(graphqlClient, projectId, flags) {
147
149
  projectId,
148
150
  });
149
151
  }
150
- throw new Error('--channel, --branch, or --group is required');
152
+ const { choice } = await (0, prompts_1.promptAsync)({
153
+ type: 'select',
154
+ message: 'Find update by branch or channel?',
155
+ name: 'choice',
156
+ choices: [
157
+ { title: 'Branch', value: 'branch' },
158
+ { title: 'Channel', value: 'channel' },
159
+ ],
160
+ });
161
+ if (choice === 'channel') {
162
+ const { name } = await (0, queries_2.selectChannelOnAppAsync)(graphqlClient, {
163
+ projectId,
164
+ selectionPromptTitle: 'Select a channel to view',
165
+ paginatedQueryOptions: {
166
+ json: flags.json,
167
+ nonInteractive: flags.nonInteractive,
168
+ offset: 0,
169
+ },
170
+ });
171
+ return await askUpdatesFromChannelNameAsync(graphqlClient, {
172
+ ...flags,
173
+ channelName: name,
174
+ projectId,
175
+ });
176
+ }
177
+ else if (choice === 'branch') {
178
+ const { name } = await (0, queries_1.selectBranchOnAppAsync)(graphqlClient, {
179
+ projectId,
180
+ promptTitle: 'Select branch from which to choose update',
181
+ displayTextForListItem: updateBranch => ({
182
+ title: updateBranch.name,
183
+ }),
184
+ // discard limit and offset because this query is not their intended target
185
+ paginatedQueryOptions: {
186
+ json: flags.json,
187
+ nonInteractive: flags.nonInteractive,
188
+ offset: 0,
189
+ },
190
+ });
191
+ return await askUpdatesFromBranchNameAsync(graphqlClient, {
192
+ ...flags,
193
+ branchName: name,
194
+ projectId,
195
+ });
196
+ }
197
+ else {
198
+ throw new Error('Must choose update via channel or branch');
199
+ }
151
200
  }
152
201
  /** Ask the user which update needs to be republished by branch name, this requires interactive mode */
153
202
  async function askUpdatesFromBranchNameAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
154
- if (nonInteractive) {
155
- throw new Error('Must supply --group when in non-interactive mode');
156
- }
157
- const updateGroup = await (0, queries_1.selectUpdateGroupOnBranchAsync)(graphqlClient, {
203
+ const updateGroup = await (0, queries_3.selectUpdateGroupOnBranchAsync)(graphqlClient, {
158
204
  projectId,
159
205
  branchName,
160
206
  paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
@@ -168,9 +214,6 @@ async function askUpdatesFromBranchNameAsync(graphqlClient, { projectId, branchN
168
214
  }
169
215
  /** Ask the user which update needs to be republished by channel name, this requires interactive mode */
170
216
  async function askUpdatesFromChannelNameAsync(graphqlClient, { projectId, channelName, json, nonInteractive, }) {
171
- if (nonInteractive) {
172
- throw new Error('Must supply --group when in non-interactive mode');
173
- }
174
217
  const branchName = await (0, getBranchNameFromChannelNameAsync_1.getBranchNameFromChannelNameAsync)(graphqlClient, projectId, channelName);
175
218
  return await askUpdatesFromBranchNameAsync(graphqlClient, {
176
219
  projectId,
@@ -229,7 +229,11 @@ UpdateRollBackToEmbedded.flags = {
229
229
  }),
230
230
  platform: core_1.Flags.enum({
231
231
  char: 'p',
232
- options: [...publish_1.defaultPublishPlatforms, 'all'],
232
+ options: [
233
+ // TODO: Add web when it's fully supported
234
+ ...publish_1.defaultPublishPlatforms,
235
+ 'all',
236
+ ],
233
237
  default: 'all',
234
238
  required: false,
235
239
  }),
@@ -0,0 +1,9 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class UpdateRollback extends EasCommand {
3
+ static description: string;
4
+ static hidden: boolean;
5
+ static flags: {
6
+ 'private-key-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
7
+ };
8
+ runAsync(): Promise<void>;
9
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
5
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
6
+ const prompts_1 = require("../../prompts");
7
+ const republish_1 = tslib_1.__importDefault(require("./republish"));
8
+ const roll_back_to_embedded_1 = tslib_1.__importDefault(require("./roll-back-to-embedded"));
9
+ class UpdateRollback extends EasCommand_1.default {
10
+ async runAsync() {
11
+ const { flags } = await this.parse(UpdateRollback);
12
+ const { choice } = await (0, prompts_1.promptAsync)({
13
+ type: 'select',
14
+ message: 'Which type of update would you like to roll back to?',
15
+ name: 'choice',
16
+ choices: [
17
+ { title: 'Published Update', value: 'published' },
18
+ { title: 'Embedded Update', value: 'embedded' },
19
+ ],
20
+ });
21
+ const privateKeyPathArg = flags['private-key-path']
22
+ ? ['--private-key-path', flags['private-key-path']]
23
+ : [];
24
+ if (choice === 'published') {
25
+ await republish_1.default.run(privateKeyPathArg);
26
+ }
27
+ else {
28
+ await roll_back_to_embedded_1.default.run(privateKeyPathArg);
29
+ }
30
+ }
31
+ }
32
+ exports.default = UpdateRollback;
33
+ UpdateRollback.description = 'roll back to an embedded update or an existing update';
34
+ UpdateRollback.hidden = true;
35
+ UpdateRollback.flags = {
36
+ 'private-key-path': core_1.Flags.string({
37
+ description: `File containing the PEM-encoded private key corresponding to the certificate in expo-updates' configuration. Defaults to a file named "private-key.pem" in the certificate's directory.`,
38
+ required: false,
39
+ }),
40
+ };
@@ -108,7 +108,16 @@ class SetUpAdhocProvisioningProfile {
108
108
  developerPortalIdentifier: provisioningProfileStoreInfo.provisioningProfileId,
109
109
  });
110
110
  }
111
- // 6. Create (or update) app build credentials
111
+ // 6. Compare selected devices with the ones actually provisioned
112
+ const diffList = (0, differenceBy_1.default)(chosenDevices, appleProvisioningProfile.appleDevices, 'identifier');
113
+ if (diffList && diffList.length > 0) {
114
+ log_1.default.warn(`Failed to provision ${diffList.length} of the selected devices:`);
115
+ for (const missingDevice of diffList) {
116
+ log_1.default.warn(`- ${(0, DeviceUtils_1.formatDeviceLabel)(missingDevice)}`);
117
+ }
118
+ log_1.default.log('Most commonly devices fail to to be provisioned while they are still being processed by Apple, which can take up to 24-72 hours. Check your Apple Developer Portal page at https://developer.apple.com/account/resources/devices/list, the devices in "Processing" status cannot be provisioned yet');
119
+ }
120
+ // 7. Create (or update) app build credentials
112
121
  (0, assert_1.default)(appleProvisioningProfile);
113
122
  return await (0, BuildCredentialsUtils_1.assignBuildCredentialsAsync)(ctx, app, generated_1.IosDistributionType.AdHoc, distCert, appleProvisioningProfile, appleTeam);
114
123
  }
package/build/log.d.ts CHANGED
@@ -11,6 +11,7 @@ export default class Log {
11
11
  static fail(message: string): void;
12
12
  static succeed(message: string): void;
13
13
  static withTick(...args: any[]): void;
14
+ static withInfo(...args: any[]): void;
14
15
  private static consoleLog;
15
16
  private static withTextColor;
16
17
  private static isLastLineNewLine;
package/build/log.js CHANGED
@@ -45,6 +45,9 @@ class Log {
45
45
  static withTick(...args) {
46
46
  Log.consoleLog(chalk_1.default.green(figures_1.default.tick), ...args);
47
47
  }
48
+ static withInfo(...args) {
49
+ Log.consoleLog(chalk_1.default.green(figures_1.default.info), ...args);
50
+ }
48
51
  static consoleLog(...args) {
49
52
  Log.updateIsLastLineNewLine(args);
50
53
  // eslint-disable-next-line no-console
@@ -145,4 +145,5 @@ export declare function getRuntimeToPlatformMappingFromRuntimeVersions(runtimeVe
145
145
  runtimeVersion: string;
146
146
  platforms: string[];
147
147
  }[];
148
+ export declare const platformDisplayNames: Record<Platform, string>;
148
149
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRuntimeToPlatformMappingFromRuntimeVersions = exports.getRuntimeVersionObjectAsync = exports.getRequestedPlatform = exports.defaultPublishPlatforms = exports.getUpdateMessageForCommandAsync = exports.getBranchNameForCommandAsync = exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.getOriginalPathFromAssetMap = exports.getAssetHashFromPath = exports.loadAssetMapAsync = exports.filterExportedPlatformsByFlag = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
3
+ exports.platformDisplayNames = exports.getRuntimeToPlatformMappingFromRuntimeVersions = exports.getRuntimeVersionObjectAsync = exports.getRequestedPlatform = exports.defaultPublishPlatforms = exports.getUpdateMessageForCommandAsync = exports.getBranchNameForCommandAsync = exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.getOriginalPathFromAssetMap = exports.getAssetHashFromPath = exports.loadAssetMapAsync = exports.filterExportedPlatformsByFlag = 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 config_plugins_1 = require("@expo/config-plugins");
6
6
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -123,6 +123,7 @@ async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clea
123
123
  if (!packageJSON) {
124
124
  throw new Error('Could not locate package.json');
125
125
  }
126
+ const platformArgs = platformFlag === 'all' ? ['--platform', 'ios', '--platform', 'android'] : [platformFlag];
126
127
  if ((0, expoCli_1.shouldUseVersionedExpoCLI)(projectDir, exp)) {
127
128
  await (0, expoCli_1.expoCommandAsync)(projectDir, [
128
129
  'export',
@@ -130,8 +131,7 @@ async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clea
130
131
  inputDir,
131
132
  '--dump-sourcemap',
132
133
  '--dump-assetmap',
133
- '--platform',
134
- platformFlag,
134
+ ...platformArgs,
135
135
  ...(clearCache ? ['--clear'] : []),
136
136
  ]);
137
137
  }
@@ -145,8 +145,7 @@ async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clea
145
145
  '--non-interactive',
146
146
  '--dump-sourcemap',
147
147
  '--dump-assetmap',
148
- '--platform',
149
- platformFlag,
148
+ ...platformArgs,
150
149
  ...(clearCache ? ['--clear'] : []),
151
150
  ]);
152
151
  }
@@ -480,3 +479,8 @@ function getRuntimeToPlatformMappingFromRuntimeVersions(runtimeVersions) {
480
479
  return runtimeToPlatformMapping;
481
480
  }
482
481
  exports.getRuntimeToPlatformMappingFromRuntimeVersions = getRuntimeToPlatformMappingFromRuntimeVersions;
482
+ exports.platformDisplayNames = {
483
+ android: 'Android',
484
+ ios: 'iOS',
485
+ web: 'Web',
486
+ };