eas-cli 0.36.1 → 0.38.2

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 (79) hide show
  1. package/README.md +37 -37
  2. package/build/build/android/build.d.ts +2 -1
  3. package/build/build/android/build.js +11 -9
  4. package/build/build/android/configure.d.ts +3 -2
  5. package/build/build/build.d.ts +0 -2
  6. package/build/build/build.js +1 -2
  7. package/build/build/configure.js +1 -2
  8. package/build/build/context.d.ts +18 -10
  9. package/build/build/context.js +0 -96
  10. package/build/build/createContext.d.ts +13 -0
  11. package/build/build/createContext.js +114 -0
  12. package/build/build/ios/UpdatesModule.js +3 -2
  13. package/build/build/ios/build.d.ts +2 -1
  14. package/build/build/ios/build.js +24 -19
  15. package/build/build/ios/configure.d.ts +3 -2
  16. package/build/build/ios/version.d.ts +1 -1
  17. package/build/build/ios/version.js +11 -4
  18. package/build/build/local.js +15 -4
  19. package/build/build/metadata.d.ts +1 -12
  20. package/build/build/metadata.js +24 -19
  21. package/build/build/utils/devClient.d.ts +1 -2
  22. package/build/build/utils/repository.js +1 -0
  23. package/build/build/validate.d.ts +3 -3
  24. package/build/commandUtils/EasCommand.js +0 -2
  25. package/build/commands/branch/publish.js +38 -2
  26. package/build/commands/build/configure.js +2 -0
  27. package/build/commands/build/index.js +26 -24
  28. package/build/commands/channel/create.d.ts +6 -0
  29. package/build/commands/channel/create.js +2 -0
  30. package/build/commands/config.js +1 -1
  31. package/build/commands/secret/create.js +0 -6
  32. package/build/commands/secret/delete.js +0 -6
  33. package/build/commands/secret/list.js +0 -6
  34. package/build/commands/submit.js +2 -11
  35. package/build/commands/webhook/create.js +1 -2
  36. package/build/commands/webhook/list.js +1 -1
  37. package/build/commands/webhook/update.js +1 -2
  38. package/build/credentials/ios/appstore/bundleIdCapabilities.js +11 -1
  39. package/build/credentials/ios/appstore/entitlements.js +9 -12
  40. package/build/credentials/manager/SelectBuildProfileFromEasJson.js +1 -1
  41. package/build/credentials/manager/SelectIosDistributionTypeGraphqlFromBuildProfile.d.ts +3 -2
  42. package/build/graphql/generated.d.ts +2 -1
  43. package/build/graphql/generated.js +1 -0
  44. package/build/project/android/applicationId.d.ts +6 -0
  45. package/build/project/android/applicationId.js +39 -29
  46. package/build/project/android/gradle.js +3 -2
  47. package/build/project/android/gradleUtils.d.ts +1 -0
  48. package/build/project/ios/bundleIdentifier.d.ts +6 -1
  49. package/build/project/ios/bundleIdentifier.js +29 -18
  50. package/build/project/ios/scheme.d.ts +3 -2
  51. package/build/submit/android/AndroidSubmitCommand.d.ts +1 -2
  52. package/build/submit/android/AndroidSubmitCommand.js +23 -35
  53. package/build/submit/android/AndroidSubmitter.d.ts +0 -2
  54. package/build/submit/android/AndroidSubmitter.js +1 -3
  55. package/build/submit/android/ServiceAccountSource.d.ts +3 -2
  56. package/build/submit/android/ServiceAccountSource.js +16 -4
  57. package/build/submit/context.d.ts +2 -0
  58. package/build/submit/context.js +2 -1
  59. package/build/submit/ios/CredentialsServiceSource.d.ts +6 -3
  60. package/build/submit/ios/CredentialsServiceSource.js +13 -2
  61. package/build/submit/ios/IosSubmitCommand.d.ts +2 -1
  62. package/build/submit/ios/IosSubmitCommand.js +47 -17
  63. package/build/submit/ios/IosSubmitter.js +1 -1
  64. package/build/{build/ios → utils}/plist.d.ts +1 -1
  65. package/build/{build/ios → utils}/plist.js +8 -2
  66. package/build/utils/profiles.d.ts +9 -5
  67. package/build/utils/profiles.js +29 -9
  68. package/build/vcs/clients/git.d.ts +2 -1
  69. package/build/vcs/clients/git.js +87 -6
  70. package/build/vcs/vcs.d.ts +4 -3
  71. package/build/vcs/vcs.js +3 -3
  72. package/build/webhooks/input.d.ts +2 -2
  73. package/build/webhooks/input.js +19 -2
  74. package/oclif.manifest.json +1 -1
  75. package/package.json +13 -14
  76. package/build/project/isEasEnabledForProject.d.ts +0 -8
  77. package/build/project/isEasEnabledForProject.js +0 -33
  78. package/build/submit/android/AndroidPackageSource.d.ts +0 -17
  79. package/build/submit/android/AndroidPackageSource.js +0 -27
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isWildcardBundleIdentifier = exports.warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject = exports.getBundleIdentifierAsync = exports.ensureBundleIdentifierIsDefinedForManagedProjectAsync = void 0;
3
+ exports.isWildcardBundleIdentifier = exports.warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject = exports.isBundleIdentifierValid = exports.getBundleIdentifierAsync = exports.AmbiguousBundleIdentifierError = exports.ensureBundleIdentifierIsDefinedForManagedProjectAsync = exports.INVALID_BUNDLE_IDENTIFIER_MESSAGE = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const config_1 = require("@expo/config");
6
6
  const config_plugins_1 = require("@expo/config-plugins");
@@ -14,7 +14,7 @@ const prompts_1 = require("../../prompts");
14
14
  const actions_1 = require("../../user/actions");
15
15
  const projectUtils_1 = require("../projectUtils");
16
16
  const workflow_1 = require("../workflow");
17
- const INVALID_BUNDLE_IDENTIFIER_MESSAGE = `Invalid format of iOS bundle identifier. Only alphanumeric characters, '.' and '-' are allowed, and each '.' must be followed by a letter.`;
17
+ exports.INVALID_BUNDLE_IDENTIFIER_MESSAGE = `Invalid format of iOS bundle identifier. Only alphanumeric characters, '.' and '-' are allowed, and each '.' must be followed by a letter.`;
18
18
  async function ensureBundleIdentifierIsDefinedForManagedProjectAsync(projectDir, exp) {
19
19
  const workflow = await (0, workflow_1.resolveWorkflowAsync)(projectDir, eas_build_job_1.Platform.IOS);
20
20
  (0, assert_1.default)(workflow === eas_build_job_1.Workflow.MANAGED, 'This function should be called only for managed projects');
@@ -26,16 +26,25 @@ async function ensureBundleIdentifierIsDefinedForManagedProjectAsync(projectDir,
26
26
  }
27
27
  }
28
28
  exports.ensureBundleIdentifierIsDefinedForManagedProjectAsync = ensureBundleIdentifierIsDefinedForManagedProjectAsync;
29
- async function getBundleIdentifierAsync(projectDir, exp, { targetName, buildConfiguration } = {}) {
29
+ class AmbiguousBundleIdentifierError extends Error {
30
+ constructor(message) {
31
+ super(message !== null && message !== void 0 ? message : 'Could not resolve bundle identifier.');
32
+ }
33
+ }
34
+ exports.AmbiguousBundleIdentifierError = AmbiguousBundleIdentifierError;
35
+ async function getBundleIdentifierAsync(projectDir, exp, xcodeContext) {
30
36
  const workflow = await (0, workflow_1.resolveWorkflowAsync)(projectDir, eas_build_job_1.Platform.IOS);
31
37
  if (workflow === eas_build_job_1.Workflow.GENERIC) {
32
38
  warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject(projectDir, exp);
33
- const bundleIdentifier = config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifierFromPbxproj(projectDir, {
34
- targetName,
35
- buildConfiguration,
36
- });
37
- const buildConfigurationDesc = targetName && buildConfiguration
38
- ? ` (target = ${targetName}, build configuration = ${buildConfiguration})`
39
+ const xcodeProject = config_plugins_1.IOSConfig.XcodeUtils.getPbxproj(projectDir);
40
+ const isMultiScheme = config_plugins_1.IOSConfig.BuildScheme.getSchemesFromXcodeproj(projectDir).length > 1;
41
+ const isMultiTarget = config_plugins_1.IOSConfig.Target.getNativeTargets(xcodeProject).filter(([, target]) => config_plugins_1.IOSConfig.Target.isTargetOfType(target, config_plugins_1.IOSConfig.Target.TargetType.APPLICATION)).length > 1;
42
+ if (!xcodeContext && isMultiScheme && isMultiTarget) {
43
+ throw new AmbiguousBundleIdentifierError("Multiple schemes and targets found in Xcode project, bundle identifier couldn't be resolved.");
44
+ }
45
+ const bundleIdentifier = config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifierFromPbxproj(projectDir, xcodeContext !== null && xcodeContext !== void 0 ? xcodeContext : {});
46
+ const buildConfigurationDesc = (xcodeContext === null || xcodeContext === void 0 ? void 0 : xcodeContext.targetName) && (xcodeContext === null || xcodeContext === void 0 ? void 0 : xcodeContext.buildConfiguration)
47
+ ? ` (target = ${xcodeContext.targetName}, build configuration = ${xcodeContext.buildConfiguration})`
39
48
  : '';
40
49
  (0, assert_1.default)(bundleIdentifier, `Could not read bundle identifier from Xcode project${buildConfigurationDesc}.`);
41
50
  if (!isBundleIdentifierValid(bundleIdentifier)) {
@@ -45,17 +54,18 @@ async function getBundleIdentifierAsync(projectDir, exp, { targetName, buildConf
45
54
  }
46
55
  else {
47
56
  // TODO: the following asserts are only temporary until we support app extensions in managed projects
48
- (0, assert_1.default)(!targetName || targetName === config_plugins_1.IOSConfig.XcodeUtils.sanitizedName(exp.name), 'targetName cannot be set to an arbitrary value for managed projects');
49
- (0, assert_1.default)(!buildConfiguration, 'buildConfiguration cannot be passed for managed projects');
50
- const bundleIdentifer = config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifier(exp);
51
- if (!bundleIdentifer || !isBundleIdentifierValid(bundleIdentifer)) {
52
- if (bundleIdentifer) {
53
- log_1.default.warn(INVALID_BUNDLE_IDENTIFIER_MESSAGE);
57
+ (0, assert_1.default)(!(xcodeContext === null || xcodeContext === void 0 ? void 0 : xcodeContext.targetName) ||
58
+ (xcodeContext === null || xcodeContext === void 0 ? void 0 : xcodeContext.targetName) === config_plugins_1.IOSConfig.XcodeUtils.sanitizedName(exp.name), 'targetName cannot be set to an arbitrary value for managed projects.');
59
+ (0, assert_1.default)(!(xcodeContext === null || xcodeContext === void 0 ? void 0 : xcodeContext.buildConfiguration), 'buildConfiguration cannot be passed for managed projects.');
60
+ const bundleIdentifier = config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifier(exp);
61
+ if (!bundleIdentifier || !isBundleIdentifierValid(bundleIdentifier)) {
62
+ if (bundleIdentifier) {
63
+ log_1.default.warn(exports.INVALID_BUNDLE_IDENTIFIER_MESSAGE);
54
64
  }
55
65
  throw new Error(`Specify "ios.bundleIdentifier" in ${(0, projectUtils_1.getProjectConfigDescription)(projectDir)} and run this command again.`);
56
66
  }
57
67
  else {
58
- return bundleIdentifer;
68
+ return bundleIdentifier;
59
69
  }
60
70
  }
61
71
  }
@@ -65,7 +75,7 @@ async function configureBundleIdentifierAsync(projectDir, exp) {
65
75
  const paths = (0, config_1.getConfigFilePaths)(projectDir);
66
76
  // we can't automatically update app.config.js
67
77
  if (paths.dynamicConfigPath) {
68
- throw new Error(`"ios.bundleIdentifier" is not defined in your app.config.js and we can't update this file programatically. Add the value on your own and run this command again.`);
78
+ throw new Error(`"ios.bundleIdentifier" is not defined in your app.config.js and we can't update this file programmatically. Add the value on your own and run this command again.`);
69
79
  }
70
80
  (0, assert_1.default)(paths.staticConfigPath, 'app.json must exist');
71
81
  log_1.default.addNewLineIfNone();
@@ -76,7 +86,7 @@ async function configureBundleIdentifierAsync(projectDir, exp) {
76
86
  type: 'text',
77
87
  message: `What would you like your iOS bundle identifier to be?`,
78
88
  initial: suggestedBundleIdentifier,
79
- validate: value => (isBundleIdentifierValid(value) ? true : INVALID_BUNDLE_IDENTIFIER_MESSAGE),
89
+ validate: value => (isBundleIdentifierValid(value) ? true : exports.INVALID_BUNDLE_IDENTIFIER_MESSAGE),
80
90
  });
81
91
  const rawStaticConfig = (0, appJson_1.readAppJson)(paths.staticConfigPath);
82
92
  rawStaticConfig.expo = {
@@ -90,6 +100,7 @@ async function configureBundleIdentifierAsync(projectDir, exp) {
90
100
  function isBundleIdentifierValid(bundleIdentifier) {
91
101
  return /^[a-zA-Z0-9-.]+$/.test(bundleIdentifier);
92
102
  }
103
+ exports.isBundleIdentifierValid = isBundleIdentifierValid;
93
104
  let warnPrinted = false;
94
105
  function warnIfBundleIdentifierDefinedInAppConfigForBareWorkflowProject(projectDir, exp) {
95
106
  if (config_plugins_1.IOSConfig.BundleIdentifier.getBundleIdentifier(exp) && !warnPrinted) {
@@ -1,5 +1,6 @@
1
1
  import { ExpoConfig } from '@expo/config';
2
- import { IosBuildProfile } from '@expo/eas-json';
2
+ import { Platform } from '@expo/eas-build-job';
3
+ import { BuildProfile } from '@expo/eas-json';
3
4
  export interface XcodeBuildContext {
4
5
  buildScheme: string;
5
6
  buildConfiguration?: string;
@@ -8,7 +9,7 @@ export declare function resolveXcodeBuildContextAsync({ exp, projectDir, nonInte
8
9
  exp: ExpoConfig;
9
10
  projectDir: string;
10
11
  nonInteractive: boolean;
11
- }, buildProfile: IosBuildProfile): Promise<XcodeBuildContext>;
12
+ }, buildProfile: BuildProfile<Platform.IOS>): Promise<XcodeBuildContext>;
12
13
  export declare function selectSchemeAsync({ projectDir, nonInteractive, }: {
13
14
  projectDir: string;
14
15
  nonInteractive?: boolean;
@@ -7,9 +7,8 @@ export default class AndroidSubmitCommand {
7
7
  runAsync(): Promise<SubmissionFragment>;
8
8
  private getAndroidSubmissionOptionsAsync;
9
9
  private maybeGetAndroidPackageFromCurrentProjectAsync;
10
- private resolveAndroidPackageSourceAsync;
11
10
  private resolveTrack;
12
11
  private resolveReleaseStatus;
13
12
  private resolveArchiveSource;
14
- private resolveServiceAccountSource;
13
+ private resolveServiceAccountSourceAsync;
15
14
  }
@@ -7,10 +7,8 @@ const results_1 = require("@expo/results");
7
7
  const generated_1 = require("../../graphql/generated");
8
8
  const log_1 = (0, tslib_1.__importDefault)(require("../../log"));
9
9
  const applicationId_1 = require("../../project/android/applicationId");
10
- const gradleUtils = (0, tslib_1.__importStar)(require("../../project/android/gradleUtils"));
11
10
  const capitalize_1 = (0, tslib_1.__importDefault)(require("../../utils/expodash/capitalize"));
12
11
  const commons_1 = require("../commons");
13
- const AndroidPackageSource_1 = require("./AndroidPackageSource");
14
12
  const AndroidSubmitter_1 = (0, tslib_1.__importDefault)(require("./AndroidSubmitter"));
15
13
  const ServiceAccountSource_1 = require("./ServiceAccountSource");
16
14
  class AndroidSubmitCommand {
@@ -24,18 +22,11 @@ class AndroidSubmitCommand {
24
22
  return await submitter.submitAsync();
25
23
  }
26
24
  async getAndroidSubmissionOptionsAsync() {
27
- const androidPackageSource = await this.resolveAndroidPackageSourceAsync();
28
25
  const track = this.resolveTrack();
29
26
  const releaseStatus = this.resolveReleaseStatus();
30
27
  const archiveSource = this.resolveArchiveSource();
31
- const serviceAccountSource = this.resolveServiceAccountSource();
32
- const errored = [
33
- androidPackageSource,
34
- track,
35
- releaseStatus,
36
- archiveSource,
37
- serviceAccountSource,
38
- ].filter(r => !r.ok);
28
+ const serviceAccountSource = await this.resolveServiceAccountSourceAsync();
29
+ const errored = [track, releaseStatus, archiveSource, serviceAccountSource].filter(r => !r.ok);
39
30
  if (errored.length > 0) {
40
31
  const message = errored.map(err => { var _a; return (_a = err.reason) === null || _a === void 0 ? void 0 : _a.message; }).join('\n');
41
32
  log_1.default.error(message);
@@ -43,7 +34,6 @@ class AndroidSubmitCommand {
43
34
  }
44
35
  return {
45
36
  projectId: this.ctx.projectId,
46
- androidPackageSource: androidPackageSource.enforceValue(),
47
37
  track: track.enforceValue(),
48
38
  releaseStatus: releaseStatus.enforceValue(),
49
39
  archiveSource: archiveSource.enforceValue(),
@@ -53,29 +43,14 @@ class AndroidSubmitCommand {
53
43
  }
54
44
  async maybeGetAndroidPackageFromCurrentProjectAsync() {
55
45
  try {
56
- return await (0, applicationId_1.getApplicationIdAsync)(this.ctx.projectDir, this.ctx.exp, {
57
- moduleName: gradleUtils.DEFAULT_MODULE_NAME,
58
- });
46
+ return (0, results_1.result)(await (0, applicationId_1.getApplicationIdAsync)(this.ctx.projectDir, this.ctx.exp));
59
47
  }
60
- catch {
61
- return undefined;
62
- }
63
- }
64
- async resolveAndroidPackageSourceAsync() {
65
- const androidPackage = await this.maybeGetAndroidPackageFromCurrentProjectAsync();
66
- if (androidPackage) {
67
- return (0, results_1.result)({
68
- sourceType: AndroidPackageSource_1.AndroidPackageSourceType.userDefined,
69
- androidPackage,
70
- });
71
- }
72
- else if (this.ctx.nonInteractive) {
73
- return (0, results_1.result)(new Error("Couldn't resolve the Android package."));
74
- }
75
- else {
76
- return (0, results_1.result)({
77
- sourceType: AndroidPackageSource_1.AndroidPackageSourceType.prompt,
78
- });
48
+ catch (error) {
49
+ if (error instanceof applicationId_1.AmbiguousApplicationIdError) {
50
+ log_1.default.warn('"applicationId" is ambiguous, specify it via "applicationId" field in the submit profile in the eas.json.');
51
+ return (0, results_1.result)(null);
52
+ }
53
+ return (0, results_1.result)(new Error(`Failed to resolve applicationId in Android project: ${error.message}.`));
79
54
  }
80
55
  }
81
56
  resolveTrack() {
@@ -112,7 +87,8 @@ class AndroidSubmitCommand {
112
87
  return (0, results_1.result)(err);
113
88
  }
114
89
  }
115
- resolveServiceAccountSource() {
90
+ async resolveServiceAccountSourceAsync() {
91
+ var _a;
116
92
  const { serviceAccountKeyPath } = this.ctx.profile;
117
93
  if (serviceAccountKeyPath) {
118
94
  return (0, results_1.result)({
@@ -120,8 +96,20 @@ class AndroidSubmitCommand {
120
96
  path: serviceAccountKeyPath,
121
97
  });
122
98
  }
99
+ let androidApplicationIdentifier = (_a = this.ctx.applicationIdentifierOverride) !== null && _a !== void 0 ? _a : this.ctx.profile.applicationId;
100
+ if (!androidApplicationIdentifier) {
101
+ const androidApplicationIdentifierResult = await this.maybeGetAndroidPackageFromCurrentProjectAsync();
102
+ if (!androidApplicationIdentifierResult.ok) {
103
+ return (0, results_1.result)(androidApplicationIdentifierResult.reason);
104
+ }
105
+ const androidApplicationIdentifierValue = androidApplicationIdentifierResult.enforceValue();
106
+ if (androidApplicationIdentifierValue) {
107
+ androidApplicationIdentifier = androidApplicationIdentifierValue;
108
+ }
109
+ }
123
110
  return (0, results_1.result)({
124
111
  sourceType: ServiceAccountSource_1.ServiceAccountSourceType.credentialsService,
112
+ androidApplicationIdentifier,
125
113
  });
126
114
  }
127
115
  }
@@ -3,11 +3,9 @@ import { AndroidSubmissionConfigInput, SubmissionFragment } from '../../graphql/
3
3
  import { Archive, ArchiveSource } from '../ArchiveSource';
4
4
  import BaseSubmitter, { SubmissionInput } from '../BaseSubmitter';
5
5
  import { SubmissionContext } from '../context';
6
- import { AndroidPackageSource } from './AndroidPackageSource';
7
6
  import { ServiceAccountKeyResult, ServiceAccountSource } from './ServiceAccountSource';
8
7
  export interface AndroidSubmissionOptions extends Pick<AndroidSubmissionConfigInput, 'track' | 'releaseStatus' | 'changesNotSentForReview'> {
9
8
  projectId: string;
10
- androidPackageSource: AndroidPackageSource;
11
9
  archiveSource: ArchiveSource;
12
10
  serviceAccountSource: ServiceAccountSource;
13
11
  }
@@ -8,7 +8,6 @@ const formatFields_1 = (0, tslib_1.__importDefault)(require("../../utils/formatF
8
8
  const ArchiveSource_1 = require("../ArchiveSource");
9
9
  const BaseSubmitter_1 = (0, tslib_1.__importDefault)(require("../BaseSubmitter"));
10
10
  const summary_1 = require("../utils/summary");
11
- const AndroidPackageSource_1 = require("./AndroidPackageSource");
12
11
  const ServiceAccountSource_1 = require("./ServiceAccountSource");
13
12
  class AndroidSubmitter extends BaseSubmitter_1.default {
14
13
  constructor(ctx, options) {
@@ -17,8 +16,7 @@ class AndroidSubmitter extends BaseSubmitter_1.default {
17
16
  archive: async () => await (0, ArchiveSource_1.getArchiveAsync)(this.options.archiveSource),
18
17
  // eslint-disable-next-line async-protect/async-suffix
19
18
  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);
19
+ return await (0, ServiceAccountSource_1.getServiceAccountKeyResultAsync)(this.ctx, this.options.serviceAccountSource);
22
20
  },
23
21
  };
24
22
  const sourceOptionsAnalytics = {
@@ -17,6 +17,7 @@ interface ServiceAccountPromptSource extends ServiceAccountSourceBase {
17
17
  }
18
18
  export interface ServiceAccountCredentialsServiceSource extends ServiceAccountSourceBase {
19
19
  sourceType: ServiceAccountSourceType.credentialsService;
20
+ androidApplicationIdentifier?: string;
20
21
  }
21
22
  export declare type ServiceAccountKeyResult = {
22
23
  result: ServiceAccountKeyFile | ServiceAccountKeyFromExpoServers;
@@ -34,7 +35,7 @@ declare type ServiceAccountKeyFromExpoServers = {
34
35
  googleServiceAccountKeyId: string;
35
36
  };
36
37
  export declare type ServiceAccountSource = ServiceAccountPathSource | ServiceAccountPromptSource | ServiceAccountCredentialsServiceSource;
37
- export declare function getServiceAccountKeyResultAsync(ctx: SubmissionContext<Platform.ANDROID>, source: ServiceAccountSource, androidApplicationIdentifier: string): Promise<ServiceAccountKeyResult>;
38
+ export declare function getServiceAccountKeyResultAsync(ctx: SubmissionContext<Platform.ANDROID>, source: ServiceAccountSource): Promise<ServiceAccountKeyResult>;
38
39
  export declare function getServiceAccountKeyPathAsync(source: ServiceAccountSource): Promise<string>;
39
- export declare function getServiceAccountFromCredentialsServiceAsync(ctx: SubmissionContext<Platform.ANDROID>, androidApplicationIdentifier: string): Promise<ServiceAccountKeyResult>;
40
+ export declare function getServiceAccountFromCredentialsServiceAsync(ctx: SubmissionContext<Platform.ANDROID>, source: ServiceAccountCredentialsServiceSource): Promise<ServiceAccountKeyResult>;
40
41
  export {};
@@ -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');
@@ -17,6 +17,7 @@ export interface SubmissionContext<T extends Platform> {
17
17
  projectId: string;
18
18
  projectName: string;
19
19
  user: Actor;
20
+ applicationIdentifierOverride?: string;
20
21
  }
21
22
  export interface SubmitArchiveFlags {
22
23
  latest?: boolean;
@@ -33,4 +34,5 @@ export declare function createSubmissionContextAsync<T extends Platform>(params:
33
34
  profile: SubmitProfile<T>;
34
35
  projectDir: string;
35
36
  projectId: string;
37
+ applicationIdentifier?: string;
36
38
  }): Promise<SubmissionContext<T>>;
@@ -10,7 +10,7 @@ const Account_1 = require("../user/Account");
10
10
  const actions_1 = require("../user/actions");
11
11
  async function createSubmissionContextAsync(params) {
12
12
  var _a;
13
- const { projectDir, nonInteractive } = params;
13
+ const { applicationIdentifier, projectDir, nonInteractive } = params;
14
14
  const exp = (0, expoConfig_1.getExpoConfig)(projectDir, { env: params.env });
15
15
  const { env, ...rest } = params;
16
16
  const user = await (0, actions_1.ensureLoggedInAsync)();
@@ -37,6 +37,7 @@ async function createSubmissionContextAsync(params) {
37
37
  projectName,
38
38
  user,
39
39
  trackingCtx,
40
+ applicationIdentifierOverride: applicationIdentifier,
40
41
  };
41
42
  }
42
43
  exports.createSubmissionContextAsync = createSubmissionContextAsync;
@@ -6,9 +6,12 @@ import { AscApiKeyResult } from './AscApiKeySource';
6
6
  * The Credentials Service will either return an ASC API Key or an App Specific Password
7
7
  * When we no longer support the App Specific Password user prompt, refactor this into the AscApiKeySource
8
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<{
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<{
12
15
  appSpecificPassword: AppSpecificPasswordCredentials;
13
16
  } | {
14
17
  ascApiKeyResult: AscApiKeyResult;
@@ -6,6 +6,7 @@ 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");
10
11
  const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
11
12
  /**
@@ -13,8 +14,18 @@ const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
13
14
  * When we no longer support the App Specific Password user prompt, refactor this into the AscApiKeySource
14
15
  */
15
16
  exports.CREDENTIALS_SERVICE_SOURCE = 'CREDENTIALS_SERVICE_SOURCE';
16
- async function getFromCredentialsServiceAsync(ctx) {
17
- 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());
18
29
  log_1.default.log(`Looking up credentials configuration for ${bundleIdentifier}...`);
19
30
  const appLookupParams = {
20
31
  account: (0, nullthrows_1.default)((0, Account_1.findAccountByName)(ctx.user.accounts, ctx.accountName), `You do not have access to account: ${ctx.accountName}`),
@@ -5,8 +5,9 @@ export default class IosSubmitCommand {
5
5
  private ctx;
6
6
  constructor(ctx: SubmissionContext<Platform.IOS>);
7
7
  runAsync(): Promise<SubmissionFragment>;
8
- private resolveCredentialSubmissionOptions;
9
8
  private resolveSubmissionOptionsAsync;
9
+ private maybeGetIosBundleIdentifierAsync;
10
+ private resolveCredentialSubmissionOptionsAsync;
10
11
  private resolveAppSpecificPasswordSource;
11
12
  private resolveAscApiKeySource;
12
13
  private resolveArchiveSource;
@@ -8,6 +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 bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
11
12
  const commons_1 = require("../commons");
12
13
  const AppProduce_1 = require("./AppProduce");
13
14
  const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
@@ -24,25 +25,9 @@ class IosSubmitCommand {
24
25
  const submitter = new IosSubmitter_1.default(this.ctx, options);
25
26
  return await submitter.submitAsync();
26
27
  }
27
- resolveCredentialSubmissionOptions() {
28
- const ascApiKeySource = this.resolveAscApiKeySource();
29
- const shouldSkipAscApiKeySource = !ascApiKeySource.ok && ascApiKeySource.enforceError() instanceof errors_1.MissingCredentialsError;
30
- if (!shouldSkipAscApiKeySource) {
31
- return { ascApiKeySource };
32
- }
33
- const appSpecificPasswordSource = this.resolveAppSpecificPasswordSource();
34
- const shouldSkipAppSpecificPasswordSource = !appSpecificPasswordSource.ok &&
35
- appSpecificPasswordSource.enforceError() instanceof errors_1.MissingCredentialsError;
36
- if (!shouldSkipAppSpecificPasswordSource) {
37
- return { appSpecificPasswordSource: this.resolveAppSpecificPasswordSource() };
38
- }
39
- return {
40
- credentialsServiceSource: (0, results_1.result)(CredentialsServiceSource_1.CREDENTIALS_SERVICE_SOURCE),
41
- };
42
- }
43
28
  async resolveSubmissionOptionsAsync() {
44
29
  const archiveSource = this.resolveArchiveSource();
45
- const credentialsSource = this.resolveCredentialSubmissionOptions();
30
+ const credentialsSource = await this.resolveCredentialSubmissionOptionsAsync();
46
31
  const maybeAppSpecificPasswordSource = 'appSpecificPasswordSource' in credentialsSource
47
32
  ? credentialsSource.appSpecificPasswordSource
48
33
  : null;
@@ -84,6 +69,51 @@ class IosSubmitCommand {
84
69
  : null),
85
70
  };
86
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
+ }
87
117
  resolveAppSpecificPasswordSource() {
88
118
  const envAppSpecificPassword = getenv_1.default.string('EXPO_APPLE_APP_SPECIFIC_PASSWORD', '');
89
119
  if (envAppSpecificPassword) {
@@ -25,7 +25,7 @@ class IosSubmitter extends BaseSubmitter_1.default {
25
25
  ? await (0, AscApiKeySource_1.getAscApiKeyLocallyAsync)(this.ctx, this.options.ascApiKeySource)
26
26
  : null;
27
27
  const maybeAscOrAspFromCredentialsService = this.options.credentialsServiceSource
28
- ? await (0, CredentialsServiceSource_1.getFromCredentialsServiceAsync)(this.ctx)
28
+ ? await (0, CredentialsServiceSource_1.getFromCredentialsServiceAsync)(this.ctx, this.options.credentialsServiceSource)
29
29
  : null;
30
30
  return {
31
31
  ...(maybeAppSpecificPassword ? { appSpecificPassword: maybeAppSpecificPassword } : null),
@@ -1,3 +1,3 @@
1
1
  import { IOSConfig } from '@expo/config-plugins';
2
- export declare function readPlistAsync(plistPath: string): Promise<object>;
2
+ export declare function readPlistAsync(plistPath: string): Promise<object | null>;
3
3
  export declare function writePlistAsync(plistPath: string, plistObject: IOSConfig.ExpoPlist | IOSConfig.InfoPlist): Promise<void>;
@@ -8,10 +8,16 @@ const path_1 = (0, tslib_1.__importDefault)(require("path"));
8
8
  async function readPlistAsync(plistPath) {
9
9
  if (await fs_extra_1.default.pathExists(plistPath)) {
10
10
  const expoPlistContent = await fs_extra_1.default.readFile(plistPath, 'utf8');
11
- return plist_1.default.parse(expoPlistContent);
11
+ try {
12
+ return plist_1.default.parse(expoPlistContent);
13
+ }
14
+ catch (err) {
15
+ err.message = `Failed to parse ${plistPath}. ${err.message}`;
16
+ throw err;
17
+ }
12
18
  }
13
19
  else {
14
- return {};
20
+ return null;
15
21
  }
16
22
  }
17
23
  exports.readPlistAsync = readPlistAsync;
@@ -1,11 +1,15 @@
1
1
  import { Platform } from '@expo/eas-build-job';
2
- export declare type ProfileData<T> = {
3
- profile: T;
2
+ import { BuildProfile, ProfileType, SubmitProfile } from '@expo/eas-json';
3
+ declare type EasProfile<T extends ProfileType> = T extends 'build' ? BuildProfile<Platform> : SubmitProfile<Platform>;
4
+ export declare type ProfileData<T extends ProfileType> = {
5
+ profile: EasProfile<T>;
4
6
  platform: Platform;
5
7
  profileName: string;
6
8
  };
7
- export declare function getProfilesAsync<T>({ platforms, profileName: profileNameArg, readProfileAsync, }: {
9
+ export declare function getProfilesAsync<T extends ProfileType>({ projectDir, platforms, profileName: profileNameArg, type, }: {
10
+ projectDir: string;
8
11
  platforms: Platform[];
9
- profileName?: string | null;
10
- readProfileAsync: (platform: Platform, profileName: string) => Promise<T>;
12
+ profileName?: string;
13
+ type: T;
11
14
  }): Promise<ProfileData<T>[]>;
15
+ export {};