eas-cli 1.0.0 → 1.2.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 (84) hide show
  1. package/README.md +72 -47
  2. package/build/analytics/events.d.ts +4 -1
  3. package/build/analytics/events.js +3 -0
  4. package/build/build/android/build.js +1 -1
  5. package/build/build/build.js +4 -4
  6. package/build/build/createContext.js +1 -0
  7. package/build/build/ios/graphql.js +0 -1
  8. package/build/build/utils/printBuildInfo.js +2 -2
  9. package/build/build/utils/repository.js +4 -4
  10. package/build/commandUtils/EasCommand.d.ts +2 -0
  11. package/build/commandUtils/EasCommand.js +44 -3
  12. package/build/commands/branch/create.js +1 -1
  13. package/build/commands/branch/delete.js +1 -1
  14. package/build/commands/branch/rename.js +2 -2
  15. package/build/commands/build/index.d.ts +2 -1
  16. package/build/commands/build/index.js +36 -18
  17. package/build/commands/channel/create.js +1 -1
  18. package/build/commands/channel/delete.js +1 -1
  19. package/build/commands/channel/edit.js +3 -3
  20. package/build/commands/channel/rollout.js +3 -3
  21. package/build/commands/channel/view.js +1 -1
  22. package/build/commands/credentials.d.ts +3 -0
  23. package/build/commands/credentials.js +6 -1
  24. package/build/commands/project/init.js +3 -1
  25. package/build/commands/secret/list.js +1 -1
  26. package/build/commands/submit.d.ts +2 -1
  27. package/build/commands/submit.js +28 -14
  28. package/build/commands/update/index.js +7 -4
  29. package/build/commands/update/list.js +1 -1
  30. package/build/credentials/android/actions/RemoveKeystore.js +1 -1
  31. package/build/credentials/android/api/GraphqlClient.js +1 -1
  32. package/build/credentials/context.d.ts +3 -0
  33. package/build/credentials/context.js +1 -0
  34. package/build/credentials/errors.js +1 -1
  35. package/build/credentials/ios/IosCredentialsProvider.d.ts +1 -0
  36. package/build/credentials/ios/IosCredentialsProvider.js +33 -5
  37. package/build/credentials/ios/actions/DistributionCertificateUtils.js +2 -2
  38. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +1 -1
  39. package/build/credentials/ios/actions/SetUpInternalProvisioningProfile.js +2 -2
  40. package/build/credentials/ios/actions/SetUpProvisioningProfile.js +1 -1
  41. package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +1 -1
  42. package/build/credentials/ios/api/GraphqlClient.js +1 -1
  43. package/build/credentials/ios/appstore/ascApiKey.d.ts +11 -0
  44. package/build/credentials/ios/appstore/ascApiKey.js +53 -3
  45. package/build/credentials/ios/appstore/bundleIdCapabilities.js +176 -15
  46. package/build/credentials/ios/appstore/contractMessages.js +1 -1
  47. package/build/credentials/ios/appstore/ensureAppExists.js +3 -3
  48. package/build/credentials/ios/appstore/pushKey.js +2 -2
  49. package/build/credentials/manager/ManageAndroid.js +2 -8
  50. package/build/credentials/manager/ManageIos.js +2 -4
  51. package/build/credentials/manager/SelectIosDistributionTypeGraphqlFromBuildProfile.js +1 -1
  52. package/build/credentials/manager/SelectPlatform.d.ts +2 -0
  53. package/build/credentials/manager/SelectPlatform.js +7 -12
  54. package/build/credentials/utils/promptForCredentials.js +1 -1
  55. package/build/devices/manager.js +1 -1
  56. package/build/graphql/client.js +1 -1
  57. package/build/graphql/generated.d.ts +191 -39
  58. package/build/graphql/generated.js +39 -1
  59. package/build/{credentials/ios/api/graphql → graphql}/queries/AppQuery.d.ts +1 -1
  60. package/build/{credentials/ios/api/graphql → graphql}/queries/AppQuery.js +2 -2
  61. package/build/graphql/queries/EnvironmentSecretsQuery.d.ts +1 -1
  62. package/build/graphql/queries/EnvironmentSecretsQuery.js +2 -2
  63. package/build/graphql/queries/StatuspageServiceQuery.d.ts +4 -0
  64. package/build/graphql/queries/StatuspageServiceQuery.js +28 -0
  65. package/build/graphql/types/StatuspageService.d.ts +1 -0
  66. package/build/graphql/types/StatuspageService.js +19 -0
  67. package/build/metadata/errors.js +2 -2
  68. package/build/project/ensureProjectExists.d.ts +0 -7
  69. package/build/project/ensureProjectExists.js +4 -14
  70. package/build/project/metroConfig.js +1 -1
  71. package/build/project/projectUtils.d.ts +16 -3
  72. package/build/project/projectUtils.js +47 -50
  73. package/build/submit/android/AndroidSubmitter.js +1 -1
  74. package/build/submit/submit.js +2 -2
  75. package/build/submit/utils/errors.js +11 -9
  76. package/build/update/utils.js +1 -1
  77. package/build/utils/statuspageService.d.ts +2 -0
  78. package/build/utils/statuspageService.js +41 -0
  79. package/build/vcs/local.d.ts +1 -0
  80. package/build/vcs/local.js +11 -2
  81. package/oclif.manifest.json +1 -1
  82. package/package.json +4 -7
  83. package/build/graphql/queries/ProjectQuery.d.ts +0 -6
  84. package/build/graphql/queries/ProjectQuery.js +0 -24
@@ -54,7 +54,7 @@ class BranchCreate extends EasCommand_1.default {
54
54
  ({ name } = await (0, prompts_1.promptAsync)({
55
55
  type: 'text',
56
56
  name: 'name',
57
- message: 'Please name the branch:',
57
+ message: 'Provide a branch name:',
58
58
  initial: (await (0, vcs_1.getVcsClient)().getBranchNameAsync()) ||
59
59
  `branch-${Math.random().toString(36).substr(2, 4)}`,
60
60
  validate: value => (value ? true : validationMessage),
@@ -67,7 +67,7 @@ class BranchDelete extends EasCommand_1.default {
67
67
  ({ name } = await (0, prompts_1.promptAsync)({
68
68
  type: 'text',
69
69
  name: 'name',
70
- message: 'Please enter the name of the branch to delete:',
70
+ message: 'Provide the name of the branch to delete:',
71
71
  validate: value => (value ? true : validationMessage),
72
72
  }));
73
73
  }
@@ -50,7 +50,7 @@ class BranchRename extends EasCommand_1.default {
50
50
  ({ currentName } = await (0, prompts_1.promptAsync)({
51
51
  type: 'text',
52
52
  name: 'currentName',
53
- message: 'Please enter the current name of the branch to rename:',
53
+ message: "Provide the name of the branch you'd like to rename:",
54
54
  validate: value => (value ? true : validationMessage),
55
55
  }));
56
56
  }
@@ -62,7 +62,7 @@ class BranchRename extends EasCommand_1.default {
62
62
  ({ newName } = await (0, prompts_1.promptAsync)({
63
63
  type: 'text',
64
64
  name: 'newName',
65
- message: `Please rename ${currentName}`,
65
+ message: `Rename ${currentName}`,
66
66
  validate: value => (value ? true : validationMessage),
67
67
  }));
68
68
  }
@@ -19,5 +19,6 @@ export default class Build extends EasCommand {
19
19
  message: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
20
20
  };
21
21
  runAsync(): Promise<void>;
22
- private sanitizeFlagsAsync;
22
+ private sanitizeFlags;
23
+ private ensurePlatformSelectedAsync;
23
24
  }
@@ -6,21 +6,29 @@ const path_1 = tslib_1.__importDefault(require("path"));
6
6
  const runBuildAndSubmit_1 = require("../../build/runBuildAndSubmit");
7
7
  const types_1 = require("../../build/types");
8
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const generated_1 = require("../../graphql/generated");
9
10
  const log_1 = tslib_1.__importDefault(require("../../log"));
10
11
  const platform_1 = require("../../platform");
11
12
  const projectUtils_1 = require("../../project/projectUtils");
12
13
  const json_1 = require("../../utils/json");
14
+ const statuspageService_1 = require("../../utils/statuspageService");
13
15
  class Build extends EasCommand_1.default {
14
16
  async runAsync() {
15
17
  const { flags: rawFlags } = await this.parse(Build);
16
18
  if (rawFlags.json) {
17
19
  (0, json_1.enableJsonOutput)();
18
20
  }
19
- const flags = await this.sanitizeFlagsAsync(rawFlags);
21
+ const flags = this.sanitizeFlags(rawFlags);
20
22
  const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
21
- await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)(projectDir, flags);
23
+ if (!flags.localBuildOptions.enable) {
24
+ await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)(flags.autoSubmit
25
+ ? [generated_1.StatuspageServiceName.EasBuild, generated_1.StatuspageServiceName.EasSubmit]
26
+ : [generated_1.StatuspageServiceName.EasBuild]);
27
+ }
28
+ const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
29
+ await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)(projectDir, flagsWithPlatform);
22
30
  }
23
- async sanitizeFlagsAsync(flags) {
31
+ sanitizeFlags(flags) {
24
32
  var _a, _b;
25
33
  const nonInteractive = flags['non-interactive'];
26
34
  if (!flags.local && flags.output) {
@@ -32,21 +40,10 @@ class Build extends EasCommand_1.default {
32
40
  if (flags.json && !nonInteractive) {
33
41
  core_1.Errors.error('--json is allowed only when building in non-interactive mode', { exit: 1 });
34
42
  }
35
- const requestedPlatform = await (0, platform_1.selectRequestedPlatformAsync)(flags.platform);
36
- if (flags.local) {
37
- if (flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined) {
38
- // TODO: implement this
39
- core_1.Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
40
- }
41
- if (requestedPlatform === platform_1.RequestedPlatform.All) {
42
- core_1.Errors.error('Builds for multiple platforms are not supported with flag --local', {
43
- exit: 1,
44
- });
45
- }
46
- else if (process.platform !== 'darwin' && requestedPlatform === platform_1.RequestedPlatform.Ios) {
47
- core_1.Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
48
- }
49
- }
43
+ const requestedPlatform = flags.platform &&
44
+ Object.values(platform_1.RequestedPlatform).includes(flags.platform.toLowerCase())
45
+ ? flags.platform.toLowerCase()
46
+ : undefined;
50
47
  if (flags['skip-credentials-check']) {
51
48
  log_1.default.warnDeprecatedFlag('skip-credentials-check', 'Build credentials validation is always skipped with the --non-interactive flag. You can also skip interactively.');
52
49
  log_1.default.newLine();
@@ -82,6 +79,27 @@ class Build extends EasCommand_1.default {
82
79
  message,
83
80
  };
84
81
  }
82
+ async ensurePlatformSelectedAsync(flags) {
83
+ const requestedPlatform = await (0, platform_1.selectRequestedPlatformAsync)(flags.requestedPlatform);
84
+ if (flags.localBuildOptions.enable) {
85
+ if (flags.autoSubmit) {
86
+ // TODO: implement this
87
+ core_1.Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
88
+ }
89
+ if (requestedPlatform === platform_1.RequestedPlatform.All) {
90
+ core_1.Errors.error('Builds for multiple platforms are not supported with flag --local', {
91
+ exit: 1,
92
+ });
93
+ }
94
+ else if (process.platform !== 'darwin' && requestedPlatform === platform_1.RequestedPlatform.Ios) {
95
+ core_1.Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
96
+ }
97
+ }
98
+ return {
99
+ ...flags,
100
+ requestedPlatform,
101
+ };
102
+ }
85
103
  }
86
104
  exports.default = Build;
87
105
  Build.description = 'start a build';
@@ -57,7 +57,7 @@ class ChannelCreate extends EasCommand_1.default {
57
57
  ({ name: channelName } = await (0, prompts_1.promptAsync)({
58
58
  type: 'text',
59
59
  name: 'name',
60
- message: 'Please name the channel:',
60
+ message: 'Provide a channel name:',
61
61
  validate: value => (value ? true : validationMessage),
62
62
  }));
63
63
  }
@@ -35,7 +35,7 @@ class ChannelDelete extends EasCommand_1.default {
35
35
  name = (await (0, prompts_1.promptAsync)({
36
36
  type: 'text',
37
37
  name: 'name',
38
- message: 'Please enter the name of the channel to delete:',
38
+ message: 'Provide the name of the channel to delete:',
39
39
  validate: (value) => (value ? true : 'Channel name may not be empty.'),
40
40
  })).name;
41
41
  }
@@ -74,7 +74,7 @@ class ChannelEdit extends EasCommand_1.default {
74
74
  const channelName = (_a = args.name) !== null && _a !== void 0 ? _a : (await promptForChannelAsync());
75
75
  const existingChannel = await getChannelByNameForAppAsync({ appId: projectId, channelName });
76
76
  if (existingChannel.updateBranches.length > 1) {
77
- throw new Error('There is a rollout in progress. Please manage it with "channel:rollout" instead.');
77
+ throw new Error('There is a rollout in progress. Manage it with "channel:rollout" instead.');
78
78
  }
79
79
  const branchName = (_b = flags.branch) !== null && _b !== void 0 ? _b : (await promptForBranchAsync());
80
80
  const branch = await BranchQuery_1.BranchQuery.getBranchByNameAsync({
@@ -82,7 +82,7 @@ class ChannelEdit extends EasCommand_1.default {
82
82
  name: branchName,
83
83
  });
84
84
  if (!branch) {
85
- throw new Error(`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
85
+ throw new Error(`Could not find a branch named "${branchName}". Check what branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
86
86
  }
87
87
  const channel = await updateChannelBranchMappingAsync({
88
88
  channelId: existingChannel.id,
@@ -125,7 +125,7 @@ async function promptForChannelAsync() {
125
125
  const { name } = await (0, prompts_1.promptAsync)({
126
126
  type: 'text',
127
127
  name: 'name',
128
- message: 'Please enter the name of the channel to edit:',
128
+ message: 'Provide the name of the channel to edit:',
129
129
  validate: value => (value ? true : 'The channel name may not be empty.'),
130
130
  });
131
131
  return name;
@@ -48,7 +48,7 @@ async function startRolloutAsync({ channelName, branchName, percent, jsonFlag, p
48
48
  name: branchName,
49
49
  });
50
50
  if (!branch) {
51
- throw new Error(`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
51
+ throw new Error(`Could not find a branch named "${branchName}". Check which branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
52
52
  }
53
53
  const oldBranchId = currentBranchMapping.data[0].branchId;
54
54
  if (branch.id === oldBranchId) {
@@ -114,7 +114,7 @@ async function endRolloutAsync({ channelName, branchName, jsonFlag, projectId, c
114
114
  name: branchName,
115
115
  });
116
116
  if (!branch) {
117
- throw new Error(`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
117
+ throw new Error(`Could not find a branch named "${branchName}". Check which branches exist on this project with ${chalk_1.default.bold('eas branch:list')}.`);
118
118
  }
119
119
  switch (branch.id) {
120
120
  case newBranch.id:
@@ -176,7 +176,7 @@ class ChannelRollout extends EasCommand_1.default {
176
176
  channelName: channelName,
177
177
  });
178
178
  if (!channel) {
179
- throw new Error(`Could not find a channel named "${channelName}". Please check what channels exist on this project with ${chalk_1.default.bold('eas channel:list')}.`);
179
+ throw new Error(`Could not find a channel named "${channelName}". Check which channels exist on this project with ${chalk_1.default.bold('eas channel:list')}.`);
180
180
  }
181
181
  const { branchMapping: currentBranchMapping, isRollout } = (0, view_1.getBranchMapping)(channel.branchMapping);
182
182
  if (currentBranchMapping.data.length === 0) {
@@ -119,7 +119,7 @@ class ChannelView extends EasCommand_1.default {
119
119
  ({ name: channelName } = await (0, prompts_1.promptAsync)({
120
120
  type: 'text',
121
121
  name: 'name',
122
- message: 'Please name the channel:',
122
+ message: 'Provide a channel name:',
123
123
  validate: value => (value ? true : validationMessage),
124
124
  }));
125
125
  }
@@ -1,5 +1,8 @@
1
1
  import EasCommand from '../commandUtils/EasCommand';
2
2
  export default class Credentials extends EasCommand {
3
3
  static description: string;
4
+ static flags: {
5
+ platform: import("@oclif/core/lib/interfaces").OptionFlag<string>;
6
+ };
4
7
  runAsync(): Promise<void>;
5
8
  }
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
4
5
  const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
5
6
  const SelectPlatform_1 = require("../credentials/manager/SelectPlatform");
6
7
  class Credentials extends EasCommand_1.default {
7
8
  async runAsync() {
8
- await new SelectPlatform_1.SelectPlatform().runAsync();
9
+ const { flags } = await this.parse(Credentials);
10
+ await new SelectPlatform_1.SelectPlatform(flags.platform).runAsync();
9
11
  }
10
12
  }
11
13
  exports.default = Credentials;
12
14
  Credentials.description = 'manage credentials';
15
+ Credentials.flags = {
16
+ platform: core_1.Flags.enum({ char: 'p', options: ['android', 'ios'] }),
17
+ };
@@ -15,7 +15,9 @@ class ProjectInit extends EasCommand_1.default {
15
15
  log_1.default.error(`app.json is already linked to project with ID: ${chalk_1.default.bold((_d = (_c = exp.extra) === null || _c === void 0 ? void 0 : _c.eas) === null || _d === void 0 ? void 0 : _d.projectId)}`);
16
16
  return;
17
17
  }
18
- await (0, projectUtils_1.setProjectIdAsync)(projectDir);
18
+ const projectId = await (0, projectUtils_1.fetchProjectIdFromServerAsync)(exp);
19
+ await (0, projectUtils_1.saveProjectIdToAppConfigAsync)(projectDir, projectId);
20
+ log_1.default.withTick(`Linked app.json to project with ID ${chalk_1.default.bold(projectId)}`);
19
21
  }
20
22
  }
21
23
  exports.default = ProjectInit;
@@ -16,7 +16,7 @@ class EnvironmentSecretList extends EasCommand_1.default {
16
16
  const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
17
17
  const projectAccountName = await (0, projectUtils_1.getProjectAccountNameAsync)(exp);
18
18
  if (!projectDir) {
19
- throw new Error("Please run this command inside your project's directory");
19
+ throw new Error("Run this command inside your project's directory");
20
20
  }
21
21
  const secrets = await EnvironmentSecretsQuery_1.EnvironmentSecretsQuery.allAsync(projectAccountName, projectId);
22
22
  const table = new cli_table3_1.default({
@@ -14,5 +14,6 @@ export default class Submit extends EasCommand {
14
14
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
15
  };
16
16
  runAsync(): Promise<void>;
17
- private sanitizeFlagsAsync;
17
+ private sanitizeFlags;
18
+ private ensurePlatformSelectedAsync;
18
19
  }
@@ -5,6 +5,7 @@ const eas_json_1 = require("@expo/eas-json");
5
5
  const core_1 = require("@oclif/core");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
8
+ const generated_1 = require("../graphql/generated");
8
9
  const AppPlatform_1 = require("../graphql/types/AppPlatform");
9
10
  const log_1 = tslib_1.__importDefault(require("../log"));
10
11
  const platform_1 = require("../platform");
@@ -14,19 +15,22 @@ const context_1 = require("../submit/context");
14
15
  const submit_1 = require("../submit/submit");
15
16
  const urls_1 = require("../submit/utils/urls");
16
17
  const profiles_1 = require("../utils/profiles");
18
+ const statuspageService_1 = require("../utils/statuspageService");
17
19
  class Submit extends EasCommand_1.default {
18
20
  async runAsync() {
19
21
  const { flags: rawFlags } = await this.parse(Submit);
20
- const flags = await this.sanitizeFlagsAsync(rawFlags);
22
+ const flags = this.sanitizeFlags(rawFlags);
21
23
  const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
22
24
  const exp = (0, expoConfig_1.getExpoConfig)(projectDir);
23
25
  const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
24
- const platforms = (0, platform_1.toPlatforms)(flags.requestedPlatform);
26
+ await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)([generated_1.StatuspageServiceName.EasSubmit]);
27
+ const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
28
+ const platforms = (0, platform_1.toPlatforms)(flagsWithPlatform.requestedPlatform);
25
29
  const submissionProfiles = await (0, profiles_1.getProfilesAsync)({
26
30
  type: 'submit',
27
31
  easJsonReader: new eas_json_1.EasJsonReader(projectDir),
28
32
  platforms,
29
- profileName: flags.profile,
33
+ profileName: flagsWithPlatform.profile,
30
34
  });
31
35
  const submissions = [];
32
36
  for (const submissionProfile of submissionProfiles) {
@@ -35,8 +39,8 @@ class Submit extends EasCommand_1.default {
35
39
  projectDir,
36
40
  projectId,
37
41
  profile: submissionProfile.profile,
38
- archiveFlags: flags.archiveFlags,
39
- nonInteractive: flags.nonInteractive,
42
+ archiveFlags: flagsWithPlatform.archiveFlags,
43
+ nonInteractive: flagsWithPlatform.nonInteractive,
40
44
  });
41
45
  if (submissionProfiles.length > 1) {
42
46
  log_1.default.newLine();
@@ -48,24 +52,22 @@ class Submit extends EasCommand_1.default {
48
52
  }
49
53
  log_1.default.newLine();
50
54
  (0, urls_1.printSubmissionDetailsUrls)(submissions);
51
- if (flags.wait) {
55
+ if (flagsWithPlatform.wait) {
52
56
  const completedSubmissions = await (0, submit_1.waitToCompleteAsync)(submissions, {
53
- verbose: flags.verbose,
57
+ verbose: flagsWithPlatform.verbose,
54
58
  });
55
59
  (0, submit_1.exitWithNonZeroCodeIfSomeSubmissionsDidntFinish)(completedSubmissions);
56
60
  }
57
61
  }
58
- async sanitizeFlagsAsync(flags) {
62
+ sanitizeFlags(flags) {
59
63
  const { platform, verbose, wait, profile, 'non-interactive': nonInteractive, ...archiveFlags } = flags;
60
64
  if (!flags.platform && nonInteractive) {
61
65
  core_1.Errors.error('--platform is required when building in non-interactive mode', { exit: 1 });
62
66
  }
63
- const requestedPlatform = await (0, platform_1.selectRequestedPlatformAsync)(flags.platform);
64
- if (requestedPlatform === platform_1.RequestedPlatform.All) {
65
- if (archiveFlags.id || archiveFlags.path || archiveFlags.url) {
66
- core_1.Errors.error('--id, --path, and --url params are only supported when performing a single-platform submit', { exit: 1 });
67
- }
68
- }
67
+ const requestedPlatform = flags.platform &&
68
+ Object.values(platform_1.RequestedPlatform).includes(flags.platform.toLowerCase())
69
+ ? flags.platform.toLowerCase()
70
+ : undefined;
69
71
  return {
70
72
  archiveFlags,
71
73
  requestedPlatform,
@@ -75,6 +77,18 @@ class Submit extends EasCommand_1.default {
75
77
  nonInteractive,
76
78
  };
77
79
  }
80
+ async ensurePlatformSelectedAsync(flags) {
81
+ const requestedPlatform = await (0, platform_1.selectRequestedPlatformAsync)(flags.requestedPlatform);
82
+ if (requestedPlatform === platform_1.RequestedPlatform.All) {
83
+ if (flags.archiveFlags.id || flags.archiveFlags.path || flags.archiveFlags.url) {
84
+ core_1.Errors.error('--id, --path, and --url params are only supported when performing a single-platform submit', { exit: 1 });
85
+ }
86
+ }
87
+ return {
88
+ ...flags,
89
+ requestedPlatform,
90
+ };
91
+ }
78
92
  }
79
93
  exports.default = Submit;
80
94
  Submit.description = 'submit app binary to App Store and/or Play Store';
@@ -16,6 +16,7 @@ const url_1 = require("../../build/utils/url");
16
16
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
17
17
  const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
18
18
  const client_1 = require("../../graphql/client");
19
+ const generated_1 = require("../../graphql/generated");
19
20
  const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
20
21
  const BranchQuery_1 = require("../../graphql/queries/BranchQuery");
21
22
  const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
@@ -32,6 +33,7 @@ const code_signing_1 = require("../../utils/code-signing");
32
33
  const uniqBy_1 = tslib_1.__importDefault(require("../../utils/expodash/uniqBy"));
33
34
  const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
34
35
  const json_1 = require("../../utils/json");
36
+ const statuspageService_1 = require("../../utils/statuspageService");
35
37
  const vcs_1 = require("../../vcs");
36
38
  const create_1 = require("../branch/create");
37
39
  const create_2 = require("../channel/create");
@@ -109,6 +111,7 @@ class UpdatePublish extends EasCommand_1.default {
109
111
  const expPrivate = (0, expoConfig_1.getExpoConfig)(projectDir, {
110
112
  isPublicConfig: false,
111
113
  });
114
+ await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)([generated_1.StatuspageServiceName.EasUpdate]);
112
115
  const codeSigningInfo = await (0, code_signing_1.getCodeSigningInfoAsync)(expPrivate, privateKeyPath);
113
116
  const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, exp.sdkVersion);
114
117
  if (!hasExpoUpdates && nonInteractive) {
@@ -153,7 +156,7 @@ class UpdatePublish extends EasCommand_1.default {
153
156
  ({ name: branchName } = await (0, prompts_1.promptAsync)({
154
157
  type: 'text',
155
158
  name: 'name',
156
- message: 'No branches found. Creating a new one. Please name the new branch:',
159
+ message: 'No branches found. Provide a branch name:',
157
160
  initial: (await (0, vcs_1.getVcsClient)().getBranchNameAsync()) ||
158
161
  `branch-${Math.random().toString(36).substr(2, 4)}`,
159
162
  validate: value => (value ? true : validationMessage),
@@ -229,7 +232,7 @@ class UpdatePublish extends EasCommand_1.default {
229
232
  ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
230
233
  type: 'text',
231
234
  name: 'publishMessage',
232
- message: `Please enter an update message.`,
235
+ message: `Provide an update message.`,
233
236
  initial: `Republish "${oldMessage}" - group: ${group}`,
234
237
  validate: (value) => (value ? true : validationMessage),
235
238
  }));
@@ -250,7 +253,7 @@ class UpdatePublish extends EasCommand_1.default {
250
253
  ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
251
254
  type: 'text',
252
255
  name: 'publishMessage',
253
- message: `Please enter an update message.`,
256
+ message: `Provide an update message.`,
254
257
  initial: (_c = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _c === void 0 ? void 0 : _c.trim(),
255
258
  validate: (value) => (value ? true : validationMessage),
256
259
  }));
@@ -529,7 +532,7 @@ async function checkEASUpdateURLIsSetAsync(exp) {
529
532
  const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
530
533
  const expectedURL = (0, api_1.getEASUpdateURL)(projectId);
531
534
  if (configuredURL !== expectedURL) {
532
- throw new Error(`The update URL is incorrectly configured for EAS Update. Please set updates.url to ${expectedURL} in your app.json.`);
535
+ 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')}.`);
533
536
  }
534
537
  }
535
538
  const truncatePublishUpdateMessage = (originalMessage) => {
@@ -47,7 +47,7 @@ class BranchView extends EasCommand_1.default {
47
47
  ({ name: branchInteractive } = await (0, prompts_1.promptAsync)({
48
48
  type: 'text',
49
49
  name: 'name',
50
- message: 'Please enter the name of the branch whose updates you wish to view:',
50
+ message: 'Provide the name of the branch whose updates you wish to view:',
51
51
  initial: (_a = (await (0, vcs_1.getVcsClient)().getBranchNameAsync())) !== null && _a !== void 0 ? _a : undefined,
52
52
  validate: (value) => (value ? true : validationMessage),
53
53
  }));
@@ -35,7 +35,7 @@ class RemoveKeystore {
35
35
  log_1.default.newLine();
36
36
  log_1.default.warn(`Clearing your Android build credentials from our build servers is a ${chalk_1.default.bold('PERMANENT and IRREVERSIBLE action.')}`);
37
37
  log_1.default.warn(chalk_1.default.bold('Android Keystore must be identical to the one previously used to submit your app to the Google Play Store.'));
38
- log_1.default.warn('Please read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.');
38
+ log_1.default.warn('Read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.');
39
39
  log_1.default.newLine();
40
40
  log_1.default.warn(chalk_1.default.bold('Your Keystore will be backed up to your current directory if you continue.'));
41
41
  log_1.default.newLine();
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.formatProjectFullName = exports.getGoogleServiceAccountKeysForAccountAsync = exports.deleteGoogleServiceAccountKeyAsync = exports.createGoogleServiceAccountKeyAsync = exports.deleteFcmAsync = exports.createFcmAsync = exports.deleteKeystoreAsync = exports.createKeystoreAsync = exports.createOrUpdateDefaultIosAppBuildCredentialsAsync = exports.createOrUpdateAndroidAppBuildCredentialsByNameAsync = exports.getAndroidAppBuildCredentialsByNameAsync = exports.getDefaultAndroidAppBuildCredentialsAsync = exports.createAndroidAppBuildCredentialsAsync = exports.updateAndroidAppBuildCredentialsAsync = exports.updateAndroidAppCredentialsAsync = exports.createOrGetExistingAndroidAppCredentialsWithBuildCredentialsAsync = exports.getLegacyAndroidAppBuildCredentialsAsync = exports.getLegacyAndroidAppCredentialsWithCommonFieldsAsync = exports.getAndroidAppBuildCredentialsListAsync = exports.getAndroidAppCredentialsWithCommonFieldsAsync = void 0;
4
- const AppQuery_1 = require("../../ios/api/graphql/queries/AppQuery");
4
+ const AppQuery_1 = require("../../../graphql/queries/AppQuery");
5
5
  const AndroidAppBuildCredentialsMutation_1 = require("./graphql/mutations/AndroidAppBuildCredentialsMutation");
6
6
  const AndroidAppCredentialsMutation_1 = require("./graphql/mutations/AndroidAppCredentialsMutation");
7
7
  const AndroidFcmMutation_1 = require("./graphql/mutations/AndroidFcmMutation");
@@ -1,5 +1,6 @@
1
1
  import { ExpoConfig } from '@expo/config';
2
2
  import { Env } from '@expo/eas-build-job';
3
+ import { EasJson } from '@expo/eas-json';
3
4
  import { Actor } from '../user/User';
4
5
  import * as AndroidGraphqlClient from './android/api/GraphqlClient';
5
6
  import * as IosGraphqlClient from './ios/api/GraphqlClient';
@@ -12,10 +13,12 @@ export declare class CredentialsContext {
12
13
  readonly nonInteractive: boolean;
13
14
  readonly projectDir: string;
14
15
  readonly user: Actor;
16
+ readonly easJsonCliConfig?: EasJson['cli'];
15
17
  private shouldAskAuthenticateAppStore;
16
18
  private resolvedExp?;
17
19
  constructor(options: {
18
20
  exp?: ExpoConfig;
21
+ easJsonCliConfig?: EasJson['cli'];
19
22
  nonInteractive?: boolean;
20
23
  projectDir: string;
21
24
  user: Actor;
@@ -20,6 +20,7 @@ class CredentialsContext {
20
20
  this.appStore = new AppStoreApi_1.default();
21
21
  this.ios = IosGraphqlClient;
22
22
  this.shouldAskAuthenticateAppStore = true;
23
+ this.easJsonCliConfig = options.easJsonCliConfig;
23
24
  this.projectDir = options.projectDir;
24
25
  this.user = options.user;
25
26
  this.nonInteractive = (_a = options.nonInteractive) !== null && _a !== void 0 ? _a : false;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UnsupportedCredentialsChoiceError = exports.MissingCredentialsError = exports.MissingCredentialsNonInteractiveError = void 0;
4
4
  class MissingCredentialsNonInteractiveError extends Error {
5
5
  constructor(message) {
6
- super(message !== null && message !== void 0 ? message : 'Credentials are not set up. Please run this command again in interactive mode.');
6
+ super(message !== null && message !== void 0 ? message : 'Credentials are not set up. Run this command again in interactive mode.');
7
7
  }
8
8
  }
9
9
  exports.MissingCredentialsNonInteractiveError = MissingCredentialsNonInteractiveError;
@@ -17,6 +17,7 @@ export default class IosCredentialsProvider {
17
17
  private getLocalAsync;
18
18
  private getRemoteAsync;
19
19
  private getPushKeyAsync;
20
+ private disablePushNotificationsSetupInEasJsonAsync;
20
21
  private assertProvisioningProfileType;
21
22
  }
22
23
  export {};
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const eas_build_job_1 = require("@expo/eas-build-job");
5
5
  const eas_json_1 = require("@expo/eas-json");
6
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
6
7
  const log_1 = tslib_1.__importDefault(require("../../log"));
7
8
  const target_1 = require("../../project/ios/target");
8
9
  const prompts_1 = require("../../prompts");
@@ -12,6 +13,12 @@ const BuildCredentialsUtils_1 = require("./actions/BuildCredentialsUtils");
12
13
  const SetUpBuildCredentials_1 = require("./actions/SetUpBuildCredentials");
13
14
  const SetUpPushKey_1 = require("./actions/SetUpPushKey");
14
15
  const provisioningProfile_1 = require("./utils/provisioningProfile");
16
+ var PushNotificationSetupOption;
17
+ (function (PushNotificationSetupOption) {
18
+ PushNotificationSetupOption[PushNotificationSetupOption["YES"] = 0] = "YES";
19
+ PushNotificationSetupOption[PushNotificationSetupOption["NO"] = 1] = "NO";
20
+ PushNotificationSetupOption[PushNotificationSetupOption["NO_DONT_ASK_AGAIN"] = 2] = "NO_DONT_ASK_AGAIN";
21
+ })(PushNotificationSetupOption || (PushNotificationSetupOption = {}));
15
22
  class IosCredentialsProvider {
16
23
  constructor(ctx, options) {
17
24
  this.ctx = ctx;
@@ -47,6 +54,7 @@ class IosCredentialsProvider {
47
54
  }).runAsync(this.ctx);
48
55
  }
49
56
  async getPushKeyAsync(ctx, targets) {
57
+ var _a;
50
58
  if (ctx.nonInteractive) {
51
59
  return null;
52
60
  }
@@ -63,13 +71,33 @@ class IosCredentialsProvider {
63
71
  log_1.default.succeed(`Push Notifications setup for ${app.projectName}: ${applicationTarget.bundleIdentifier}`);
64
72
  return null;
65
73
  }
66
- const confirmSetup = await (0, prompts_1.confirmAsync)({
67
- message: `Would you like to set up Push Notifications for your project?`,
68
- });
69
- if (!confirmSetup) {
74
+ if (((_a = ctx.easJsonCliConfig) === null || _a === void 0 ? void 0 : _a.promptToConfigurePushNotfications) === false) {
70
75
  return null;
71
76
  }
72
- return await setupPushKeyAction.runAsync(ctx);
77
+ const setupOption = await (0, prompts_1.selectAsync)(`Would you like to set up Push Notifications for your project?`, [
78
+ { title: 'Yes', value: PushNotificationSetupOption.YES },
79
+ { title: 'No', value: PushNotificationSetupOption.NO },
80
+ {
81
+ title: `No, don't ask again (preference will be saved to eas.json)`,
82
+ value: PushNotificationSetupOption.NO_DONT_ASK_AGAIN,
83
+ },
84
+ ]);
85
+ if (setupOption === PushNotificationSetupOption.YES) {
86
+ return await setupPushKeyAction.runAsync(ctx);
87
+ }
88
+ else {
89
+ if (setupOption === PushNotificationSetupOption.NO_DONT_ASK_AGAIN) {
90
+ await this.disablePushNotificationsSetupInEasJsonAsync(ctx);
91
+ }
92
+ return null;
93
+ }
94
+ }
95
+ async disablePushNotificationsSetupInEasJsonAsync(ctx) {
96
+ const easJsonPath = eas_json_1.EasJsonReader.formatEasJsonPath(ctx.projectDir);
97
+ const easJson = await fs_extra_1.default.readJSON(easJsonPath);
98
+ easJson.cli = { ...easJson === null || easJson === void 0 ? void 0 : easJson.cli, promptToConfigurePushNotfications: false };
99
+ await fs_extra_1.default.writeFile(easJsonPath, `${JSON.stringify(easJson, null, 2)}\n`);
100
+ log_1.default.withTick('Updated eas.json');
73
101
  }
74
102
  assertProvisioningProfileType(provisioningProfile, targetName) {
75
103
  const isAdHoc = (0, provisioningProfile_1.isAdHocProfile)(provisioningProfile);
@@ -96,8 +96,8 @@ async function selectValidDistributionCertificateAsync(ctx, appLookupParams) {
96
96
  exports.selectValidDistributionCertificateAsync = selectValidDistributionCertificateAsync;
97
97
  const APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR = `
98
98
  You can have only ${chalk_1.default.underline('three')} Apple Distribution Certificates generated on your Apple Developer account.
99
- Please revoke the old ones or reuse existing from your other apps.
100
- Please remember that Apple Distribution Certificates are not application specific!
99
+ Revoke the old ones or reuse existing from your other apps.
100
+ Remember that Apple Distribution Certificates are not application specific!
101
101
  `;
102
102
  async function provideOrGenerateDistributionCertificateAsync(ctx) {
103
103
  if (!ctx.nonInteractive) {
@@ -34,7 +34,7 @@ class SetUpAdhocProvisioningProfile {
34
34
  return (0, nullthrows_1.default)(await (0, BuildCredentialsUtils_1.getBuildCredentialsAsync)(ctx, this.app, generated_1.IosDistributionType.AdHoc));
35
35
  }
36
36
  else {
37
- throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Please run this command again in interactive mode.');
37
+ throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Run this command again in interactive mode.');
38
38
  }
39
39
  }
40
40
  const currentBuildCredentials = await (0, BuildCredentialsUtils_1.getBuildCredentialsAsync)(ctx, this.app, generated_1.IosDistributionType.AdHoc);
@@ -59,7 +59,7 @@ class SetUpInternalProvisioningProfile {
59
59
  }
60
60
  else {
61
61
  if (adhocBuildCredentialsExist && enterpriseBuildCredentialsExist) {
62
- throw new Error(`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Please set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`);
62
+ throw new Error(`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`);
63
63
  }
64
64
  else if (adhocBuildCredentialsExist) {
65
65
  return await this.setupAdhocProvisioningProfileAsync(ctx);
@@ -68,7 +68,7 @@ class SetUpInternalProvisioningProfile {
68
68
  return await this.setupUniversalProvisioningProfileAsync(ctx);
69
69
  }
70
70
  else {
71
- throw new Error(`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Please run again in interactive mode.`);
71
+ throw new Error(`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Run this command again in interactive mode.`);
72
72
  }
73
73
  }
74
74
  }