eas-cli 0.35.0 → 0.38.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 (106) hide show
  1. package/README.md +37 -37
  2. package/build/analytics/common.d.ts +8 -0
  3. package/build/analytics/common.js +19 -0
  4. package/build/analytics/events.d.ts +43 -0
  5. package/build/analytics/events.js +51 -0
  6. package/build/{analytics.d.ts → analytics/rudderstackClient.d.ts} +0 -0
  7. package/build/{analytics.js → analytics/rudderstackClient.js} +2 -2
  8. package/build/build/android/build.d.ts +2 -1
  9. package/build/build/android/build.js +11 -9
  10. package/build/build/build.d.ts +0 -2
  11. package/build/build/build.js +19 -29
  12. package/build/build/configure.js +0 -1
  13. package/build/build/context.d.ts +19 -11
  14. package/build/build/context.js +0 -96
  15. package/build/build/createContext.d.ts +13 -0
  16. package/build/build/createContext.js +114 -0
  17. package/build/build/ios/UpdatesModule.js +3 -2
  18. package/build/build/ios/build.d.ts +2 -1
  19. package/build/build/ios/build.js +24 -19
  20. package/build/build/ios/credentials.js +3 -3
  21. package/build/build/ios/version.js +7 -3
  22. package/build/build/local.js +28 -26
  23. package/build/build/metadata.d.ts +1 -12
  24. package/build/build/metadata.js +24 -19
  25. package/build/build/types.d.ts +0 -1
  26. package/build/build/utils/devClient.d.ts +1 -2
  27. package/build/build/utils/repository.js +1 -0
  28. package/build/build/validate.d.ts +3 -3
  29. package/build/commandUtils/EasCommand.js +4 -4
  30. package/build/commands/branch/publish.js +24 -2
  31. package/build/commands/build/configure.js +2 -0
  32. package/build/commands/build/index.js +12 -17
  33. package/build/commands/channel/create.d.ts +6 -0
  34. package/build/commands/channel/create.js +2 -0
  35. package/build/commands/secret/create.js +0 -6
  36. package/build/commands/secret/delete.js +0 -6
  37. package/build/commands/secret/list.js +0 -6
  38. package/build/commands/submit.js +2 -11
  39. package/build/commands/webhook/create.js +1 -2
  40. package/build/commands/webhook/list.js +1 -1
  41. package/build/commands/webhook/update.js +1 -2
  42. package/build/credentials/android/actions/RemoveFcm.js +4 -4
  43. package/build/credentials/android/utils/keystore.js +67 -32
  44. package/build/credentials/ios/actions/AscApiKeyUtils.js +8 -7
  45. package/build/credentials/ios/actions/AssignAscApiKey.js +1 -1
  46. package/build/credentials/ios/actions/CreateAscApiKey.js +2 -2
  47. package/build/credentials/ios/actions/RemoveAscApiKey.js +6 -6
  48. package/build/credentials/ios/actions/SetUpAscApiKey.js +8 -8
  49. package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +3 -3
  50. package/build/credentials/ios/appstore/ascApiKey.js +12 -12
  51. package/build/credentials/ios/appstore/bundleIdCapabilities.js +11 -1
  52. package/build/credentials/ios/appstore/entitlements.d.ts +2 -2
  53. package/build/credentials/ios/appstore/entitlements.js +28 -21
  54. package/build/credentials/ios/credentials.js +2 -2
  55. package/build/credentials/ios/utils/printCredentials.js +1 -1
  56. package/build/credentials/manager/AndroidActions.js +3 -3
  57. package/build/credentials/manager/IosActions.js +5 -5
  58. package/build/credentials/manager/ManageIos.js +4 -4
  59. package/build/graphql/generated.d.ts +146 -54
  60. package/build/graphql/generated.js +1 -0
  61. package/build/graphql/mutations/KeystoreGenerationUrlMutation.d.ts +3 -0
  62. package/build/graphql/mutations/KeystoreGenerationUrlMutation.js +23 -0
  63. package/build/project/android/applicationId.d.ts +6 -0
  64. package/build/project/android/applicationId.js +39 -29
  65. package/build/project/android/gradle.js +3 -2
  66. package/build/project/android/gradleUtils.d.ts +1 -0
  67. package/build/project/ios/bundleIdentifier.d.ts +6 -1
  68. package/build/project/ios/bundleIdentifier.js +29 -18
  69. package/build/submit/BaseSubmitter.d.ts +20 -4
  70. package/build/submit/BaseSubmitter.js +34 -1
  71. package/build/submit/android/AndroidSubmitCommand.d.ts +1 -2
  72. package/build/submit/android/AndroidSubmitCommand.js +23 -35
  73. package/build/submit/android/AndroidSubmitter.d.ts +12 -8
  74. package/build/submit/android/AndroidSubmitter.js +30 -21
  75. package/build/submit/android/ServiceAccountSource.d.ts +3 -2
  76. package/build/submit/android/ServiceAccountSource.js +16 -4
  77. package/build/submit/context.d.ts +4 -0
  78. package/build/submit/context.js +16 -1
  79. package/build/submit/ios/AppSpecificPasswordSource.d.ts +8 -1
  80. package/build/submit/ios/AppSpecificPasswordSource.js +44 -4
  81. package/build/submit/ios/CredentialsServiceSource.d.ts +9 -5
  82. package/build/submit/ios/CredentialsServiceSource.js +22 -5
  83. package/build/submit/ios/IosSubmitCommand.d.ts +2 -2
  84. package/build/submit/ios/IosSubmitCommand.js +46 -53
  85. package/build/submit/ios/IosSubmitter.d.ts +17 -7
  86. package/build/submit/ios/IosSubmitter.js +55 -29
  87. package/build/submit/submit.js +13 -4
  88. package/build/user/User.js +1 -1
  89. package/build/{build/ios → utils}/plist.d.ts +1 -1
  90. package/build/{build/ios → utils}/plist.js +8 -2
  91. package/build/utils/profiles.d.ts +9 -4
  92. package/build/utils/profiles.js +14 -7
  93. package/build/vcs/clients/git.d.ts +2 -1
  94. package/build/vcs/clients/git.js +87 -6
  95. package/build/vcs/vcs.d.ts +4 -3
  96. package/build/vcs/vcs.js +3 -3
  97. package/build/webhooks/input.d.ts +2 -2
  98. package/build/webhooks/input.js +19 -2
  99. package/oclif.manifest.json +1 -1
  100. package/package.json +10 -10
  101. package/build/build/utils/analytics.d.ts +0 -22
  102. package/build/build/utils/analytics.js +0 -28
  103. package/build/project/isEasEnabledForProject.d.ts +0 -8
  104. package/build/project/isEasEnabledForProject.js +0 -33
  105. package/build/submit/android/AndroidPackageSource.d.ts +0 -17
  106. package/build/submit/android/AndroidPackageSource.js +0 -27
@@ -8,6 +8,7 @@ const nullthrows_1 = (0, tslib_1.__importDefault)(require("nullthrows"));
8
8
  const SetUpGoogleServiceAccountKey_1 = require("../../credentials/android/actions/SetUpGoogleServiceAccountKey");
9
9
  const googleServiceAccountKey_1 = require("../../credentials/android/utils/googleServiceAccountKey");
10
10
  const log_1 = (0, tslib_1.__importStar)(require("../../log"));
11
+ const applicationId_1 = require("../../project/android/applicationId");
11
12
  const prompts_1 = require("../../prompts");
12
13
  const Account_1 = require("../../user/Account");
13
14
  const files_1 = require("../utils/files");
@@ -17,9 +18,9 @@ var ServiceAccountSourceType;
17
18
  ServiceAccountSourceType[ServiceAccountSourceType["prompt"] = 1] = "prompt";
18
19
  ServiceAccountSourceType[ServiceAccountSourceType["credentialsService"] = 2] = "credentialsService";
19
20
  })(ServiceAccountSourceType = exports.ServiceAccountSourceType || (exports.ServiceAccountSourceType = {}));
20
- async function getServiceAccountKeyResultAsync(ctx, source, androidApplicationIdentifier) {
21
+ async function getServiceAccountKeyResultAsync(ctx, source) {
21
22
  if (source.sourceType === ServiceAccountSourceType.credentialsService) {
22
- return await getServiceAccountFromCredentialsServiceAsync(ctx, androidApplicationIdentifier);
23
+ return await getServiceAccountFromCredentialsServiceAsync(ctx, source);
23
24
  }
24
25
  else {
25
26
  return await getServiceAccountLocallyAsync(source);
@@ -50,12 +51,23 @@ async function getServiceAccountKeyPathAsync(source) {
50
51
  }
51
52
  }
52
53
  exports.getServiceAccountKeyPathAsync = getServiceAccountKeyPathAsync;
53
- async function getServiceAccountFromCredentialsServiceAsync(ctx, androidApplicationIdentifier) {
54
+ async function promptForApplicationIdAsync() {
55
+ const { androidPackage } = await (0, prompts_1.promptAsync)({
56
+ name: 'androidPackage',
57
+ message: 'Android package name:',
58
+ type: 'text',
59
+ validate: value => ((0, applicationId_1.isApplicationIdValid)(value) ? true : applicationId_1.INVALID_APPLICATION_ID_MESSAGE),
60
+ });
61
+ return androidPackage;
62
+ }
63
+ async function getServiceAccountFromCredentialsServiceAsync(ctx, source) {
64
+ var _a;
54
65
  const appLookupParams = {
55
66
  account: (0, nullthrows_1.default)((0, Account_1.findAccountByName)(ctx.user.accounts, ctx.accountName), `You do not have access to account: ${ctx.accountName}`),
56
67
  projectName: ctx.projectName,
57
- androidApplicationIdentifier,
68
+ androidApplicationIdentifier: (_a = source.androidApplicationIdentifier) !== null && _a !== void 0 ? _a : (await promptForApplicationIdAsync()),
58
69
  };
70
+ log_1.default.log(`Looking up credentials configuration for ${appLookupParams.androidApplicationIdentifier}...`);
59
71
  const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey_1.SetUpGoogleServiceAccountKey(appLookupParams);
60
72
  const androidAppCredentials = await setupGoogleServiceAccountKeyAction.runAsync(ctx.credentialsCtx);
61
73
  const googleServiceAccountKey = (0, nullthrows_1.default)(androidAppCredentials.googleServiceAccountKeyForSubmissions, 'Credentials Service must provide a valid GoogleServiceAccountKey');
@@ -1,12 +1,14 @@
1
1
  import { ExpoConfig } from '@expo/config';
2
2
  import { Platform } from '@expo/eas-build-job';
3
3
  import { SubmitProfile } from '@expo/eas-json';
4
+ import { TrackingContext } from '../analytics/common';
4
5
  import { CredentialsContext } from '../credentials/context';
5
6
  import { Actor } from '../user/User';
6
7
  export interface SubmissionContext<T extends Platform> {
7
8
  accountName: string;
8
9
  archiveFlags: SubmitArchiveFlags;
9
10
  credentialsCtx: CredentialsContext;
11
+ trackingCtx: TrackingContext;
10
12
  exp: ExpoConfig;
11
13
  nonInteractive: boolean;
12
14
  platform: T;
@@ -15,6 +17,7 @@ export interface SubmissionContext<T extends Platform> {
15
17
  projectId: string;
16
18
  projectName: string;
17
19
  user: Actor;
20
+ applicationIdentifierOverride?: string;
18
21
  }
19
22
  export interface SubmitArchiveFlags {
20
23
  latest?: boolean;
@@ -31,4 +34,5 @@ export declare function createSubmissionContextAsync<T extends Platform>(params:
31
34
  profile: SubmitProfile<T>;
32
35
  projectDir: string;
33
36
  projectId: string;
37
+ applicationIdentifier?: string;
34
38
  }): Promise<SubmissionContext<T>>;
@@ -1,21 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSubmissionContextAsync = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const events_1 = require("../analytics/events");
4
6
  const context_1 = require("../credentials/context");
5
7
  const expoConfig_1 = require("../project/expoConfig");
6
8
  const projectUtils_1 = require("../project/projectUtils");
9
+ const Account_1 = require("../user/Account");
7
10
  const actions_1 = require("../user/actions");
8
11
  async function createSubmissionContextAsync(params) {
9
- const { projectDir, nonInteractive } = params;
12
+ var _a;
13
+ const { applicationIdentifier, projectDir, nonInteractive } = params;
10
14
  const exp = (0, expoConfig_1.getExpoConfig)(projectDir, { env: params.env });
11
15
  const { env, ...rest } = params;
12
16
  const user = await (0, actions_1.ensureLoggedInAsync)();
13
17
  const projectName = exp.slug;
14
18
  const accountName = (0, projectUtils_1.getProjectAccountName)(exp, user);
19
+ const accountId = (_a = (0, Account_1.findAccountByName)(user.accounts, accountName)) === null || _a === void 0 ? void 0 : _a.id;
15
20
  let credentialsCtx = params.credentialsCtx;
16
21
  if (!credentialsCtx) {
17
22
  credentialsCtx = new context_1.CredentialsContext({ projectDir, user, exp, nonInteractive });
18
23
  }
24
+ const trackingCtx = {
25
+ tracking_id: (0, uuid_1.v4)(),
26
+ platform: params.platform,
27
+ ...(accountId && { account_id: accountId }),
28
+ account_name: accountName,
29
+ project_id: params.projectId,
30
+ };
31
+ events_1.Analytics.logEvent(events_1.SubmissionEvent.SUBMIT_COMMAND, trackingCtx);
19
32
  return {
20
33
  ...rest,
21
34
  accountName,
@@ -23,6 +36,8 @@ async function createSubmissionContextAsync(params) {
23
36
  exp,
24
37
  projectName,
25
38
  user,
39
+ trackingCtx,
40
+ applicationIdentifierOverride: applicationIdentifier,
26
41
  };
27
42
  }
28
43
  exports.createSubmissionContextAsync = createSubmissionContextAsync;
@@ -1,3 +1,5 @@
1
+ import { Platform } from '@expo/eas-build-job';
2
+ import { SubmissionContext } from '../context';
1
3
  export declare enum AppSpecificPasswordSourceType {
2
4
  userDefined = 0
3
5
  }
@@ -8,6 +10,11 @@ interface AppSpecificPasswordUserDefinedSource extends AppSpecificPasswordSource
8
10
  sourceType: AppSpecificPasswordSourceType.userDefined;
9
11
  appSpecificPassword: string;
10
12
  }
13
+ export interface AppSpecificPasswordCredentials {
14
+ password: string;
15
+ appleIdUsername: string;
16
+ }
11
17
  export declare type AppSpecificPasswordSource = AppSpecificPasswordUserDefinedSource;
12
- export declare function getAppSpecificPasswordAsync(source: AppSpecificPasswordSource): Promise<string>;
18
+ export declare function getAppSpecificPasswordLocallyAsync(ctx: SubmissionContext<Platform.IOS>, source: AppSpecificPasswordSource): Promise<AppSpecificPasswordCredentials>;
19
+ export declare function getAppleIdUsernameAsync(ctx: SubmissionContext<Platform.IOS>): Promise<string>;
13
20
  export {};
@@ -1,18 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAppSpecificPasswordAsync = exports.AppSpecificPasswordSourceType = void 0;
3
+ exports.getAppleIdUsernameAsync = exports.getAppSpecificPasswordLocallyAsync = exports.AppSpecificPasswordSourceType = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const getenv_1 = (0, tslib_1.__importDefault)(require("getenv"));
6
+ const prompts_1 = require("../../prompts");
7
+ const UserSettings_1 = (0, tslib_1.__importDefault)(require("../../user/UserSettings"));
4
8
  var AppSpecificPasswordSourceType;
5
9
  (function (AppSpecificPasswordSourceType) {
6
10
  AppSpecificPasswordSourceType[AppSpecificPasswordSourceType["userDefined"] = 0] = "userDefined";
7
11
  })(AppSpecificPasswordSourceType = exports.AppSpecificPasswordSourceType || (exports.AppSpecificPasswordSourceType = {}));
8
- async function getAppSpecificPasswordAsync(source) {
12
+ async function getAppSpecificPasswordLocallyAsync(ctx, source) {
9
13
  var _a;
10
14
  if (source.sourceType === AppSpecificPasswordSourceType.userDefined) {
11
- return source.appSpecificPassword;
15
+ return {
16
+ password: source.appSpecificPassword,
17
+ appleIdUsername: await getAppleIdUsernameAsync(ctx),
18
+ };
12
19
  }
13
20
  else {
14
21
  // exhaustive -- should never happen
15
22
  throw new Error(`Unknown app specific password source type "${(_a = source) === null || _a === void 0 ? void 0 : _a.sourceType}"`);
16
23
  }
17
24
  }
18
- exports.getAppSpecificPasswordAsync = getAppSpecificPasswordAsync;
25
+ exports.getAppSpecificPasswordLocallyAsync = getAppSpecificPasswordLocallyAsync;
26
+ async function getAppleIdUsernameAsync(ctx) {
27
+ var _a;
28
+ if (ctx.profile.appleId) {
29
+ return ctx.profile.appleId;
30
+ }
31
+ const envAppleId = getenv_1.default.string('EXPO_APPLE_ID', '');
32
+ if (envAppleId) {
33
+ return envAppleId;
34
+ }
35
+ if ((_a = ctx.credentialsCtx.appStore.authCtx) === null || _a === void 0 ? void 0 : _a.appleId) {
36
+ return ctx.credentialsCtx.appStore.authCtx.appleId;
37
+ }
38
+ // Get the email address that was last used and set it as
39
+ // the default value for quicker authentication.
40
+ const lastAppleId = await UserSettings_1.default.getAsync('appleId', null);
41
+ if (ctx.nonInteractive) {
42
+ if (lastAppleId) {
43
+ return lastAppleId;
44
+ }
45
+ else {
46
+ throw new Error('Set appleId in the submit profile (eas.json).');
47
+ }
48
+ }
49
+ const { appleId } = await (0, prompts_1.promptAsync)({
50
+ type: 'text',
51
+ name: 'appleId',
52
+ message: `Enter your Apple ID:`,
53
+ validate: (val) => !!val,
54
+ initial: lastAppleId !== null && lastAppleId !== void 0 ? lastAppleId : undefined,
55
+ });
56
+ return appleId;
57
+ }
58
+ exports.getAppleIdUsernameAsync = getAppleIdUsernameAsync;
@@ -1,14 +1,18 @@
1
1
  import { Platform } from '@expo/eas-build-job';
2
2
  import { SubmissionContext } from '../context';
3
+ import { AppSpecificPasswordCredentials } from './AppSpecificPasswordSource';
3
4
  import { AscApiKeyResult } from './AscApiKeySource';
4
5
  /**
5
- * The Credentials Service will either return an ASC Api Key or an App Specific Password
6
+ * The Credentials Service will either return an ASC API Key or an App Specific Password
6
7
  * When we no longer support the App Specific Password user prompt, refactor this into the AscApiKeySource
7
8
  */
8
- export declare const CREDENTIALS_SERVICE_SOURCE = "CREDENTIALS_SERVICE_SOURCE";
9
- export declare type CredentialsServiceSource = typeof CREDENTIALS_SERVICE_SOURCE;
10
- export declare function getFromCredentialsServiceAsync(ctx: SubmissionContext<Platform.IOS>): Promise<{
11
- appSpecificPassword: string;
9
+ export declare const CREDENTIALS_SERVICE_SOURCE: "CREDENTIALS_SERVICE_SOURCE";
10
+ export interface CredentialsServiceSource {
11
+ sourceType: typeof CREDENTIALS_SERVICE_SOURCE;
12
+ bundleIdentifier?: string;
13
+ }
14
+ export declare function getFromCredentialsServiceAsync(ctx: SubmissionContext<Platform.IOS>, source: CredentialsServiceSource): Promise<{
15
+ appSpecificPassword: AppSpecificPasswordCredentials;
12
16
  } | {
13
17
  ascApiKeyResult: AscApiKeyResult;
14
18
  }>;
@@ -6,14 +6,26 @@ const nullthrows_1 = (0, tslib_1.__importDefault)(require("nullthrows"));
6
6
  const SetUpSubmissionCredentials_1 = require("../../credentials/ios/actions/SetUpSubmissionCredentials");
7
7
  const log_1 = (0, tslib_1.__importDefault)(require("../../log"));
8
8
  const bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
9
+ const prompts_1 = require("../../prompts");
9
10
  const Account_1 = require("../../user/Account");
11
+ const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
10
12
  /**
11
- * The Credentials Service will either return an ASC Api Key or an App Specific Password
13
+ * The Credentials Service will either return an ASC API Key or an App Specific Password
12
14
  * When we no longer support the App Specific Password user prompt, refactor this into the AscApiKeySource
13
15
  */
14
16
  exports.CREDENTIALS_SERVICE_SOURCE = 'CREDENTIALS_SERVICE_SOURCE';
15
- async function getFromCredentialsServiceAsync(ctx) {
16
- const bundleIdentifier = await (0, bundleIdentifier_1.getBundleIdentifierAsync)(ctx.projectDir, ctx.exp);
17
+ async function promptForBundleIdentifierAsync() {
18
+ const { bundleIdentifier } = await (0, prompts_1.promptAsync)({
19
+ name: 'bundleIdentifier',
20
+ message: 'Bundle identifier:',
21
+ type: 'text',
22
+ validate: value => ((0, bundleIdentifier_1.isBundleIdentifierValid)(value) ? true : bundleIdentifier_1.INVALID_BUNDLE_IDENTIFIER_MESSAGE),
23
+ });
24
+ return bundleIdentifier;
25
+ }
26
+ async function getFromCredentialsServiceAsync(ctx, source) {
27
+ var _a;
28
+ const bundleIdentifier = (_a = source.bundleIdentifier) !== null && _a !== void 0 ? _a : (await promptForBundleIdentifierAsync());
17
29
  log_1.default.log(`Looking up credentials configuration for ${bundleIdentifier}...`);
18
30
  const appLookupParams = {
19
31
  account: (0, nullthrows_1.default)((0, Account_1.findAccountByName)(ctx.user.accounts, ctx.accountName), `You do not have access to account: ${ctx.accountName}`),
@@ -24,10 +36,15 @@ async function getFromCredentialsServiceAsync(ctx) {
24
36
  const ascOrAsp = await setupSubmissionCredentialsAction.runAsync(ctx.credentialsCtx);
25
37
  const isAppSpecificPassword = typeof ascOrAsp === 'string';
26
38
  if (isAppSpecificPassword) {
27
- return { appSpecificPassword: ascOrAsp };
39
+ return {
40
+ appSpecificPassword: {
41
+ password: ascOrAsp,
42
+ appleIdUsername: await (0, AppSpecificPasswordSource_1.getAppleIdUsernameAsync)(ctx),
43
+ },
44
+ };
28
45
  }
29
46
  else {
30
- const ascKeyForSubmissions = (0, nullthrows_1.default)(ascOrAsp.appStoreConnectApiKeyForSubmissions, `An EAS Submit ASC Api Key could not be found for ${ascOrAsp.appleAppIdentifier.bundleIdentifier}`);
47
+ const ascKeyForSubmissions = (0, nullthrows_1.default)(ascOrAsp.appStoreConnectApiKeyForSubmissions, `An EAS Submit ASC API Key could not be found for ${ascOrAsp.appleAppIdentifier.bundleIdentifier}`);
31
48
  const { id, keyIdentifier, name } = ascKeyForSubmissions;
32
49
  return {
33
50
  ascApiKeyResult: {
@@ -5,11 +5,11 @@ export default class IosSubmitCommand {
5
5
  private ctx;
6
6
  constructor(ctx: SubmissionContext<Platform.IOS>);
7
7
  runAsync(): Promise<SubmissionFragment>;
8
- private resolveCredentialSubmissionOptionsAsync;
9
8
  private resolveSubmissionOptionsAsync;
9
+ private maybeGetIosBundleIdentifierAsync;
10
+ private resolveCredentialSubmissionOptionsAsync;
10
11
  private resolveAppSpecificPasswordSource;
11
12
  private resolveAscApiKeySource;
12
13
  private resolveArchiveSource;
13
14
  private resolveAscAppIdentifierAsync;
14
- private resolveAppleIdUsernameAsync;
15
15
  }
@@ -8,8 +8,7 @@ const getenv_1 = (0, tslib_1.__importDefault)(require("getenv"));
8
8
  const wrap_ansi_1 = (0, tslib_1.__importDefault)(require("wrap-ansi"));
9
9
  const errors_1 = require("../../credentials/errors");
10
10
  const log_1 = (0, tslib_1.__importStar)(require("../../log"));
11
- const prompts_1 = require("../../prompts");
12
- const UserSettings_1 = (0, tslib_1.__importDefault)(require("../../user/UserSettings"));
11
+ const bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
13
12
  const commons_1 = require("../commons");
14
13
  const AppProduce_1 = require("./AppProduce");
15
14
  const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
@@ -26,22 +25,6 @@ class IosSubmitCommand {
26
25
  const submitter = new IosSubmitter_1.default(this.ctx, options);
27
26
  return await submitter.submitAsync();
28
27
  }
29
- async resolveCredentialSubmissionOptionsAsync() {
30
- const ascApiKeySource = this.resolveAscApiKeySource();
31
- const shouldSkipAscApiKeySource = !ascApiKeySource.ok && ascApiKeySource.enforceError() instanceof errors_1.MissingCredentialsError;
32
- if (!shouldSkipAscApiKeySource) {
33
- return { ascApiKeySource };
34
- }
35
- const appSpecificPasswordSource = this.resolveAppSpecificPasswordSource();
36
- const shouldSkipAppSpecificPasswordSource = !appSpecificPasswordSource.ok &&
37
- appSpecificPasswordSource.enforceError() instanceof errors_1.MissingCredentialsError;
38
- if (!shouldSkipAppSpecificPasswordSource) {
39
- return { appSpecificPasswordSource: this.resolveAppSpecificPasswordSource() };
40
- }
41
- return {
42
- credentialsServiceSource: (0, results_1.result)(CredentialsServiceSource_1.CREDENTIALS_SERVICE_SOURCE),
43
- };
44
- }
45
28
  async resolveSubmissionOptionsAsync() {
46
29
  const archiveSource = this.resolveArchiveSource();
47
30
  const credentialsSource = await this.resolveCredentialSubmissionOptionsAsync();
@@ -53,14 +36,12 @@ class IosSubmitCommand {
53
36
  ? credentialsSource.credentialsServiceSource
54
37
  : null;
55
38
  const ascAppIdentifier = await this.resolveAscAppIdentifierAsync();
56
- const appleIdUsername = await this.resolveAppleIdUsernameAsync();
57
39
  const errored = [
58
40
  archiveSource,
59
41
  ...(maybeAppSpecificPasswordSource ? [maybeAppSpecificPasswordSource] : []),
60
42
  ...(maybeAscApiKeySource ? [maybeAscApiKeySource] : []),
61
43
  ...(maybeCredentialsServiceSource ? [maybeCredentialsServiceSource] : []),
62
44
  ascAppIdentifier,
63
- appleIdUsername,
64
45
  ].filter(r => !r.ok);
65
46
  if (errored.length > 0) {
66
47
  const message = errored.map(err => { var _a; return (_a = err.reason) === null || _a === void 0 ? void 0 : _a.message; }).join('\n');
@@ -69,7 +50,6 @@ class IosSubmitCommand {
69
50
  }
70
51
  return {
71
52
  projectId: this.ctx.projectId,
72
- appleIdUsername: appleIdUsername.enforceValue(),
73
53
  ascAppIdentifier: ascAppIdentifier.enforceValue(),
74
54
  archiveSource: archiveSource.enforceValue(),
75
55
  ...(maybeAppSpecificPasswordSource
@@ -89,6 +69,51 @@ class IosSubmitCommand {
89
69
  : null),
90
70
  };
91
71
  }
72
+ async maybeGetIosBundleIdentifierAsync() {
73
+ try {
74
+ return (0, results_1.result)(await (0, bundleIdentifier_1.getBundleIdentifierAsync)(this.ctx.projectDir, this.ctx.exp));
75
+ }
76
+ catch (error) {
77
+ if (error instanceof bundleIdentifier_1.AmbiguousBundleIdentifierError) {
78
+ log_1.default.warn('bundleIdentifier in the Xcode project is ambiguous, specify it via "bundleIdentifier" field in the submit profile in the eas.json.');
79
+ return (0, results_1.result)(null);
80
+ }
81
+ return (0, results_1.result)(new Error(`Failed to resolve bundleIdentifier in the Xcode project: ${error.message}.`));
82
+ }
83
+ }
84
+ async resolveCredentialSubmissionOptionsAsync() {
85
+ var _a;
86
+ const ascApiKeySource = this.resolveAscApiKeySource();
87
+ const shouldSkipAscApiKeySource = !ascApiKeySource.ok && ascApiKeySource.enforceError() instanceof errors_1.MissingCredentialsError;
88
+ if (!shouldSkipAscApiKeySource) {
89
+ return { ascApiKeySource };
90
+ }
91
+ const appSpecificPasswordSource = this.resolveAppSpecificPasswordSource();
92
+ const shouldSkipAppSpecificPasswordSource = !appSpecificPasswordSource.ok &&
93
+ appSpecificPasswordSource.enforceError() instanceof errors_1.MissingCredentialsError;
94
+ if (!shouldSkipAppSpecificPasswordSource) {
95
+ return { appSpecificPasswordSource: this.resolveAppSpecificPasswordSource() };
96
+ }
97
+ let bundleIdentifier = (_a = this.ctx.applicationIdentifierOverride) !== null && _a !== void 0 ? _a : this.ctx.profile.bundleIdentifier;
98
+ if (!bundleIdentifier) {
99
+ const bundleIdentifierResult = await this.maybeGetIosBundleIdentifierAsync();
100
+ if (!bundleIdentifierResult.ok) {
101
+ return {
102
+ credentialsServiceSource: (0, results_1.result)(bundleIdentifierResult.reason),
103
+ };
104
+ }
105
+ const bundleIdentifierValue = bundleIdentifierResult.enforceValue();
106
+ if (bundleIdentifierValue) {
107
+ bundleIdentifier = bundleIdentifierValue;
108
+ }
109
+ }
110
+ return {
111
+ credentialsServiceSource: (0, results_1.result)({
112
+ sourceType: CredentialsServiceSource_1.CREDENTIALS_SERVICE_SOURCE,
113
+ bundleIdentifier,
114
+ }),
115
+ };
116
+ }
92
117
  resolveAppSpecificPasswordSource() {
93
118
  const envAppSpecificPassword = getenv_1.default.string('EXPO_APPLE_APP_SPECIFIC_PASSWORD', '');
94
119
  if (envAppSpecificPassword) {
@@ -148,37 +173,5 @@ class IosSubmitCommand {
148
173
  }
149
174
  }
150
175
  }
151
- async resolveAppleIdUsernameAsync() {
152
- var _a;
153
- if (this.ctx.profile.appleId) {
154
- return (0, results_1.result)(this.ctx.profile.appleId);
155
- }
156
- const envAppleId = getenv_1.default.string('EXPO_APPLE_ID', '');
157
- if (envAppleId) {
158
- return (0, results_1.result)(envAppleId);
159
- }
160
- if ((_a = this.ctx.credentialsCtx.appStore.authCtx) === null || _a === void 0 ? void 0 : _a.appleId) {
161
- return (0, results_1.result)(this.ctx.credentialsCtx.appStore.authCtx.appleId);
162
- }
163
- // Get the email address that was last used and set it as
164
- // the default value for quicker authentication.
165
- const lastAppleId = await UserSettings_1.default.getAsync('appleId', null);
166
- if (this.ctx.nonInteractive) {
167
- if (lastAppleId) {
168
- return (0, results_1.result)(lastAppleId);
169
- }
170
- else {
171
- return (0, results_1.result)(new Error('Set appleId in the submit profile (eas.json).'));
172
- }
173
- }
174
- const { appleId } = await (0, prompts_1.promptAsync)({
175
- type: 'text',
176
- name: 'appleId',
177
- message: `Enter your Apple ID:`,
178
- validate: (val) => !!val,
179
- initial: lastAppleId !== null && lastAppleId !== void 0 ? lastAppleId : undefined,
180
- });
181
- return (0, results_1.result)(appleId);
182
- }
183
176
  }
184
177
  exports.default = IosSubmitCommand;
@@ -1,9 +1,10 @@
1
1
  import { Platform } from '@expo/eas-build-job';
2
2
  import { IosSubmissionConfigInput, SubmissionFragment } from '../../graphql/generated';
3
- import { ArchiveSource } from '../ArchiveSource';
3
+ import { Archive, ArchiveSource } from '../ArchiveSource';
4
4
  import BaseSubmitter, { SubmissionInput } from '../BaseSubmitter';
5
- import { AppSpecificPasswordSource } from './AppSpecificPasswordSource';
6
- import { AscApiKeySource } from './AscApiKeySource';
5
+ import { SubmissionContext } from '../context';
6
+ import { AppSpecificPasswordCredentials, AppSpecificPasswordSource } from './AppSpecificPasswordSource';
7
+ import { AscApiKeyResult, AscApiKeySource } from './AscApiKeySource';
7
8
  import { CredentialsServiceSource } from './CredentialsServiceSource';
8
9
  export interface IosSubmissionOptions extends Pick<IosSubmissionConfigInput, 'appleIdUsername' | 'ascAppIdentifier'> {
9
10
  projectId: string;
@@ -12,11 +13,20 @@ export interface IosSubmissionOptions extends Pick<IosSubmissionConfigInput, 'ap
12
13
  ascApiKeySource?: AscApiKeySource;
13
14
  credentialsServiceSource?: CredentialsServiceSource;
14
15
  }
15
- export default class IosSubmitter extends BaseSubmitter<Platform.IOS, IosSubmissionOptions> {
16
- submitAsync(): Promise<SubmissionFragment>;
16
+ interface ResolvedSourceOptions {
17
+ archive: Archive;
18
+ credentials: {
19
+ appSpecificPassword?: AppSpecificPasswordCredentials;
20
+ ascApiKeyResult?: AscApiKeyResult;
21
+ };
22
+ }
23
+ export default class IosSubmitter extends BaseSubmitter<Platform.IOS, ResolvedSourceOptions, IosSubmissionOptions> {
24
+ constructor(ctx: SubmissionContext<Platform.IOS>, options: IosSubmissionOptions);
25
+ createSubmissionInputAsync(resolvedSourceOptions: ResolvedSourceOptions): Promise<SubmissionInput<Platform.IOS>>;
17
26
  protected createPlatformSubmissionAsync({ projectId, submissionConfig, buildId, }: SubmissionInput<Platform.IOS>): Promise<SubmissionFragment>;
18
- private resolveSourceOptionsAsync;
19
- private formatSubmissionConfigAsync;
27
+ private formatSubmissionConfig;
28
+ private formatAppSpecificPassword;
20
29
  private formatAscApiKeyResult;
21
30
  private prepareSummaryData;
22
31
  }
32
+ export {};
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
5
+ const events_1 = require("../../analytics/events");
5
6
  const SubmissionMutation_1 = require("../../graphql/mutations/SubmissionMutation");
6
7
  const formatFields_1 = (0, tslib_1.__importDefault)(require("../../utils/formatFields"));
7
8
  const ArchiveSource_1 = require("../ArchiveSource");
@@ -11,16 +12,51 @@ const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
11
12
  const AscApiKeySource_1 = require("./AscApiKeySource");
12
13
  const CredentialsServiceSource_1 = require("./CredentialsServiceSource");
13
14
  class IosSubmitter extends BaseSubmitter_1.default {
14
- async submitAsync() {
15
+ constructor(ctx, options) {
16
+ const sourceOptionsResolver = {
17
+ // eslint-disable-next-line async-protect/async-suffix
18
+ archive: async () => await (0, ArchiveSource_1.getArchiveAsync)(this.options.archiveSource),
19
+ // eslint-disable-next-line async-protect/async-suffix
20
+ credentials: async () => {
21
+ const maybeAppSpecificPassword = this.options.appSpecificPasswordSource
22
+ ? await (0, AppSpecificPasswordSource_1.getAppSpecificPasswordLocallyAsync)(this.ctx, this.options.appSpecificPasswordSource)
23
+ : null;
24
+ const maybeAppStoreConnectApiKey = this.options.ascApiKeySource
25
+ ? await (0, AscApiKeySource_1.getAscApiKeyLocallyAsync)(this.ctx, this.options.ascApiKeySource)
26
+ : null;
27
+ const maybeAscOrAspFromCredentialsService = this.options.credentialsServiceSource
28
+ ? await (0, CredentialsServiceSource_1.getFromCredentialsServiceAsync)(this.ctx, this.options.credentialsServiceSource)
29
+ : null;
30
+ return {
31
+ ...(maybeAppSpecificPassword ? { appSpecificPassword: maybeAppSpecificPassword } : null),
32
+ ...(maybeAppStoreConnectApiKey ? { ascApiKeyResult: maybeAppStoreConnectApiKey } : null),
33
+ ...(maybeAscOrAspFromCredentialsService ? maybeAscOrAspFromCredentialsService : null),
34
+ };
35
+ },
36
+ };
37
+ const sourceOptionsAnalytics = {
38
+ archive: {
39
+ attemptEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_ATTEMPT,
40
+ successEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_SUCCESS,
41
+ failureEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_FAIL,
42
+ },
43
+ credentials: {
44
+ attemptEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_ATTEMPT,
45
+ successEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_SUCCESS,
46
+ failureEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_FAIL,
47
+ },
48
+ };
49
+ super(ctx, options, sourceOptionsResolver, sourceOptionsAnalytics);
50
+ }
51
+ async createSubmissionInputAsync(resolvedSourceOptions) {
15
52
  var _a;
16
- const resolvedSourceOptions = await this.resolveSourceOptionsAsync();
17
- const submissionConfig = await this.formatSubmissionConfigAsync(this.options, resolvedSourceOptions);
53
+ const submissionConfig = this.formatSubmissionConfig(this.options, resolvedSourceOptions);
18
54
  (0, summary_1.printSummary)(this.prepareSummaryData(this.options, resolvedSourceOptions), SummaryHumanReadableKeys);
19
- return await this.createSubmissionAsync({
55
+ return {
20
56
  projectId: this.options.projectId,
21
57
  submissionConfig,
22
58
  buildId: (_a = resolvedSourceOptions.archive.build) === null || _a === void 0 ? void 0 : _a.id,
23
- });
59
+ };
24
60
  }
25
61
  async createPlatformSubmissionAsync({ projectId, submissionConfig, buildId, }) {
26
62
  return await SubmissionMutation_1.SubmissionMutation.createIosSubmissionAsync({
@@ -29,34 +65,23 @@ class IosSubmitter extends BaseSubmitter_1.default {
29
65
  submittedBuildId: buildId,
30
66
  });
31
67
  }
32
- async resolveSourceOptionsAsync() {
33
- const archive = await (0, ArchiveSource_1.getArchiveAsync)(this.options.archiveSource);
34
- const maybeAppSpecificPassword = this.options.appSpecificPasswordSource
35
- ? await (0, AppSpecificPasswordSource_1.getAppSpecificPasswordAsync)(this.options.appSpecificPasswordSource)
36
- : null;
37
- const maybeAppStoreConnectApiKey = this.options.ascApiKeySource
38
- ? await (0, AscApiKeySource_1.getAscApiKeyLocallyAsync)(this.ctx, this.options.ascApiKeySource)
39
- : null;
40
- const maybeAscOrAspFromCredentialsService = this.options.credentialsServiceSource
41
- ? await (0, CredentialsServiceSource_1.getFromCredentialsServiceAsync)(this.ctx)
42
- : null;
43
- return {
44
- archive,
45
- ...(maybeAppSpecificPassword ? { appSpecificPassword: maybeAppSpecificPassword } : null),
46
- ...(maybeAppStoreConnectApiKey ? { ascApiKeyResult: maybeAppStoreConnectApiKey } : null),
47
- ...(maybeAscOrAspFromCredentialsService ? maybeAscOrAspFromCredentialsService : null),
48
- };
49
- }
50
- async formatSubmissionConfigAsync(options, { archive, appSpecificPassword, ascApiKeyResult }) {
68
+ formatSubmissionConfig(options, { archive, credentials }) {
69
+ const { appSpecificPassword, ascApiKeyResult } = credentials;
51
70
  const { appleIdUsername, ascAppIdentifier } = options;
52
71
  return {
53
72
  ascAppIdentifier,
54
73
  appleIdUsername,
55
74
  archiveUrl: archive.url,
56
- appleAppSpecificPassword: appSpecificPassword,
75
+ ...(appSpecificPassword ? this.formatAppSpecificPassword(appSpecificPassword) : null),
57
76
  ...((ascApiKeyResult === null || ascApiKeyResult === void 0 ? void 0 : ascApiKeyResult.result) ? this.formatAscApiKeyResult(ascApiKeyResult.result) : null),
58
77
  };
59
78
  }
79
+ formatAppSpecificPassword(appSpecificPassword) {
80
+ return {
81
+ appleAppSpecificPassword: appSpecificPassword.password,
82
+ appleIdUsername: appSpecificPassword.appleIdUsername,
83
+ };
84
+ }
60
85
  formatAscApiKeyResult(result) {
61
86
  return 'ascApiKeyId' in result
62
87
  ? { ascApiKeyId: result.ascApiKeyId }
@@ -68,13 +93,14 @@ class IosSubmitter extends BaseSubmitter_1.default {
68
93
  },
69
94
  };
70
95
  }
71
- prepareSummaryData(options, { archive, ascApiKeyResult }) {
72
- const { appleIdUsername, ascAppIdentifier, projectId } = options;
96
+ prepareSummaryData(options, { archive, credentials }) {
97
+ const { ascApiKeyResult, appSpecificPassword } = credentials;
98
+ const { ascAppIdentifier, projectId } = options;
73
99
  // structuring order affects table rows order
74
100
  return {
75
101
  ascAppIdentifier,
76
- appleIdUsername: appleIdUsername !== null && appleIdUsername !== void 0 ? appleIdUsername : undefined,
77
102
  projectId,
103
+ ...(appSpecificPassword ? { appleIdUsername: appSpecificPassword.appleIdUsername } : null),
78
104
  ...(ascApiKeyResult ? { formattedAscApiKey: formatAscApiKeySummary(ascApiKeyResult) } : null),
79
105
  ...(0, summary_1.formatArchiveSourceSummary)(archive),
80
106
  };
@@ -88,7 +114,7 @@ const SummaryHumanReadableKeys = {
88
114
  archiveUrl: 'Archive URL',
89
115
  archivePath: 'Archive Path',
90
116
  formattedBuild: 'Build',
91
- formattedAscApiKey: 'App Store Connect Api Key',
117
+ formattedAscApiKey: 'App Store Connect API Key',
92
118
  };
93
119
  function formatAscApiKeySummary({ summary }) {
94
120
  const { source, path, keyId, name } = summary;
@@ -4,6 +4,8 @@ exports.waitToCompleteAsync = exports.submitAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const eas_build_job_1 = require("@expo/eas-build-job");
6
6
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
7
+ const common_1 = require("../analytics/common");
8
+ const events_1 = require("../analytics/events");
7
9
  const generated_1 = require("../graphql/generated");
8
10
  const log_1 = (0, tslib_1.__importStar)(require("../log"));
9
11
  const platform_1 = require("../platform");
@@ -12,10 +14,17 @@ const IosSubmitCommand_1 = (0, tslib_1.__importDefault)(require("./ios/IosSubmit
12
14
  const logs_1 = require("./utils/logs");
13
15
  const wait_1 = require("./utils/wait");
14
16
  async function submitAsync(ctx) {
15
- const command = ctx.platform === eas_build_job_1.Platform.ANDROID
16
- ? new AndroidSubmitCommand_1.default(ctx)
17
- : new IosSubmitCommand_1.default(ctx);
18
- return command.runAsync();
17
+ return await (0, common_1.withAnalyticsAsync)(async () => {
18
+ const command = ctx.platform === eas_build_job_1.Platform.ANDROID
19
+ ? new AndroidSubmitCommand_1.default(ctx)
20
+ : new IosSubmitCommand_1.default(ctx);
21
+ return command.runAsync();
22
+ }, {
23
+ attemptEvent: events_1.SubmissionEvent.SUBMIT_COMMAND_ATTEMPT,
24
+ successEvent: events_1.SubmissionEvent.SUBMIT_COMMAND_SUCCESS,
25
+ failureEvent: events_1.SubmissionEvent.SUBMIT_COMMAND_FAIL,
26
+ trackingCtx: ctx.trackingCtx,
27
+ });
19
28
  }
20
29
  exports.submitAsync = submitAsync;
21
30
  async function waitToCompleteAsync(submissions, { verbose = false } = {}) {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.logoutAsync = exports.loginAsync = exports.getUserAsync = exports.getActorDisplayName = exports.getAccessToken = exports.getSessionSecret = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const graphql_tag_1 = (0, tslib_1.__importDefault)(require("graphql-tag"));
6
- const Analytics = (0, tslib_1.__importStar)(require("../analytics"));
6
+ const Analytics = (0, tslib_1.__importStar)(require("../analytics/rudderstackClient"));
7
7
  const api_1 = require("../api");
8
8
  const client_1 = require("../graphql/client");
9
9
  const UserQuery_1 = require("../graphql/queries/UserQuery");