eas-cli 0.34.0 → 0.36.1

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 (125) hide show
  1. package/README.md +27 -27
  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/api.js +3 -3
  9. package/build/build/build.js +18 -27
  10. package/build/build/context.d.ts +1 -1
  11. package/build/build/context.js +2 -2
  12. package/build/build/ios/credentials.js +3 -3
  13. package/build/build/local.js +18 -27
  14. package/build/build/types.d.ts +0 -1
  15. package/build/build/utils/devClient.js +6 -3
  16. package/build/build/utils/formatBuild.js +1 -9
  17. package/build/build/utils/url.js +1 -1
  18. package/build/commandUtils/EasCommand.js +4 -4
  19. package/build/commands/build/index.js +14 -5
  20. package/build/commands/secret/delete.js +1 -1
  21. package/build/credentials/android/AndroidCredentialsProvider.js +2 -2
  22. package/build/credentials/android/actions/RemoveFcm.js +4 -4
  23. package/build/credentials/android/actions/{SetupBuildCredentials.d.ts → SetUpBuildCredentials.d.ts} +1 -1
  24. package/build/credentials/android/actions/{SetupBuildCredentials.js → SetUpBuildCredentials.js} +3 -3
  25. package/build/credentials/android/actions/{SetupBuildCredentialsFromCredentialsJson.d.ts → SetUpBuildCredentialsFromCredentialsJson.d.ts} +1 -1
  26. package/build/credentials/android/actions/{SetupBuildCredentialsFromCredentialsJson.js → SetUpBuildCredentialsFromCredentialsJson.js} +3 -3
  27. package/build/credentials/android/actions/{SetupGoogleServiceAccountKey.d.ts → SetUpGoogleServiceAccountKey.d.ts} +1 -1
  28. package/build/credentials/android/actions/{SetupGoogleServiceAccountKey.js → SetUpGoogleServiceAccountKey.js} +3 -3
  29. package/build/credentials/android/utils/keystore.js +67 -32
  30. package/build/credentials/errors.d.ts +4 -0
  31. package/build/credentials/errors.js +8 -1
  32. package/build/credentials/ios/IosCredentialsProvider.js +4 -4
  33. package/build/credentials/ios/actions/AscApiKeyUtils.d.ts +17 -1
  34. package/build/credentials/ios/actions/AscApiKeyUtils.js +158 -24
  35. package/build/credentials/ios/actions/AssignAscApiKey.d.ts +9 -0
  36. package/build/credentials/ios/actions/AssignAscApiKey.js +29 -0
  37. package/build/credentials/ios/actions/CreateAscApiKey.d.ts +9 -0
  38. package/build/credentials/ios/actions/CreateAscApiKey.js +21 -0
  39. package/build/credentials/ios/actions/DistributionCertificateUtils.js +1 -1
  40. package/build/credentials/ios/actions/PushKeyUtils.js +1 -1
  41. package/build/credentials/ios/actions/RemoveAscApiKey.d.ts +14 -0
  42. package/build/credentials/ios/actions/RemoveAscApiKey.js +55 -0
  43. package/build/credentials/ios/actions/{SetupAdhocProvisioningProfile.d.ts → SetUpAdhocProvisioningProfile.d.ts} +1 -1
  44. package/build/credentials/ios/actions/{SetupAdhocProvisioningProfile.js → SetUpAdhocProvisioningProfile.js} +5 -5
  45. package/build/credentials/ios/actions/SetUpAscApiKey.d.ts +21 -0
  46. package/build/credentials/ios/actions/SetUpAscApiKey.js +114 -0
  47. package/build/credentials/ios/actions/{SetupBuildCredentials.d.ts → SetUpBuildCredentials.d.ts} +1 -1
  48. package/build/credentials/ios/actions/{SetupBuildCredentials.js → SetUpBuildCredentials.js} +5 -5
  49. package/build/credentials/ios/actions/{SetupBuildCredentialsFromCredentialsJson.d.ts → SetUpBuildCredentialsFromCredentialsJson.d.ts} +1 -1
  50. package/build/credentials/ios/actions/{SetupBuildCredentialsFromCredentialsJson.js → SetUpBuildCredentialsFromCredentialsJson.js} +5 -5
  51. package/build/credentials/ios/actions/{SetupDistributionCertificate.d.ts → SetUpDistributionCertificate.d.ts} +1 -1
  52. package/build/credentials/ios/actions/{SetupDistributionCertificate.js → SetUpDistributionCertificate.js} +3 -3
  53. package/build/credentials/ios/actions/{SetupInternalProvisioningProfile.d.ts → SetUpInternalProvisioningProfile.d.ts} +1 -1
  54. package/build/credentials/ios/actions/{SetupInternalProvisioningProfile.js → SetUpInternalProvisioningProfile.js} +7 -7
  55. package/build/credentials/ios/actions/{SetupProvisioningProfile.d.ts → SetUpProvisioningProfile.d.ts} +1 -1
  56. package/build/credentials/ios/actions/{SetupProvisioningProfile.js → SetUpProvisioningProfile.js} +5 -5
  57. package/build/credentials/ios/actions/{SetupPushKey.d.ts → SetUpPushKey.d.ts} +1 -1
  58. package/build/credentials/ios/actions/{SetupPushKey.js → SetUpPushKey.js} +3 -3
  59. package/build/credentials/ios/actions/SetUpSubmissionCredentials.d.ts +10 -0
  60. package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +53 -0
  61. package/build/credentials/ios/actions/{SetupTargetBuildCredentials.d.ts → SetUpTargetBuildCredentials.d.ts} +1 -1
  62. package/build/credentials/ios/actions/{SetupTargetBuildCredentials.js → SetUpTargetBuildCredentials.js} +10 -10
  63. package/build/credentials/ios/actions/{SetupTargetBuildCredentialsFromCredentialsJson.d.ts → SetUpTargetBuildCredentialsFromCredentialsJson.d.ts} +1 -1
  64. package/build/credentials/ios/actions/{SetupTargetBuildCredentialsFromCredentialsJson.js → SetUpTargetBuildCredentialsFromCredentialsJson.js} +3 -3
  65. package/build/credentials/ios/api/GraphqlClient.d.ts +8 -2
  66. package/build/credentials/ios/api/GraphqlClient.js +74 -2
  67. package/build/credentials/ios/api/graphql/mutations/AppStoreConnectApiKeyMutation.d.ts +5 -0
  68. package/build/credentials/ios/api/graphql/mutations/AppStoreConnectApiKeyMutation.js +54 -0
  69. package/build/credentials/ios/api/graphql/mutations/IosAppCredentialsMutation.d.ts +1 -0
  70. package/build/credentials/ios/api/graphql/mutations/IosAppCredentialsMutation.js +25 -0
  71. package/build/credentials/ios/api/graphql/queries/AppStoreConnectApiKeyQuery.d.ts +4 -0
  72. package/build/credentials/ios/api/graphql/queries/AppStoreConnectApiKeyQuery.js +33 -0
  73. package/build/credentials/ios/appstore/AppStoreApi.d.ts +1 -1
  74. package/build/credentials/ios/appstore/Credentials.types.d.ts +1 -0
  75. package/build/credentials/ios/appstore/ascApiKey.d.ts +1 -1
  76. package/build/credentials/ios/appstore/ascApiKey.js +11 -1
  77. package/build/credentials/ios/appstore/entitlements.d.ts +2 -2
  78. package/build/credentials/ios/appstore/entitlements.js +20 -10
  79. package/build/credentials/ios/credentials.d.ts +2 -1
  80. package/build/credentials/ios/credentials.js +7 -2
  81. package/build/credentials/ios/utils/printCredentials.js +30 -1
  82. package/build/credentials/ios/validators/validateAscApiKey.d.ts +5 -0
  83. package/build/credentials/ios/validators/validateAscApiKey.js +21 -0
  84. package/build/credentials/manager/Actions.d.ts +20 -15
  85. package/build/credentials/manager/Actions.js +20 -15
  86. package/build/credentials/manager/AndroidActions.js +6 -6
  87. package/build/credentials/manager/IosActions.d.ts +1 -0
  88. package/build/credentials/manager/IosActions.js +40 -5
  89. package/build/credentials/manager/ManageAndroid.js +6 -6
  90. package/build/credentials/manager/ManageIos.js +56 -17
  91. package/build/credentials/utils/promptForCredentials.d.ts +2 -1
  92. package/build/credentials/utils/promptForCredentials.js +3 -2
  93. package/build/graphql/client.js +1 -1
  94. package/build/graphql/generated.d.ts +233 -82
  95. package/build/graphql/mutations/KeystoreGenerationUrlMutation.d.ts +3 -0
  96. package/build/graphql/mutations/KeystoreGenerationUrlMutation.js +23 -0
  97. package/build/graphql/types/Build.js +1 -6
  98. package/build/graphql/types/credentials/AppStoreConnectApiKey.d.ts +1 -0
  99. package/build/graphql/types/credentials/AppStoreConnectApiKey.js +23 -0
  100. package/build/graphql/types/credentials/IosAppCredentials.js +6 -0
  101. package/build/submit/ArchiveSource.js +2 -1
  102. package/build/submit/BaseSubmitter.d.ts +20 -4
  103. package/build/submit/BaseSubmitter.js +34 -1
  104. package/build/submit/android/AndroidSubmitter.d.ts +12 -6
  105. package/build/submit/android/AndroidSubmitter.js +31 -20
  106. package/build/submit/android/ServiceAccountSource.js +2 -2
  107. package/build/submit/context.d.ts +2 -0
  108. package/build/submit/context.js +14 -0
  109. package/build/submit/ios/AppSpecificPasswordSource.d.ts +9 -6
  110. package/build/submit/ios/AppSpecificPasswordSource.js +42 -20
  111. package/build/submit/ios/AscApiKeySource.d.ts +9 -3
  112. package/build/submit/ios/AscApiKeySource.js +10 -10
  113. package/build/submit/ios/CredentialsServiceSource.d.ts +15 -0
  114. package/build/submit/ios/CredentialsServiceSource.js +52 -0
  115. package/build/submit/ios/IosSubmitCommand.d.ts +1 -2
  116. package/build/submit/ios/IosSubmitCommand.js +24 -53
  117. package/build/submit/ios/IosSubmitter.d.ts +20 -7
  118. package/build/submit/ios/IosSubmitter.js +79 -43
  119. package/build/submit/submit.js +13 -4
  120. package/build/submit/utils/errors.js +2 -0
  121. package/build/user/User.js +1 -1
  122. package/oclif.manifest.json +1 -1
  123. package/package.json +6 -6
  124. package/build/build/utils/analytics.d.ts +0 -22
  125. package/build/build/utils/analytics.js +0 -28
@@ -0,0 +1,3 @@
1
+ export declare const KeystoreGenerationUrlMutation: {
2
+ createKeystoreGenerationUrlAsync(): Promise<string>;
3
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KeystoreGenerationUrlMutation = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_tag_1 = (0, tslib_1.__importDefault)(require("graphql-tag"));
6
+ const client_1 = require("../client");
7
+ exports.KeystoreGenerationUrlMutation = {
8
+ async createKeystoreGenerationUrlAsync() {
9
+ const data = await (0, client_1.withErrorHandlingAsync)(client_1.graphqlClient
10
+ .mutation((0, graphql_tag_1.default) `
11
+ mutation CreateKeystoreGenerationUrlMutation {
12
+ keystoreGenerationUrl {
13
+ createKeystoreGenerationUrl {
14
+ id
15
+ url
16
+ }
17
+ }
18
+ }
19
+ `)
20
+ .toPromise());
21
+ return data.keystoreGenerationUrl.createKeystoreGenerationUrl.url;
22
+ },
23
+ };
@@ -20,12 +20,7 @@ exports.BuildFragmentNode = (0, graphql_tag_1.default) `
20
20
  initiatingActor {
21
21
  __typename
22
22
  id
23
- ... on User {
24
- username
25
- }
26
- ... on Robot {
27
- firstName
28
- }
23
+ displayName
29
24
  }
30
25
  project {
31
26
  __typename
@@ -0,0 +1 @@
1
+ export declare const AppStoreConnectApiKeyFragmentNode: import("graphql").DocumentNode;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppStoreConnectApiKeyFragmentNode = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_1 = require("graphql");
6
+ const graphql_tag_1 = (0, tslib_1.__importDefault)(require("graphql-tag"));
7
+ const AppleTeam_1 = require("./AppleTeam");
8
+ exports.AppStoreConnectApiKeyFragmentNode = (0, graphql_tag_1.default) `
9
+ fragment AppStoreConnectApiKeyFragment on AppStoreConnectApiKey {
10
+ id
11
+ appleTeam {
12
+ id
13
+ ...AppleTeamFragment
14
+ }
15
+ issuerIdentifier
16
+ keyIdentifier
17
+ name
18
+ roles
19
+ createdAt
20
+ updatedAt
21
+ }
22
+ ${(0, graphql_1.print)(AppleTeam_1.AppleTeamFragmentNode)}
23
+ `;
@@ -4,6 +4,7 @@ exports.CommonIosAppCredentialsFragmentNode = exports.CommonIosAppCredentialsWit
4
4
  const tslib_1 = require("tslib");
5
5
  const graphql_tag_1 = (0, tslib_1.__importDefault)(require("graphql-tag"));
6
6
  const App_1 = require("../App");
7
+ const AppStoreConnectApiKey_1 = require("./AppStoreConnectApiKey");
7
8
  const AppleAppIdentifier_1 = require("./AppleAppIdentifier");
8
9
  const ApplePushKey_1 = require("./ApplePushKey");
9
10
  const AppleTeam_1 = require("./AppleTeam");
@@ -27,11 +28,16 @@ exports.CommonIosAppCredentialsWithoutBuildCredentialsFragmentNode = (0, graphql
27
28
  id
28
29
  ...ApplePushKeyFragment
29
30
  }
31
+ appStoreConnectApiKeyForSubmissions {
32
+ id
33
+ ...AppStoreConnectApiKeyFragment
34
+ }
30
35
  }
31
36
  ${App_1.AppFragmentNode}
32
37
  ${AppleTeam_1.AppleTeamFragmentNode}
33
38
  ${AppleAppIdentifier_1.AppleAppIdentifierFragmentNode}
34
39
  ${ApplePushKey_1.ApplePushKeyFragmentNode}
40
+ ${AppStoreConnectApiKey_1.AppStoreConnectApiKeyFragmentNode}
35
41
  `;
36
42
  exports.CommonIosAppCredentialsFragmentNode = (0, graphql_tag_1.default) `
37
43
  fragment CommonIosAppCredentialsFragment on IosAppCredentials {
@@ -188,7 +188,7 @@ async function handleBuildListSourceAsync(source) {
188
188
  }
189
189
  }
190
190
  function formatBuildChoice(build, expiryDate) {
191
- const { id, platform, updatedAt, appVersion, sdkVersion, runtimeVersion, buildProfile, appBuildVersion, releaseChannel, } = build;
191
+ const { id, platform, updatedAt, appVersion, sdkVersion, runtimeVersion, buildProfile, appBuildVersion, releaseChannel, initiatingActor, } = build;
192
192
  const formatValue = (field) => field ? chalk_1.default.bold(field) : chalk_1.default.dim('Unknown');
193
193
  const buildDate = new Date(updatedAt);
194
194
  const maybeRuntimeVersion = runtimeVersion ? `Runtime: ${formatValue(runtimeVersion)}` : null;
@@ -204,6 +204,7 @@ function formatBuildChoice(build, expiryDate) {
204
204
  .filter(it => it != null)
205
205
  .join(', '),
206
206
  `\tProfile: ${formatValue(buildProfile)}, Release channel: ${formatValue(releaseChannel)}`,
207
+ `\tAuthored by: ${formatValue(initiatingActor === null || initiatingActor === void 0 ? void 0 : initiatingActor.displayName)}`,
207
208
  ].join('\n');
208
209
  return {
209
210
  title,
@@ -1,4 +1,5 @@
1
1
  import { Platform } from '@expo/eas-build-job';
2
+ import { Event } from '../analytics/events';
2
3
  import { AndroidSubmissionConfigInput, IosSubmissionConfigInput, SubmissionFragment } from '../graphql/generated';
3
4
  import { SubmissionContext } from './context';
4
5
  export interface SubmissionInput<P extends Platform> {
@@ -6,11 +7,26 @@ export interface SubmissionInput<P extends Platform> {
6
7
  submissionConfig: P extends Platform.ANDROID ? AndroidSubmissionConfigInput : IosSubmissionConfigInput;
7
8
  buildId?: string;
8
9
  }
9
- export default abstract class BaseSubmitter<P extends Platform, SubmissionOptions> {
10
+ interface AnalyticEvents {
11
+ attemptEvent: Event;
12
+ successEvent: Event;
13
+ failureEvent: Event;
14
+ }
15
+ export default abstract class BaseSubmitter<P extends Platform, ResolvedSourceOptions, SubmissionOptions> {
10
16
  protected ctx: SubmissionContext<P>;
11
17
  protected options: SubmissionOptions;
12
- constructor(ctx: SubmissionContext<P>, options: SubmissionOptions);
13
- abstract submitAsync(): Promise<SubmissionFragment>;
14
- protected createSubmissionAsync(submissionInput: SubmissionInput<P>): Promise<SubmissionFragment>;
18
+ protected sourceOptionResolver: {
19
+ [K in keyof ResolvedSourceOptions]: () => Promise<ResolvedSourceOptions[K]>;
20
+ };
21
+ protected sourceOptionAnalytics: Record<keyof ResolvedSourceOptions, AnalyticEvents>;
22
+ constructor(ctx: SubmissionContext<P>, options: SubmissionOptions, sourceOptionResolver: {
23
+ [K in keyof ResolvedSourceOptions]: () => Promise<ResolvedSourceOptions[K]>;
24
+ }, sourceOptionAnalytics: Record<keyof ResolvedSourceOptions, AnalyticEvents>);
25
+ private getSourceOptionsAsync;
26
+ submitAsync(): Promise<SubmissionFragment>;
27
+ abstract createSubmissionInputAsync(resolvedOptions: ResolvedSourceOptions): Promise<SubmissionInput<P>>;
28
+ private createSubmissionAsync;
29
+ private createSubmissionWithAnalyticsAsync;
15
30
  protected abstract createPlatformSubmissionAsync(input: SubmissionInput<P>): Promise<SubmissionFragment>;
16
31
  }
32
+ export {};
@@ -1,14 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const common_1 = require("../analytics/common");
5
+ const events_1 = require("../analytics/events");
4
6
  const AppPlatform_1 = require("../graphql/types/AppPlatform");
5
7
  const log_1 = (0, tslib_1.__importDefault)(require("../log"));
6
8
  const ora_1 = require("../ora");
7
9
  const platform_1 = require("../platform");
8
10
  class BaseSubmitter {
9
- constructor(ctx, options) {
11
+ constructor(ctx, options, sourceOptionResolver, sourceOptionAnalytics) {
10
12
  this.ctx = ctx;
11
13
  this.options = options;
14
+ this.sourceOptionResolver = sourceOptionResolver;
15
+ this.sourceOptionAnalytics = sourceOptionAnalytics;
16
+ }
17
+ async getSourceOptionsAsync() {
18
+ const resolvedSourceOptions = {};
19
+ // Do not perform this in parallel as some of these require user interaction
20
+ for (const key in this.sourceOptionResolver) {
21
+ const sourceOptionKey = key;
22
+ const sourceOptionAnalytics = this.sourceOptionAnalytics[sourceOptionKey];
23
+ const sourceOption = await (0, common_1.withAnalyticsAsync)(async () => await this.sourceOptionResolver[sourceOptionKey](), {
24
+ attemptEvent: sourceOptionAnalytics.attemptEvent,
25
+ successEvent: sourceOptionAnalytics.successEvent,
26
+ failureEvent: sourceOptionAnalytics.failureEvent,
27
+ trackingCtx: this.ctx.trackingCtx,
28
+ });
29
+ resolvedSourceOptions[sourceOptionKey] = sourceOption;
30
+ }
31
+ return resolvedSourceOptions;
32
+ }
33
+ async submitAsync() {
34
+ const resolvedSourceOptions = await this.getSourceOptionsAsync();
35
+ const input = await this.createSubmissionInputAsync(resolvedSourceOptions);
36
+ return await this.createSubmissionWithAnalyticsAsync(input);
12
37
  }
13
38
  async createSubmissionAsync(submissionInput) {
14
39
  log_1.default.addNewLineIfNone();
@@ -24,5 +49,13 @@ class BaseSubmitter {
24
49
  throw err;
25
50
  }
26
51
  }
52
+ async createSubmissionWithAnalyticsAsync(submissionInput) {
53
+ return await (0, common_1.withAnalyticsAsync)(async () => this.createSubmissionAsync(submissionInput), {
54
+ attemptEvent: events_1.SubmissionEvent.SUBMIT_REQUEST_ATTEMPT,
55
+ successEvent: events_1.SubmissionEvent.SUBMIT_REQUEST_SUCCESS,
56
+ failureEvent: events_1.SubmissionEvent.SUBMIT_REQUEST_FAIL,
57
+ trackingCtx: this.ctx.trackingCtx,
58
+ });
59
+ }
27
60
  }
28
61
  exports.default = BaseSubmitter;
@@ -1,19 +1,25 @@
1
1
  import { Platform } from '@expo/eas-build-job';
2
2
  import { AndroidSubmissionConfigInput, SubmissionFragment } from '../../graphql/generated';
3
- import { ArchiveSource } from '../ArchiveSource';
3
+ import { Archive, ArchiveSource } from '../ArchiveSource';
4
4
  import BaseSubmitter, { SubmissionInput } from '../BaseSubmitter';
5
+ import { SubmissionContext } from '../context';
5
6
  import { AndroidPackageSource } from './AndroidPackageSource';
6
- import { ServiceAccountSource } from './ServiceAccountSource';
7
+ import { ServiceAccountKeyResult, ServiceAccountSource } from './ServiceAccountSource';
7
8
  export interface AndroidSubmissionOptions extends Pick<AndroidSubmissionConfigInput, 'track' | 'releaseStatus' | 'changesNotSentForReview'> {
8
9
  projectId: string;
9
10
  androidPackageSource: AndroidPackageSource;
10
11
  archiveSource: ArchiveSource;
11
12
  serviceAccountSource: ServiceAccountSource;
12
13
  }
13
- export default class AndroidSubmitter extends BaseSubmitter<Platform.ANDROID, AndroidSubmissionOptions> {
14
- submitAsync(): Promise<SubmissionFragment>;
14
+ interface ResolvedSourceOptions {
15
+ archive: Archive;
16
+ serviceAccountKeyResult: ServiceAccountKeyResult;
17
+ }
18
+ export default class AndroidSubmitter extends BaseSubmitter<Platform.ANDROID, ResolvedSourceOptions, AndroidSubmissionOptions> {
19
+ constructor(ctx: SubmissionContext<Platform.ANDROID>, options: AndroidSubmissionOptions);
20
+ createSubmissionInputAsync(resolvedSourceOptions: ResolvedSourceOptions): Promise<SubmissionInput<Platform.ANDROID>>;
15
21
  protected createPlatformSubmissionAsync({ projectId, submissionConfig, buildId, }: SubmissionInput<Platform.ANDROID>): Promise<SubmissionFragment>;
16
- private resolveSourceOptionsAsync;
17
- private formatSubmissionConfigAsync;
22
+ private formatSubmissionConfig;
18
23
  private prepareSummaryData;
19
24
  }
25
+ 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");
@@ -10,16 +11,39 @@ const summary_1 = require("../utils/summary");
10
11
  const AndroidPackageSource_1 = require("./AndroidPackageSource");
11
12
  const ServiceAccountSource_1 = require("./ServiceAccountSource");
12
13
  class AndroidSubmitter extends BaseSubmitter_1.default {
13
- async submitAsync() {
14
+ constructor(ctx, options) {
15
+ const sourceOptionsResolver = {
16
+ // eslint-disable-next-line async-protect/async-suffix
17
+ archive: async () => await (0, ArchiveSource_1.getArchiveAsync)(this.options.archiveSource),
18
+ // eslint-disable-next-line async-protect/async-suffix
19
+ serviceAccountKeyResult: async () => {
20
+ const androidPackage = await (0, AndroidPackageSource_1.getAndroidPackageAsync)(this.options.androidPackageSource);
21
+ return await (0, ServiceAccountSource_1.getServiceAccountKeyResultAsync)(this.ctx, this.options.serviceAccountSource, androidPackage);
22
+ },
23
+ };
24
+ const sourceOptionsAnalytics = {
25
+ archive: {
26
+ attemptEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_ATTEMPT,
27
+ successEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_SUCCESS,
28
+ failureEvent: events_1.SubmissionEvent.GATHER_ARCHIVE_FAIL,
29
+ },
30
+ serviceAccountKeyResult: {
31
+ attemptEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_ATTEMPT,
32
+ successEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_SUCCESS,
33
+ failureEvent: events_1.SubmissionEvent.GATHER_CREDENTIALS_FAIL,
34
+ },
35
+ };
36
+ super(ctx, options, sourceOptionsResolver, sourceOptionsAnalytics);
37
+ }
38
+ async createSubmissionInputAsync(resolvedSourceOptions) {
14
39
  var _a;
15
- const resolvedSourceOptions = await this.resolveSourceOptionsAsync();
16
- const submissionConfig = await this.formatSubmissionConfigAsync(this.options, resolvedSourceOptions);
40
+ const submissionConfig = await this.formatSubmissionConfig(this.options, resolvedSourceOptions);
17
41
  (0, summary_1.printSummary)(this.prepareSummaryData(this.options, resolvedSourceOptions), SummaryHumanReadableKeys);
18
- return await this.createSubmissionAsync({
42
+ return {
19
43
  projectId: this.options.projectId,
20
44
  submissionConfig,
21
45
  buildId: (_a = resolvedSourceOptions.archive.build) === null || _a === void 0 ? void 0 : _a.id,
22
- });
46
+ };
23
47
  }
24
48
  async createPlatformSubmissionAsync({ projectId, submissionConfig, buildId, }) {
25
49
  return await SubmissionMutation_1.SubmissionMutation.createAndroidSubmissionAsync({
@@ -28,20 +52,9 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
28
52
  submittedBuildId: buildId,
29
53
  });
30
54
  }
31
- async resolveSourceOptionsAsync() {
32
- const androidPackage = await (0, AndroidPackageSource_1.getAndroidPackageAsync)(this.options.androidPackageSource);
33
- const archive = await (0, ArchiveSource_1.getArchiveAsync)(this.options.archiveSource);
34
- const serviceAccountKeyResult = await (0, ServiceAccountSource_1.getServiceAccountKeyResultAsync)(this.ctx, this.options.serviceAccountSource, androidPackage);
35
- return {
36
- androidPackage,
37
- archive,
38
- serviceAccountKeyResult,
39
- };
40
- }
41
- async formatSubmissionConfigAsync(options, { archive, androidPackage, serviceAccountKeyResult }) {
55
+ formatSubmissionConfig(options, { archive, serviceAccountKeyResult }) {
42
56
  const { track, releaseStatus, changesNotSentForReview } = options;
43
57
  return {
44
- applicationIdentifier: androidPackage,
45
58
  archiveUrl: archive.url,
46
59
  track,
47
60
  changesNotSentForReview,
@@ -49,12 +62,11 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
49
62
  ...serviceAccountKeyResult.result,
50
63
  };
51
64
  }
52
- prepareSummaryData(options, { archive, androidPackage, serviceAccountKeyResult }) {
65
+ prepareSummaryData(options, { archive, serviceAccountKeyResult }) {
53
66
  const { projectId, track, releaseStatus, changesNotSentForReview } = options;
54
67
  // structuring order affects table rows order
55
68
  return {
56
69
  projectId,
57
- androidPackage,
58
70
  track,
59
71
  changesNotSentForReview: changesNotSentForReview !== null && changesNotSentForReview !== void 0 ? changesNotSentForReview : undefined,
60
72
  releaseStatus: releaseStatus !== null && releaseStatus !== void 0 ? releaseStatus : undefined,
@@ -65,7 +77,6 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
65
77
  }
66
78
  exports.default = AndroidSubmitter;
67
79
  const SummaryHumanReadableKeys = {
68
- androidPackage: 'Android package',
69
80
  archivePath: 'Archive path',
70
81
  archiveUrl: 'Download URL',
71
82
  changesNotSentForReview: 'Changes not sent for a review',
@@ -5,7 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
6
6
  const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
7
7
  const nullthrows_1 = (0, tslib_1.__importDefault)(require("nullthrows"));
8
- const SetupGoogleServiceAccountKey_1 = require("../../credentials/android/actions/SetupGoogleServiceAccountKey");
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
11
  const prompts_1 = require("../../prompts");
@@ -56,7 +56,7 @@ async function getServiceAccountFromCredentialsServiceAsync(ctx, androidApplicat
56
56
  projectName: ctx.projectName,
57
57
  androidApplicationIdentifier,
58
58
  };
59
- const setupGoogleServiceAccountKeyAction = new SetupGoogleServiceAccountKey_1.SetupGoogleServiceAccountKey(appLookupParams);
59
+ const setupGoogleServiceAccountKeyAction = new SetUpGoogleServiceAccountKey_1.SetUpGoogleServiceAccountKey(appLookupParams);
60
60
  const androidAppCredentials = await setupGoogleServiceAccountKeyAction.runAsync(ctx.credentialsCtx);
61
61
  const googleServiceAccountKey = (0, nullthrows_1.default)(androidAppCredentials.googleServiceAccountKeyForSubmissions, 'Credentials Service must provide a valid GoogleServiceAccountKey');
62
62
  return {
@@ -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;
@@ -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) {
12
+ var _a;
9
13
  const { 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,7 @@ async function createSubmissionContextAsync(params) {
23
36
  exp,
24
37
  projectName,
25
38
  user,
39
+ trackingCtx,
26
40
  };
27
41
  }
28
42
  exports.createSubmissionContextAsync = createSubmissionContextAsync;
@@ -1,6 +1,7 @@
1
+ import { Platform } from '@expo/eas-build-job';
2
+ import { SubmissionContext } from '../context';
1
3
  export declare enum AppSpecificPasswordSourceType {
2
- userDefined = 0,
3
- prompt = 1
4
+ userDefined = 0
4
5
  }
5
6
  interface AppSpecificPasswordSourceBase {
6
7
  sourceType: AppSpecificPasswordSourceType;
@@ -9,9 +10,11 @@ interface AppSpecificPasswordUserDefinedSource extends AppSpecificPasswordSource
9
10
  sourceType: AppSpecificPasswordSourceType.userDefined;
10
11
  appSpecificPassword: string;
11
12
  }
12
- interface AppSpecificPasswordPromptSource extends AppSpecificPasswordSourceBase {
13
- sourceType: AppSpecificPasswordSourceType.prompt;
13
+ export interface AppSpecificPasswordCredentials {
14
+ password: string;
15
+ appleIdUsername: string;
14
16
  }
15
- export declare type AppSpecificPasswordSource = AppSpecificPasswordUserDefinedSource | AppSpecificPasswordPromptSource;
16
- export declare function getAppSpecificPasswordAsync(source: AppSpecificPasswordSource): Promise<string>;
17
+ export declare type AppSpecificPasswordSource = AppSpecificPasswordUserDefinedSource;
18
+ export declare function getAppSpecificPasswordLocallyAsync(ctx: SubmissionContext<Platform.IOS>, source: AppSpecificPasswordSource): Promise<AppSpecificPasswordCredentials>;
19
+ export declare function getAppleIdUsernameAsync(ctx: SubmissionContext<Platform.IOS>): Promise<string>;
17
20
  export {};
@@ -1,36 +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
4
  const tslib_1 = require("tslib");
5
- const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
6
- const wrap_ansi_1 = (0, tslib_1.__importDefault)(require("wrap-ansi"));
7
- const log_1 = (0, tslib_1.__importStar)(require("../../log"));
5
+ const getenv_1 = (0, tslib_1.__importDefault)(require("getenv"));
8
6
  const prompts_1 = require("../../prompts");
7
+ const UserSettings_1 = (0, tslib_1.__importDefault)(require("../../user/UserSettings"));
9
8
  var AppSpecificPasswordSourceType;
10
9
  (function (AppSpecificPasswordSourceType) {
11
10
  AppSpecificPasswordSourceType[AppSpecificPasswordSourceType["userDefined"] = 0] = "userDefined";
12
- AppSpecificPasswordSourceType[AppSpecificPasswordSourceType["prompt"] = 1] = "prompt";
13
11
  })(AppSpecificPasswordSourceType = exports.AppSpecificPasswordSourceType || (exports.AppSpecificPasswordSourceType = {}));
14
- async function getAppSpecificPasswordAsync(source) {
12
+ async function getAppSpecificPasswordLocallyAsync(ctx, source) {
15
13
  var _a;
16
14
  if (source.sourceType === AppSpecificPasswordSourceType.userDefined) {
17
- return source.appSpecificPassword;
18
- }
19
- else if (source.sourceType === AppSpecificPasswordSourceType.prompt) {
20
- log_1.default.addNewLineIfNone();
21
- log_1.default.log((0, wrap_ansi_1.default)(`Please enter your Apple app-specific password. You can also provide it by using the ${chalk_1.default.bold('EXPO_APPLE_APP_SPECIFIC_PASSWORD')} environment variable.`, process.stdout.columns || 80));
22
- log_1.default.log((0, log_1.learnMore)('https://expo.fyi/apple-app-specific-password'));
23
- const { appSpecificPassword } = await (0, prompts_1.promptAsync)({
24
- name: 'appSpecificPassword',
25
- message: 'Your Apple app-specific password:',
26
- type: 'password',
27
- validate: (val) => val !== '' || 'Apple app-specific password cannot be empty!',
28
- });
29
- return appSpecificPassword;
15
+ return {
16
+ password: source.appSpecificPassword,
17
+ appleIdUsername: await getAppleIdUsernameAsync(ctx),
18
+ };
30
19
  }
31
20
  else {
32
21
  // exhaustive -- should never happen
33
22
  throw new Error(`Unknown app specific password source type "${(_a = source) === null || _a === void 0 ? void 0 : _a.sourceType}"`);
34
23
  }
35
24
  }
36
- 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,4 +1,6 @@
1
+ import { Platform } from '@expo/eas-build-job';
1
2
  import { AscApiKeyPath, MinimalAscApiKey } from '../../credentials/ios/credentials';
3
+ import { SubmissionContext } from '../context';
2
4
  export declare enum AscApiKeySourceType {
3
5
  path = 0,
4
6
  prompt = 1
@@ -18,11 +20,15 @@ declare type AscApiKeySummary = {
18
20
  source: 'local' | 'EAS servers';
19
21
  path?: string;
20
22
  keyId: string;
23
+ name?: string;
24
+ };
25
+ export declare type AscApiKeyFromExpoServers = {
26
+ ascApiKeyId: string;
21
27
  };
22
28
  export declare type AscApiKeyResult = {
23
- result: MinimalAscApiKey;
29
+ result: MinimalAscApiKey | AscApiKeyFromExpoServers;
24
30
  summary: AscApiKeySummary;
25
31
  };
26
- export declare function getAscApiKeyLocallyAsync(source: AscApiKeySource): Promise<AscApiKeyResult>;
27
- export declare function getAscApiKeyPathAsync(source: AscApiKeySource): Promise<AscApiKeyPath>;
32
+ export declare function getAscApiKeyLocallyAsync(ctx: SubmissionContext<Platform.IOS>, source: AscApiKeySource): Promise<AscApiKeyResult>;
33
+ export declare function getAscApiKeyPathAsync(ctx: SubmissionContext<Platform.IOS>, source: AscApiKeySource): Promise<AscApiKeyPath>;
28
34
  export {};
@@ -11,8 +11,8 @@ var AscApiKeySourceType;
11
11
  AscApiKeySourceType[AscApiKeySourceType["path"] = 0] = "path";
12
12
  AscApiKeySourceType[AscApiKeySourceType["prompt"] = 1] = "prompt";
13
13
  })(AscApiKeySourceType = exports.AscApiKeySourceType || (exports.AscApiKeySourceType = {}));
14
- async function getAscApiKeyLocallyAsync(source) {
15
- const ascApiKeyPath = await getAscApiKeyPathAsync(source);
14
+ async function getAscApiKeyLocallyAsync(ctx, source) {
15
+ const ascApiKeyPath = await getAscApiKeyPathAsync(ctx, source);
16
16
  const { keyP8Path, keyId, issuerId } = ascApiKeyPath;
17
17
  const keyP8 = await fs_extra_1.default.readFile(keyP8Path, 'utf-8');
18
18
  return {
@@ -25,26 +25,26 @@ async function getAscApiKeyLocallyAsync(source) {
25
25
  };
26
26
  }
27
27
  exports.getAscApiKeyLocallyAsync = getAscApiKeyLocallyAsync;
28
- async function getAscApiKeyPathAsync(source) {
28
+ async function getAscApiKeyPathAsync(ctx, source) {
29
29
  switch (source.sourceType) {
30
30
  case AscApiKeySourceType.path:
31
- return await handlePathSourceAsync(source);
31
+ return await handlePathSourceAsync(ctx, source);
32
32
  case AscApiKeySourceType.prompt:
33
- return await handlePromptSourceAsync(source);
33
+ return await handlePromptSourceAsync(ctx, source);
34
34
  }
35
35
  }
36
36
  exports.getAscApiKeyPathAsync = getAscApiKeyPathAsync;
37
- async function handlePathSourceAsync(source) {
37
+ async function handlePathSourceAsync(ctx, source) {
38
38
  const { keyP8Path } = source.path;
39
39
  if (!(await (0, files_1.isExistingFileAsync)(keyP8Path))) {
40
40
  log_1.default.warn(`File ${keyP8Path} doesn't exist.`);
41
- return await getAscApiKeyPathAsync({ sourceType: AscApiKeySourceType.prompt });
41
+ return await getAscApiKeyPathAsync(ctx, { sourceType: AscApiKeySourceType.prompt });
42
42
  }
43
43
  return source.path;
44
44
  }
45
- async function handlePromptSourceAsync(_source) {
46
- const ascApiKeyPath = await (0, AscApiKeyUtils_1.promptForAscApiKeyAsync)();
47
- return await getAscApiKeyPathAsync({
45
+ async function handlePromptSourceAsync(ctx, _source) {
46
+ const ascApiKeyPath = await (0, AscApiKeyUtils_1.promptForAscApiKeyPathAsync)(ctx.credentialsCtx);
47
+ return await getAscApiKeyPathAsync(ctx, {
48
48
  sourceType: AscApiKeySourceType.path,
49
49
  path: ascApiKeyPath,
50
50
  });
@@ -0,0 +1,15 @@
1
+ import { Platform } from '@expo/eas-build-job';
2
+ import { SubmissionContext } from '../context';
3
+ import { AppSpecificPasswordCredentials } from './AppSpecificPasswordSource';
4
+ import { AscApiKeyResult } from './AscApiKeySource';
5
+ /**
6
+ * The Credentials Service will either return an ASC API Key or an App Specific Password
7
+ * When we no longer support the App Specific Password user prompt, refactor this into the AscApiKeySource
8
+ */
9
+ export declare const CREDENTIALS_SERVICE_SOURCE = "CREDENTIALS_SERVICE_SOURCE";
10
+ export declare type CredentialsServiceSource = typeof CREDENTIALS_SERVICE_SOURCE;
11
+ export declare function getFromCredentialsServiceAsync(ctx: SubmissionContext<Platform.IOS>): Promise<{
12
+ appSpecificPassword: AppSpecificPasswordCredentials;
13
+ } | {
14
+ ascApiKeyResult: AscApiKeyResult;
15
+ }>;