eas-cli 14.5.0 → 14.6.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 (43) hide show
  1. package/README.md +126 -72
  2. package/build/build/android/graphql.js +2 -0
  3. package/build/build/android/prepareJob.js +1 -0
  4. package/build/build/android/version.d.ts +1 -0
  5. package/build/build/android/version.js +5 -1
  6. package/build/build/configure.d.ts +11 -0
  7. package/build/build/configure.js +46 -1
  8. package/build/build/evaluateConfigWithEnvVarsAsync.js +2 -4
  9. package/build/build/ios/build.js +2 -0
  10. package/build/build/ios/graphql.js +2 -0
  11. package/build/build/ios/prepareJob.js +1 -0
  12. package/build/build/ios/version.js +4 -1
  13. package/build/build/local.js +1 -1
  14. package/build/build/metadata.js +0 -1
  15. package/build/build/runBuildAndSubmit.d.ts +12 -1
  16. package/build/build/runBuildAndSubmit.js +16 -13
  17. package/build/build/utils/environment.d.ts +4 -0
  18. package/build/build/utils/environment.js +20 -0
  19. package/build/commands/build/dev.d.ts +23 -0
  20. package/build/commands/build/dev.js +225 -0
  21. package/build/commands/build/index.js +9 -1
  22. package/build/commands/build/inspect.js +26 -18
  23. package/build/commands/build/internal.js +22 -14
  24. package/build/commands/fingerprint/compare.d.ts +14 -1
  25. package/build/commands/fingerprint/compare.js +192 -53
  26. package/build/commands/project/onboarding.js +23 -14
  27. package/build/credentials/ios/appstore/ensureAppExists.d.ts +22 -1
  28. package/build/credentials/ios/appstore/ensureAppExists.js +73 -2
  29. package/build/credentials/ios/appstore/ensureTestFlightGroup.d.ts +7 -0
  30. package/build/credentials/ios/appstore/ensureTestFlightGroup.js +158 -0
  31. package/build/credentials/ios/appstore/provisioningProfile.js +1 -0
  32. package/build/graphql/generated.d.ts +193 -3
  33. package/build/graphql/generated.js +11 -2
  34. package/build/graphql/queries/FingerprintQuery.d.ts +16 -0
  35. package/build/graphql/queries/FingerprintQuery.js +61 -0
  36. package/build/graphql/types/Fingerprint.js +18 -0
  37. package/build/project/ios/exemptEncryption.d.ts +7 -0
  38. package/build/project/ios/exemptEncryption.js +80 -0
  39. package/build/submit/ios/AppProduce.js +12 -23
  40. package/build/utils/fingerprintCli.d.ts +2 -1
  41. package/build/utils/fingerprintCli.js +11 -3
  42. package/oclif.manifest.json +60 -4
  43. package/package.json +4 -4
@@ -4,6 +4,7 @@ exports.transformJob = void 0;
4
4
  const eas_build_job_1 = require("@expo/eas-build-job");
5
5
  const generated_1 = require("../../graphql/generated");
6
6
  const graphql_1 = require("../graphql");
7
+ const environment_1 = require("../utils/environment");
7
8
  function transformJob(job) {
8
9
  return {
9
10
  type: (0, graphql_1.transformWorkflow)(job.type),
@@ -24,6 +25,7 @@ function transformJob(job) {
24
25
  experimental: job.experimental,
25
26
  mode: (0, graphql_1.transformBuildMode)(job.mode),
26
27
  customBuildConfig: job.customBuildConfig,
28
+ environment: (0, environment_1.buildProfileEnvironmentToEnvironment)(job.environment),
27
29
  loggerLevel: job.loggerLevel
28
30
  ? graphql_1.loggerLevelToGraphQLWorkerLoggerLevel[job.loggerLevel]
29
31
  : undefined,
@@ -72,6 +72,7 @@ async function prepareJobAsync(ctx, jobData) {
72
72
  gradleCommand: buildProfile.gradleCommand,
73
73
  applicationArchivePath: buildProfile.applicationArchivePath ?? buildProfile.artifactPath,
74
74
  buildArtifactPaths: buildProfile.buildArtifactPaths,
75
+ environment: ctx.buildProfile.environment,
75
76
  buildType,
76
77
  username,
77
78
  ...(ctx.android.versionCodeOverride && {
@@ -21,6 +21,7 @@ export declare function bumpVersionInAppJsonAsync({ bumpStrategy, projectDir, ex
21
21
  export declare function maybeResolveVersionsAsync(projectDir: string, exp: ExpoConfig, buildProfile: BuildProfile<Platform.ANDROID>, vcsClient: Client): Promise<{
22
22
  appVersion?: string;
23
23
  appBuildVersion?: string;
24
+ isVersionInitialized?: boolean;
24
25
  }>;
25
26
  export declare function updateNativeVersionsAsync({ projectDir, version, versionCode, }: {
26
27
  projectDir: string;
@@ -73,6 +73,7 @@ async function maybeResolveVersionsAsync(projectDir, exp, buildProfile, vcsClien
73
73
  return {
74
74
  appVersion: (0, gradleUtils_1.resolveConfigValue)(buildGradle, 'versionName', parsedGradleCommand?.flavor) ?? '1.0.0',
75
75
  appBuildVersion: (0, gradleUtils_1.resolveConfigValue)(buildGradle, 'versionCode', parsedGradleCommand?.flavor) ?? '1',
76
+ isVersionInitialized: !(0, gradleUtils_1.resolveConfigValue)(buildGradle, 'versionCode', parsedGradleCommand?.flavor),
76
77
  };
77
78
  }
78
79
  catch {
@@ -121,6 +122,7 @@ async function resolveRemoteVersionCodeAsync(graphqlClient, { projectDir, projec
121
122
  const remoteVersions = await AppVersionQuery_1.AppVersionQuery.latestVersionAsync(graphqlClient, projectId, generated_1.AppPlatform.Android, applicationId);
122
123
  const localVersions = await maybeResolveVersionsAsync(projectDir, exp, buildProfile, vcsClient);
123
124
  let currentBuildVersion;
125
+ let shouldInitializeVersionCode = false;
124
126
  if (remoteVersions?.buildVersion) {
125
127
  currentBuildVersion = remoteVersions.buildVersion;
126
128
  }
@@ -128,6 +130,7 @@ async function resolveRemoteVersionCodeAsync(graphqlClient, { projectDir, projec
128
130
  if (localVersions.appBuildVersion) {
129
131
  log_1.default.log(chalk_1.default.green('No remote versions are configured for this project, versionCode will be initialized based on the value from the local project.'));
130
132
  currentBuildVersion = localVersions.appBuildVersion;
133
+ shouldInitializeVersionCode = localVersions.isVersionInitialized ?? false;
131
134
  }
132
135
  else {
133
136
  log_1.default.error(`Remote versions are not configured and EAS CLI was not able to read the current version from your project. Use "eas build:version:set" to initialize remote versions.`);
@@ -137,7 +140,8 @@ async function resolveRemoteVersionCodeAsync(graphqlClient, { projectDir, projec
137
140
  if (!buildProfile.autoIncrement && remoteVersions?.buildVersion) {
138
141
  return currentBuildVersion;
139
142
  }
140
- else if (!buildProfile.autoIncrement && !remoteVersions?.buildVersion) {
143
+ else if ((!buildProfile.autoIncrement && !remoteVersions?.buildVersion) ||
144
+ shouldInitializeVersionCode) {
141
145
  const spinner = (0, ora_1.ora)(`Initializing versionCode with ${chalk_1.default.bold(currentBuildVersion)}.`).start();
142
146
  try {
143
147
  await AppVersionMutation_1.AppVersionMutation.createAppVersionAsync(graphqlClient, {
@@ -13,4 +13,15 @@ export declare function easJsonExistsAsync(projectDir: string): Promise<boolean>
13
13
  * - true - if eas.json was created by the function
14
14
  */
15
15
  export declare function ensureProjectConfiguredAsync(configureParams: ConfigureParams): Promise<boolean>;
16
+ export declare function doesBuildProfileExistAsync({ projectDir, profileName, }: {
17
+ projectDir: string;
18
+ profileName: string;
19
+ }): Promise<boolean>;
20
+ export declare function createBuildProfileAsync({ projectDir, profileName, profileContents, vcsClient, nonInteractive, }: {
21
+ projectDir: string;
22
+ profileName: string;
23
+ profileContents: Record<string, any>;
24
+ vcsClient: Client;
25
+ nonInteractive: boolean;
26
+ }): Promise<void>;
16
27
  export {};
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureProjectConfiguredAsync = exports.easJsonExistsAsync = void 0;
3
+ exports.createBuildProfileAsync = exports.doesBuildProfileExistAsync = exports.ensureProjectConfiguredAsync = exports.easJsonExistsAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const eas_json_1 = require("@expo/eas-json");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
8
  const repository_1 = require("./utils/repository");
9
9
  const log_1 = tslib_1.__importStar(require("../log"));
10
+ const ora_1 = require("../ora");
10
11
  const easCli_1 = require("../utils/easCli");
11
12
  async function easJsonExistsAsync(projectDir) {
12
13
  return await fs_extra_1.default.pathExists(eas_json_1.EasJsonAccessor.formatEasJsonPath(projectDir));
@@ -37,6 +38,50 @@ async function configureAsync({ projectDir, nonInteractive, vcsClient, }) {
37
38
  });
38
39
  }
39
40
  }
41
+ async function doesBuildProfileExistAsync({ projectDir, profileName, }) {
42
+ try {
43
+ const easJsonAccessor = eas_json_1.EasJsonAccessor.fromProjectPath(projectDir);
44
+ const easJson = await easJsonAccessor.readRawJsonAsync();
45
+ if (!easJson.build?.[profileName]) {
46
+ return false;
47
+ }
48
+ return true;
49
+ }
50
+ catch (error) {
51
+ log_1.default.error(`We were unable to read ${chalk_1.default.bold('eas.json')} contents. Error: ${error}.`);
52
+ throw error;
53
+ }
54
+ }
55
+ exports.doesBuildProfileExistAsync = doesBuildProfileExistAsync;
56
+ async function createBuildProfileAsync({ projectDir, profileName, profileContents, vcsClient, nonInteractive, }) {
57
+ const spinner = (0, ora_1.ora)(`Adding "${profileName}" build profile to ${chalk_1.default.bold('eas.json')}`).start();
58
+ try {
59
+ const easJsonAccessor = eas_json_1.EasJsonAccessor.fromProjectPath(projectDir);
60
+ await easJsonAccessor.readRawJsonAsync();
61
+ easJsonAccessor.patch(easJsonRawObject => {
62
+ return {
63
+ ...easJsonRawObject,
64
+ build: {
65
+ ...easJsonRawObject.build,
66
+ [profileName]: profileContents,
67
+ },
68
+ };
69
+ });
70
+ await easJsonAccessor.writeAsync();
71
+ spinner.succeed(`Successfully added "${profileName}" build profile to ${chalk_1.default.bold('eas.json')}.`);
72
+ if (await vcsClient.isCommitRequiredAsync()) {
73
+ log_1.default.newLine();
74
+ await (0, repository_1.reviewAndCommitChangesAsync)(vcsClient, `Add "${profileName}" build profile to eas.json`, {
75
+ nonInteractive,
76
+ });
77
+ }
78
+ }
79
+ catch (error) {
80
+ spinner.fail(`We were not able to configure "${profileName}" build profile inside of ${chalk_1.default.bold('eas.json')}. Error: ${error}.`);
81
+ throw error;
82
+ }
83
+ }
84
+ exports.createBuildProfileAsync = createBuildProfileAsync;
40
85
  const EAS_JSON_DEFAULT = {
41
86
  cli: {
42
87
  version: `>= ${easCli_1.easCliVersion}`,
@@ -2,12 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.evaluateConfigWithEnvVarsAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const environment_1 = require("./utils/environment");
5
6
  const generated_1 = require("../graphql/generated");
6
7
  const EnvironmentVariablesQuery_1 = require("../graphql/queries/EnvironmentVariablesQuery");
7
8
  const log_1 = tslib_1.__importStar(require("../log"));
8
- function isEnvironment(env) {
9
- return Object.values(generated_1.EnvironmentVariableEnvironment).includes(env);
10
- }
11
9
  async function evaluateConfigWithEnvVarsAsync({ buildProfile, buildProfileName, graphqlClient, getProjectConfig, opts, }) {
12
10
  if (!graphqlClient) {
13
11
  log_1.default.warn('An Expo user account is required to fetch environment variables.');
@@ -28,7 +26,7 @@ exports.evaluateConfigWithEnvVarsAsync = evaluateConfigWithEnvVarsAsync;
28
26
  async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClient, projectId, }) {
29
27
  const environment = buildProfile.environment?.toUpperCase() ??
30
28
  resolveSuggestedEnvironmentForBuildProfileConfiguration(buildProfile);
31
- if (!isEnvironment(environment)) {
29
+ if (!(0, environment_1.isEnvironment)(environment)) {
32
30
  log_1.default.log(`Loaded "env" configuration for the "${buildProfileName}" profile: ${buildProfile.env && Object.keys(buildProfile.env).length > 0
33
31
  ? Object.keys(buildProfile.env).join(', ')
34
32
  : 'no environment variables specified'}. ${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/variables/')}`);
@@ -10,6 +10,7 @@ const syncProjectConfiguration_1 = require("./syncProjectConfiguration");
10
10
  const version_1 = require("./version");
11
11
  const BuildMutation_1 = require("../../graphql/mutations/BuildMutation");
12
12
  const bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
13
+ const exemptEncryption_1 = require("../../project/ios/exemptEncryption");
13
14
  const scheme_1 = require("../../project/ios/scheme");
14
15
  const target_1 = require("../../project/ios/target");
15
16
  const build_1 = require("../build");
@@ -19,6 +20,7 @@ async function createIosContextAsync(ctx) {
19
20
  const { buildProfile, env } = ctx;
20
21
  if (ctx.workflow === eas_build_job_1.Workflow.MANAGED) {
21
22
  await (0, bundleIdentifier_1.ensureBundleIdentifierIsDefinedForManagedProjectAsync)(ctx);
23
+ await (0, exemptEncryption_1.ensureNonExemptEncryptionIsDefinedForManagedProjectAsync)(ctx);
22
24
  }
23
25
  (0, validate_1.checkNodeEnvVariable)(ctx);
24
26
  await (0, validate_1.checkGoogleServicesFileAsync)(ctx);
@@ -4,6 +4,7 @@ exports.transformIosSecrets = exports.transformJob = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
6
6
  const graphql_1 = require("../graphql");
7
+ const environment_1 = require("../utils/environment");
7
8
  function transformJob(job) {
8
9
  return {
9
10
  type: (0, graphql_1.transformWorkflow)(job.type),
@@ -25,6 +26,7 @@ function transformJob(job) {
25
26
  experimental: job.experimental,
26
27
  mode: (0, graphql_1.transformBuildMode)(job.mode),
27
28
  customBuildConfig: job.customBuildConfig,
29
+ environment: (0, environment_1.buildProfileEnvironmentToEnvironment)(job.environment),
28
30
  loggerLevel: job.loggerLevel
29
31
  ? graphql_1.loggerLevelToGraphQLWorkerLoggerLevel[job.loggerLevel]
30
32
  : undefined,
@@ -67,6 +67,7 @@ async function prepareJobAsync(ctx, jobData) {
67
67
  buildConfiguration: buildProfile.buildConfiguration,
68
68
  applicationArchivePath: buildProfile.applicationArchivePath ?? buildProfile.artifactPath,
69
69
  buildArtifactPaths: buildProfile.buildArtifactPaths,
70
+ environment: ctx.buildProfile.environment,
70
71
  username,
71
72
  ...(ctx.ios.buildNumberOverride && {
72
73
  version: {
@@ -209,6 +209,7 @@ async function resolveRemoteBuildNumberAsync(graphqlClient, { projectDir, projec
209
209
  const localBuildNumber = await readBuildNumberAsync(projectDir, exp, applicationTarget.buildSettings ?? {}, vcsClient);
210
210
  const localShortVersion = await readShortVersionAsync(projectDir, exp, applicationTarget.buildSettings ?? {}, vcsClient);
211
211
  let currentBuildVersion;
212
+ let shouldInitializeBuildNumber = false;
212
213
  if (remoteVersions?.buildVersion) {
213
214
  currentBuildVersion = remoteVersions.buildVersion;
214
215
  }
@@ -216,6 +217,7 @@ async function resolveRemoteBuildNumberAsync(graphqlClient, { projectDir, projec
216
217
  if (localBuildNumber) {
217
218
  log_1.default.log(chalk_1.default.green('No remote versions are configured for this project, buildNumber will be initialized based on the value from the local project.'));
218
219
  currentBuildVersion = localBuildNumber;
220
+ shouldInitializeBuildNumber = localBuildNumber === '1';
219
221
  }
220
222
  else {
221
223
  log_1.default.error(`Remote versions are not configured and EAS CLI was not able to read the current version from your project. Use "eas build:version:set" to initialize remote versions.`);
@@ -225,7 +227,8 @@ async function resolveRemoteBuildNumberAsync(graphqlClient, { projectDir, projec
225
227
  if (!buildProfile.autoIncrement && remoteVersions?.buildVersion) {
226
228
  return currentBuildVersion;
227
229
  }
228
- else if (!buildProfile.autoIncrement && !remoteVersions?.buildVersion) {
230
+ else if ((!buildProfile.autoIncrement && !remoteVersions?.buildVersion) ||
231
+ shouldInitializeBuildNumber) {
229
232
  const spinner = (0, ora_1.ora)(`Initializing buildNumber with ${chalk_1.default.bold(currentBuildVersion)}.`).start();
230
233
  try {
231
234
  await AppVersionMutation_1.AppVersionMutation.createAppVersionAsync(graphqlClient, {
@@ -7,7 +7,7 @@ const semver_1 = tslib_1.__importDefault(require("semver"));
7
7
  const log_1 = tslib_1.__importDefault(require("../log"));
8
8
  const ora_1 = require("../ora");
9
9
  const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
10
- const PLUGIN_PACKAGE_VERSION = '1.0.163';
10
+ const PLUGIN_PACKAGE_VERSION = '1.0.168';
11
11
  var LocalBuildMode;
12
12
  (function (LocalBuildMode) {
13
13
  /**
@@ -50,7 +50,6 @@ async function collectMetadataAsync(ctx, runtimeAndFingerprintMetadata) {
50
50
  requiredPackageManager: ctx.requiredPackageManager ?? undefined,
51
51
  selectedImage: ctx.buildProfile.image,
52
52
  customNodeVersion: ctx.buildProfile.node,
53
- environment: ctx.buildProfile.environment,
54
53
  simulator: 'simulator' in ctx.buildProfile && ctx.buildProfile.simulator,
55
54
  };
56
55
  return (0, eas_build_job_1.sanitizeMetadata)(metadata);
@@ -1,3 +1,4 @@
1
+ import { Env } from '@expo/eas-build-job';
1
2
  import { ResourceClass } from '@expo/eas-json';
2
3
  import { LoggerLevel } from '@expo/logger';
3
4
  import { LocalBuildOptions } from './local';
@@ -23,6 +24,16 @@ export interface BuildFlags {
23
24
  freezeCredentials: boolean;
24
25
  repack: boolean;
25
26
  }
26
- export declare function runBuildAndSubmitAsync(graphqlClient: ExpoGraphqlClient, analytics: Analytics, vcsClient: Client, projectDir: string, flags: BuildFlags, actor: Actor, getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn): Promise<{
27
+ export declare function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsClient, projectDir, flags, actor, getDynamicPrivateProjectConfigAsync, downloadSimBuildAutoConfirm, envOverride, }: {
28
+ graphqlClient: ExpoGraphqlClient;
29
+ analytics: Analytics;
30
+ vcsClient: Client;
31
+ projectDir: string;
32
+ flags: BuildFlags;
33
+ actor: Actor;
34
+ getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn;
35
+ downloadSimBuildAutoConfirm?: boolean;
36
+ envOverride?: Env;
37
+ }): Promise<{
27
38
  buildIds: string[];
28
39
  }>;
@@ -42,7 +42,7 @@ const json_1 = require("../utils/json");
42
42
  const profiles_1 = require("../utils/profiles");
43
43
  let metroConfigValidated = false;
44
44
  let sdkVersionChecked = false;
45
- async function runBuildAndSubmitAsync(graphqlClient, analytics, vcsClient, projectDir, flags, actor, getDynamicPrivateProjectConfigAsync) {
45
+ async function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsClient, projectDir, flags, actor, getDynamicPrivateProjectConfigAsync, downloadSimBuildAutoConfirm, envOverride, }) {
46
46
  await vcsClient.ensureRepoExistsAsync();
47
47
  await (0, repository_1.ensureRepoIsCleanAsync)(vcsClient, flags.nonInteractive);
48
48
  await (0, configure_1.ensureProjectConfiguredAsync)({
@@ -98,13 +98,15 @@ async function runBuildAndSubmitAsync(graphqlClient, analytics, vcsClient, proje
98
98
  const buildCtxByPlatform = {};
99
99
  for (const buildProfile of buildProfiles) {
100
100
  const platform = (0, AppPlatform_1.toAppPlatform)(buildProfile.platform);
101
- const { env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
102
- buildProfile: buildProfile.profile,
103
- buildProfileName: buildProfile.profileName,
104
- graphqlClient,
105
- getProjectConfig: getDynamicPrivateProjectConfigAsync,
106
- opts: { env: buildProfile.profile.env },
107
- });
101
+ const { env } = !envOverride
102
+ ? await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
103
+ buildProfile: buildProfile.profile,
104
+ buildProfileName: buildProfile.profileName,
105
+ graphqlClient,
106
+ getProjectConfig: getDynamicPrivateProjectConfigAsync,
107
+ opts: { env: buildProfile.profile.env },
108
+ })
109
+ : { env: envOverride };
108
110
  const { build: maybeBuild, buildCtx } = await prepareAndStartBuildAsync({
109
111
  projectDir,
110
112
  flags,
@@ -190,7 +192,7 @@ async function runBuildAndSubmitAsync(graphqlClient, analytics, vcsClient, proje
190
192
  }
191
193
  const haveAllBuildsFailedOrCanceled = builds.every(build => build?.status &&
192
194
  [generated_1.BuildStatus.Errored, generated_1.BuildStatus.Canceled, generated_1.BuildStatus.PendingCancel].includes(build?.status));
193
- await maybeDownloadAndRunSimulatorBuildsAsync(builds, flags);
195
+ await maybeDownloadAndRunSimulatorBuildsAsync(builds, flags, downloadSimBuildAutoConfirm);
194
196
  if (haveAllBuildsFailedOrCanceled || !flags.autoSubmit) {
195
197
  if (flags.json) {
196
198
  (0, json_1.printJsonOnlyOutput)(builds);
@@ -341,15 +343,16 @@ async function downloadAndRunAsync(build) {
341
343
  const buildPath = await (0, download_1.downloadAndMaybeExtractAppAsync)(build.artifacts.applicationArchiveUrl, build.platform);
342
344
  await (0, run_1.runAsync)(buildPath, build.platform);
343
345
  }
344
- async function maybeDownloadAndRunSimulatorBuildsAsync(builds, flags) {
346
+ async function maybeDownloadAndRunSimulatorBuildsAsync(builds, flags, autoConfirm) {
345
347
  const simBuilds = builds.filter(filter_1.truthy).filter(utils_1.isRunnableOnSimulatorOrEmulator);
346
348
  if (simBuilds.length > 0 && !flags.autoSubmit && !flags.nonInteractive) {
347
349
  for (const simBuild of simBuilds) {
348
350
  if (simBuild.platform === generated_1.AppPlatform.Android || process.platform === 'darwin') {
349
351
  log_1.default.newLine();
350
- const confirm = await (0, prompts_1.confirmAsync)({
351
- message: `Install and run the ${simBuild.platform === generated_1.AppPlatform.Android ? 'Android' : 'iOS'} build on ${simBuild.platform === generated_1.AppPlatform.Android ? 'an emulator' : 'a simulator'}?`,
352
- });
352
+ const confirm = autoConfirm ??
353
+ (await (0, prompts_1.confirmAsync)({
354
+ message: `Install and run the ${simBuild.platform === generated_1.AppPlatform.Android ? 'Android' : 'iOS'} build on ${simBuild.platform === generated_1.AppPlatform.Android ? 'an emulator' : 'a simulator'}?`,
355
+ }));
353
356
  if (confirm) {
354
357
  await downloadAndRunAsync(simBuild);
355
358
  }
@@ -0,0 +1,4 @@
1
+ import { BuildProfile } from '@expo/eas-json';
2
+ import { EnvironmentVariableEnvironment } from '../../graphql/generated';
3
+ export declare function isEnvironment(env: string): env is EnvironmentVariableEnvironment;
4
+ export declare function buildProfileEnvironmentToEnvironment(environment: BuildProfile['environment']): EnvironmentVariableEnvironment | null;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildProfileEnvironmentToEnvironment = exports.isEnvironment = void 0;
4
+ const generated_1 = require("../../graphql/generated");
5
+ const BuildProfileEnvironmentToEnvironment = {
6
+ production: generated_1.EnvironmentVariableEnvironment.Production,
7
+ preview: generated_1.EnvironmentVariableEnvironment.Preview,
8
+ development: generated_1.EnvironmentVariableEnvironment.Development,
9
+ };
10
+ function isEnvironment(env) {
11
+ return Object.values(generated_1.EnvironmentVariableEnvironment).includes(env);
12
+ }
13
+ exports.isEnvironment = isEnvironment;
14
+ function buildProfileEnvironmentToEnvironment(environment) {
15
+ if (!environment) {
16
+ return null;
17
+ }
18
+ return BuildProfileEnvironmentToEnvironment[environment];
19
+ }
20
+ exports.buildProfileEnvironmentToEnvironment = buildProfileEnvironmentToEnvironment;
@@ -0,0 +1,23 @@
1
+ import { Platform } from '@expo/eas-build-job';
2
+ import EasCommand from '../../commandUtils/EasCommand';
3
+ export default class BuildDev extends EasCommand {
4
+ static hidden: true;
5
+ static description: string;
6
+ static flags: {
7
+ platform: import("@oclif/core/lib/interfaces").OptionFlag<Platform | undefined>;
8
+ profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
9
+ };
10
+ static contextDefinition: {
11
+ projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
12
+ analytics: import("../../commandUtils/context/AnalyticsContextField").default;
13
+ vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
14
+ projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
15
+ getDynamicPublicProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPublicProjectConfigContextField;
16
+ getDynamicPrivateProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPrivateProjectConfigContextField;
17
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
18
+ };
19
+ protected runAsync(): Promise<any>;
20
+ private selectPlatformAsync;
21
+ private validateBuildRunProfileAsync;
22
+ private ensureValidBuildRunProfileExistsAsync;
23
+ }
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const eas_build_job_1 = require("@expo/eas-build-job");
5
+ const eas_json_1 = require("@expo/eas-json");
6
+ const core_1 = require("@oclif/core");
7
+ const configure_1 = require("../../build/configure");
8
+ const evaluateConfigWithEnvVarsAsync_1 = require("../../build/evaluateConfigWithEnvVarsAsync");
9
+ const runBuildAndSubmit_1 = require("../../build/runBuildAndSubmit");
10
+ const repository_1 = require("../../build/utils/repository");
11
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
12
+ const generated_1 = require("../../graphql/generated");
13
+ const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
14
+ const AppPlatform_1 = require("../../graphql/types/AppPlatform");
15
+ const log_1 = tslib_1.__importDefault(require("../../log"));
16
+ const platform_1 = require("../../platform");
17
+ const workflow_1 = require("../../project/workflow");
18
+ const prompts_1 = require("../../prompts");
19
+ const run_1 = require("../../run/run");
20
+ const download_1 = require("../../utils/download");
21
+ const fingerprintCli_1 = require("../../utils/fingerprintCli");
22
+ const profiles_1 = require("../../utils/profiles");
23
+ const DEFAULT_EAS_BUILD_RUN_PROFILE_NAME = 'development-simulator';
24
+ class BuildDev extends EasCommand_1.default {
25
+ static hidden;
26
+ static description = 'run dev client simulator/emulator build with matching fingerprint or create a new one';
27
+ static flags = {
28
+ platform: core_1.Flags.enum({
29
+ char: 'p',
30
+ options: [eas_build_job_1.Platform.IOS, eas_build_job_1.Platform.ANDROID],
31
+ }),
32
+ profile: core_1.Flags.string({
33
+ char: 'e',
34
+ description: `Name of the build profile from eas.json. It must be a profile allowing to create emulator/simulator internal distribution dev client builds. The "${DEFAULT_EAS_BUILD_RUN_PROFILE_NAME}" build profile will be selected by default.`,
35
+ helpValue: 'PROFILE_NAME',
36
+ }),
37
+ };
38
+ static contextDefinition = {
39
+ ...this.ContextOptions.LoggedIn,
40
+ ...this.ContextOptions.DynamicProjectConfig,
41
+ ...this.ContextOptions.ProjectDir,
42
+ ...this.ContextOptions.Vcs,
43
+ ...this.ContextOptions.Analytics,
44
+ ...this.ContextOptions.ProjectId,
45
+ };
46
+ async runAsync() {
47
+ const { flags } = await this.parse(BuildDev);
48
+ const { loggedIn: { actor, graphqlClient }, getDynamicPrivateProjectConfigAsync, projectDir, analytics, vcsClient, projectId, } = await this.getContextAsync(BuildDev, {
49
+ nonInteractive: false,
50
+ withServerSideEnvironment: null,
51
+ });
52
+ const platform = await this.selectPlatformAsync(flags.platform);
53
+ if (process.platform !== 'darwin' && platform === eas_build_job_1.Platform.IOS) {
54
+ core_1.Errors.error('Running iOS builds in simulator is only supported on macOS.', { exit: 1 });
55
+ }
56
+ await vcsClient.ensureRepoExistsAsync();
57
+ await (0, repository_1.ensureRepoIsCleanAsync)(vcsClient, flags.nonInteractive);
58
+ await (0, configure_1.ensureProjectConfiguredAsync)({
59
+ projectDir,
60
+ nonInteractive: false,
61
+ vcsClient,
62
+ });
63
+ const buildProfile = await this.ensureValidBuildRunProfileExistsAsync({
64
+ projectDir,
65
+ platform,
66
+ selectedBuildProfileName: flags.profile,
67
+ vcsClient,
68
+ });
69
+ const workflow = await (0, workflow_1.resolveWorkflowAsync)(projectDir, platform, vcsClient);
70
+ const { env } = await (0, evaluateConfigWithEnvVarsAsync_1.evaluateConfigWithEnvVarsAsync)({
71
+ buildProfile: buildProfile.profile,
72
+ buildProfileName: buildProfile.profileName,
73
+ graphqlClient,
74
+ getProjectConfig: getDynamicPrivateProjectConfigAsync,
75
+ opts: { env: buildProfile.profile.env },
76
+ });
77
+ const fingerprint = await (0, fingerprintCli_1.createFingerprintAsync)(projectDir, {
78
+ env,
79
+ workflow,
80
+ platforms: [platform],
81
+ });
82
+ if (!fingerprint) {
83
+ core_1.Errors.error('Failed to calculate fingerprint', { exit: 1 });
84
+ }
85
+ log_1.default.log(`✨ Calculated fingerprint hash: ${fingerprint.hash}`);
86
+ log_1.default.newLine();
87
+ const builds = await BuildQuery_1.BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
88
+ appId: projectId,
89
+ filter: {
90
+ platform: (0, AppPlatform_1.toAppPlatform)(platform),
91
+ fingerprintHash: fingerprint.hash,
92
+ status: generated_1.BuildStatus.Finished,
93
+ simulator: platform === eas_build_job_1.Platform.IOS ? true : undefined,
94
+ distribution: platform === eas_build_job_1.Platform.ANDROID ? generated_1.DistributionType.Internal : undefined,
95
+ developmentClient: true,
96
+ },
97
+ offset: 0,
98
+ limit: 1,
99
+ });
100
+ if (builds.length !== 0) {
101
+ const build = builds[0];
102
+ log_1.default.succeed(`🎯 Found successful build with matching fingerprint on EAS servers. Running it...`);
103
+ if (build.artifacts?.applicationArchiveUrl) {
104
+ const buildPath = await (0, download_1.downloadAndMaybeExtractAppAsync)(build.artifacts.applicationArchiveUrl, build.platform);
105
+ await (0, run_1.runAsync)(buildPath, build.platform);
106
+ return;
107
+ }
108
+ else {
109
+ log_1.default.warn('Artifacts for this build expired. New build will be started.');
110
+ }
111
+ }
112
+ log_1.default.log('🚀 No successful build with matching fingerprint found. Starting a new build...');
113
+ await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)({
114
+ graphqlClient,
115
+ analytics,
116
+ vcsClient,
117
+ projectDir,
118
+ flags: {
119
+ requestedPlatform: platform === eas_build_job_1.Platform.ANDROID ? platform_1.RequestedPlatform.Android : platform_1.RequestedPlatform.Ios,
120
+ nonInteractive: false,
121
+ freezeCredentials: false,
122
+ wait: true,
123
+ clearCache: false,
124
+ json: false,
125
+ autoSubmit: false,
126
+ localBuildOptions: {},
127
+ repack: false,
128
+ profile: flags.profile ?? DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
129
+ },
130
+ actor,
131
+ getDynamicPrivateProjectConfigAsync,
132
+ downloadSimBuildAutoConfirm: true,
133
+ envOverride: env,
134
+ });
135
+ }
136
+ async selectPlatformAsync(platform) {
137
+ if (platform) {
138
+ return platform;
139
+ }
140
+ const { resolvedPlatform } = await (0, prompts_1.promptAsync)({
141
+ type: 'select',
142
+ message: 'Select platform',
143
+ name: 'resolvedPlatform',
144
+ choices: [
145
+ { title: 'Android', value: eas_build_job_1.Platform.ANDROID },
146
+ { title: 'iOS', value: eas_build_job_1.Platform.IOS },
147
+ ],
148
+ });
149
+ return resolvedPlatform;
150
+ }
151
+ async validateBuildRunProfileAsync({ platform, buildProfile, buildProfileName, }) {
152
+ if (buildProfile.developmentClient !== true) {
153
+ core_1.Errors.error(`Profile "${buildProfileName}" must specify "developmentClient: true" to create a dev client build. Select a different profile or update the profile in eas.json.`, { exit: 1 });
154
+ }
155
+ if (buildProfile.distribution !== 'internal') {
156
+ core_1.Errors.error(`Profile "${buildProfileName}" must specify "distribution: internal" in order to work with eas build:dev command. Select a different profile or update the profile in eas.json.`, { exit: 1 });
157
+ }
158
+ if (platform === eas_build_job_1.Platform.IOS) {
159
+ const iosProfile = buildProfile;
160
+ if (iosProfile.simulator !== true && iosProfile.withoutCredentials !== true) {
161
+ core_1.Errors.error(`Profile "${buildProfileName}" must specify "ios.simulator: true" or "withoutCredentials: true" to create an iOS simulator build. Select a different profile or update the profile in eas.json.`, { exit: 1 });
162
+ }
163
+ }
164
+ else {
165
+ const androidProfile = buildProfile;
166
+ if (androidProfile.distribution !== 'internal' &&
167
+ androidProfile.withoutCredentials !== true) {
168
+ core_1.Errors.error(`Profile "${buildProfileName}" must specify "distribution: internal" or "withoutCredentials: true" to create an Android emulator build. Select a different profile or update the profile in eas.json.`, { exit: 1 });
169
+ }
170
+ }
171
+ }
172
+ async ensureValidBuildRunProfileExistsAsync({ projectDir, platform, selectedBuildProfileName, vcsClient, }) {
173
+ if (!!selectedBuildProfileName ||
174
+ (await (0, configure_1.doesBuildProfileExistAsync)({
175
+ projectDir,
176
+ profileName: DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
177
+ }))) {
178
+ const easJsonAccessor = eas_json_1.EasJsonAccessor.fromProjectPath(projectDir);
179
+ const [buildProfile] = await (0, profiles_1.getProfilesAsync)({
180
+ type: 'build',
181
+ easJsonAccessor,
182
+ platforms: [platform],
183
+ profileName: selectedBuildProfileName ?? DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
184
+ projectDir,
185
+ });
186
+ await this.validateBuildRunProfileAsync({
187
+ buildProfileName: selectedBuildProfileName ?? DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
188
+ platform,
189
+ buildProfile: buildProfile.profile,
190
+ });
191
+ }
192
+ else {
193
+ const createBuildProfile = await (0, prompts_1.confirmAsync)({
194
+ message: `We want to go ahead and generate "${DEFAULT_EAS_BUILD_RUN_PROFILE_NAME}" build profile for you, that matches eas build:dev criteria. Do you want to proceed?`,
195
+ });
196
+ if (!createBuildProfile) {
197
+ core_1.Errors.error('Come back later or specify different build compliant with eas build:dev requirements by using "--profile" flag.', { exit: 1 });
198
+ }
199
+ await (0, configure_1.createBuildProfileAsync)({
200
+ projectDir,
201
+ profileName: DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
202
+ profileContents: {
203
+ developmentClient: true,
204
+ distribution: 'internal',
205
+ ios: {
206
+ simulator: true,
207
+ },
208
+ environment: 'development',
209
+ },
210
+ nonInteractive: false,
211
+ vcsClient,
212
+ });
213
+ }
214
+ const easJsonAccessor = eas_json_1.EasJsonAccessor.fromProjectPath(projectDir);
215
+ const [buildProfile] = await (0, profiles_1.getProfilesAsync)({
216
+ type: 'build',
217
+ easJsonAccessor,
218
+ platforms: [platform],
219
+ profileName: selectedBuildProfileName ?? DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
220
+ projectDir,
221
+ });
222
+ return buildProfile;
223
+ }
224
+ }
225
+ exports.default = BuildDev;
@@ -118,7 +118,15 @@ class Build extends EasCommand_1.default {
118
118
  : [generated_1.StatuspageServiceName.EasBuild]);
119
119
  }
120
120
  const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
121
- await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)(graphqlClient, analytics, vcsClient, projectDir, flagsWithPlatform, actor, getDynamicPrivateProjectConfigAsync);
121
+ await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)({
122
+ graphqlClient,
123
+ analytics,
124
+ vcsClient,
125
+ projectDir,
126
+ flags: flagsWithPlatform,
127
+ actor,
128
+ getDynamicPrivateProjectConfigAsync,
129
+ });
122
130
  }
123
131
  sanitizeFlags(flags) {
124
132
  const nonInteractive = flags['non-interactive'];