eas-cli 14.4.0 → 14.5.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.
@@ -126,7 +126,7 @@ async function resolveRemoteVersionCodeAsync(graphqlClient, { projectDir, projec
126
126
  }
127
127
  else {
128
128
  if (localVersions.appBuildVersion) {
129
- log_1.default.warn('No remote versions are configured for this project, versionCode will be initialized based on the value from the local project.');
129
+ 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
130
  currentBuildVersion = localVersions.appBuildVersion;
131
131
  }
132
132
  else {
@@ -464,21 +464,22 @@ async function computeAndMaybeUploadFingerprintFromExpoUpdatesAsync(ctx) {
464
464
  * It's ok for fingerprintSources or runtimeVersion to be empty
465
465
  * fingerprintSources only exist if the project is using runtimeVersion.policy: fingerprint
466
466
  */
467
- if (!resolvedRuntimeVersion.fingerprint || !resolvedRuntimeVersion.runtimeVersion) {
467
+ if (!resolvedRuntimeVersion.expoUpdatesRuntimeFingerprint ||
468
+ !resolvedRuntimeVersion.runtimeVersion) {
468
469
  return {
469
470
  runtimeVersion: resolvedRuntimeVersion.runtimeVersion ?? undefined,
470
471
  };
471
472
  }
472
473
  const uploadedFingerprint = await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
473
474
  hash: resolvedRuntimeVersion.runtimeVersion,
474
- fingerprint: resolvedRuntimeVersion.fingerprint,
475
+ fingerprint: resolvedRuntimeVersion.expoUpdatesRuntimeFingerprint,
475
476
  graphqlClient: ctx.graphqlClient,
476
477
  localBuildMode: ctx.localBuildOptions.localBuildMode,
477
478
  });
478
479
  return {
479
480
  runtimeVersion: uploadedFingerprint.hash,
480
481
  fingerprintSource: uploadedFingerprint.fingerprintSource,
481
- fingerprintHash: resolvedRuntimeVersion.fingerprintHash ?? undefined,
482
+ fingerprintHash: resolvedRuntimeVersion.expoUpdatesRuntimeFingerprintHash ?? undefined,
482
483
  };
483
484
  }
484
485
  async function computeAndMaybeUploadFingerprintWithoutExpoUpdatesAsync(ctx, { debug } = {}) {
@@ -43,10 +43,10 @@ async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClie
43
43
  .filter(({ name, value }) => name && value)
44
44
  .map(({ name, value }) => [name, value]));
45
45
  if (Object.keys(serverEnvVars).length > 0) {
46
- log_1.default.log(`Environment variables with visibility "Plain text" and "Sensitive" loaded from the "${environment.toLowerCase()}" environment on EAS servers: ${Object.keys(serverEnvVars).join(', ')}.`);
46
+ log_1.default.log(`Environment variables with visibility "Plain text" and "Sensitive" loaded from the "${environment.toLowerCase()}" environment on EAS: ${Object.keys(serverEnvVars).join(', ')}.`);
47
47
  }
48
48
  else {
49
- log_1.default.log(`No environment variables with visibility "Plain text" and "Sensitive" found for the "${environment.toLowerCase()}" environment on EAS servers.`);
49
+ log_1.default.log(`No environment variables with visibility "Plain text" and "Sensitive" found for the "${environment.toLowerCase()}" environment on EAS.`);
50
50
  }
51
51
  if (buildProfile.env && Object.keys(buildProfile.env).length > 0) {
52
52
  log_1.default.log(`Environment variables loaded from the "${buildProfileName}" build profile "env" configuration: ${buildProfile.env && Object.keys(buildProfile.env).join(', ')}.`);
@@ -56,7 +56,7 @@ async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClie
56
56
  Object.keys(serverEnvVars).length > 0) {
57
57
  const overlappingKeys = Object.keys(serverEnvVars).filter(key => buildProfile.env && Object.keys(buildProfile.env).includes(key));
58
58
  if (overlappingKeys.length > 0) {
59
- log_1.default.warn(`The following environment variables are defined in both the "${buildProfileName}" build profile "env" configuration and the "${environment.toLowerCase()}" environment on EAS servers: ${overlappingKeys.join(', ')}. The values from the build profile configuration will be used.`);
59
+ log_1.default.warn(`The following environment variables are defined in both the "${buildProfileName}" build profile "env" configuration and the "${environment.toLowerCase()}" environment on EAS: ${overlappingKeys.join(', ')}. The values from the build profile configuration will be used.`);
60
60
  }
61
61
  }
62
62
  log_1.default.newLine();
@@ -70,17 +70,11 @@ async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClie
70
70
  }
71
71
  }
72
72
  function resolveSuggestedEnvironmentForBuildProfileConfiguration(buildProfile) {
73
- const setEnvironmentMessage = 'Set the "environment" field in the build profile if you want to specify the environment manually.';
74
- if (buildProfile.distribution === 'store') {
75
- log_1.default.log(`We detected that you are building for the "store" distribution. Resolving the environment for environment variables used during the build to "production". ${setEnvironmentMessage}`);
76
- return generated_1.EnvironmentVariableEnvironment.Production;
77
- }
78
- else {
79
- if (buildProfile.developmentClient) {
80
- log_1.default.log(`We detected that you are building the development client. Resolving the environment for environment variables used during the build to "development". ${setEnvironmentMessage}`);
81
- return generated_1.EnvironmentVariableEnvironment.Development;
82
- }
83
- log_1.default.log(`We detected that you are building for the "internal" distribution. Resolving the environment for environment variables used during the build to "preview". ${setEnvironmentMessage}`);
84
- return generated_1.EnvironmentVariableEnvironment.Preview;
85
- }
73
+ const environment = buildProfile.distribution === 'store'
74
+ ? generated_1.EnvironmentVariableEnvironment.Production
75
+ : buildProfile.developmentClient
76
+ ? generated_1.EnvironmentVariableEnvironment.Development
77
+ : generated_1.EnvironmentVariableEnvironment.Preview;
78
+ log_1.default.log(`Resolved "${environment.toLowerCase()}" environment for the build. ${(0, log_1.learnMore)('https://docs.expo.dev/eas/environment-variables/#setting-the-environment-for-your-builds')}`);
79
+ return environment;
86
80
  }
@@ -214,7 +214,7 @@ async function resolveRemoteBuildNumberAsync(graphqlClient, { projectDir, projec
214
214
  }
215
215
  else {
216
216
  if (localBuildNumber) {
217
- log_1.default.warn('No remote versions are configured for this project, buildNumber will be initialized based on the value from the local project.');
217
+ 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
218
  currentBuildVersion = localBuildNumber;
219
219
  }
220
220
  else {
@@ -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.152';
10
+ const PLUGIN_PACKAGE_VERSION = '1.0.163';
11
11
  var LocalBuildMode;
12
12
  (function (LocalBuildMode) {
13
13
  /**
@@ -20,6 +20,7 @@ export default class BuildList extends EasCommand {
20
20
  'app-identifier': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
21
21
  'build-profile': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
22
22
  'git-commit-hash': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
23
+ 'fingerprint-hash': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
23
24
  };
24
25
  static contextDefinition: {
25
26
  vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
@@ -58,6 +58,9 @@ class BuildList extends EasCommand_1.default {
58
58
  aliases: ['gitCommitHash'],
59
59
  description: 'Filter only builds created with the specified git commit hash',
60
60
  }),
61
+ 'fingerprint-hash': core_1.Flags.string({
62
+ description: 'Filter only builds with the specified fingerprint hash',
63
+ }),
61
64
  ...pagination_1.EasPaginatedQueryFlags,
62
65
  limit: (0, pagination_1.getLimitFlagWithCustomValues)({ defaultTo: 10, limit: queries_1.BUILDS_LIMIT }),
63
66
  ...flags_1.EasNonInteractiveAndJsonFlags,
@@ -107,6 +110,7 @@ class BuildList extends EasCommand_1.default {
107
110
  buildProfile: flags['build-profile'],
108
111
  gitCommitHash: flags['git-commit-hash'],
109
112
  simulator: flags.simulator,
113
+ fingerprintHash: flags['fingerprint-hash'],
110
114
  },
111
115
  paginatedQueryOptions,
112
116
  });
@@ -12,9 +12,9 @@ const json_1 = require("../../utils/json");
12
12
  const deployment_1 = require("../../worker/deployment");
13
13
  const logs_1 = require("../../worker/utils/logs");
14
14
  class WorkerAlias extends EasCommand_1.default {
15
- static description = 'Assign deployment aliases';
16
- static aliases = ['deploy:alias', 'deploy:promote'];
17
- static state = 'beta';
15
+ static description = 'Assign deployment aliases.';
16
+ static aliases = ['worker:alias', 'deploy:promote'];
17
+ static state = 'preview';
18
18
  static flags = {
19
19
  prod: core_1.Flags.boolean({
20
20
  aliases: ['production'],
@@ -44,7 +44,7 @@ class WorkerAlias extends EasCommand_1.default {
44
44
  if (flags.json) {
45
45
  (0, json_1.enableJsonOutput)();
46
46
  }
47
- log_1.default.warn('EAS Hosting is still in beta and subject to changes.');
47
+ log_1.default.warn('EAS Hosting is still in preview and subject to changes.');
48
48
  const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, } = await this.getContextAsync(WorkerAlias, {
49
49
  nonInteractive: true,
50
50
  withServerSideEnvironment: null,
@@ -21,10 +21,10 @@ const isDirectory = (directoryPath) => node_fs_1.default.promises
21
21
  .then(stat => stat.isDirectory())
22
22
  .catch(() => false);
23
23
  class WorkerDeploy extends EasCommand_1.default {
24
- static description = 'Deploy your Expo web build';
25
- static aliases = ['deploy'];
24
+ static description = 'Deploy your Expo Router web build and API Routes.';
25
+ static aliases = ['worker:deploy'];
26
26
  static usage = [(0, chalk_1.default) `deploy {dim [options]}`, `deploy --prod`];
27
- static state = 'beta';
27
+ static state = 'preview';
28
28
  static flags = {
29
29
  prod: core_1.Flags.boolean({
30
30
  aliases: ['production'],
@@ -62,7 +62,7 @@ class WorkerDeploy extends EasCommand_1.default {
62
62
  if (flags.json) {
63
63
  (0, json_1.enableJsonOutput)();
64
64
  }
65
- log_1.default.warn('EAS Hosting is still in beta and subject to changes.');
65
+ log_1.default.warn('EAS Hosting is still in preview and subject to changes.');
66
66
  const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, projectDir, } = await this.getContextAsync(WorkerDeploy, { ...flags, withServerSideEnvironment: null });
67
67
  const projectDist = await resolveExportedProjectAsync(flags, projectDir);
68
68
  const { projectId } = await getDynamicPrivateProjectConfigAsync();
@@ -331,7 +331,7 @@ function logExportedProjectInfo(project) {
331
331
  // Only show the timestamp for exports older than 1 minute
332
332
  if (project.modifiedAt && Date.now() - project.modifiedAt.getTime() > 60000) {
333
333
  modifiedAgo = ` - exported ${(0, timeago_js_1.format)(project.modifiedAt)}`;
334
- log_1.default.warn(`> Project export: ${project.type}${modifiedAgo}}`);
334
+ log_1.default.warn(`> Project export: ${project.type}${modifiedAgo}`);
335
335
  }
336
336
  else {
337
337
  log_1.default.log((0, chalk_1.default) `{dim > Project export: ${project.type}}`);
@@ -16,8 +16,8 @@ export default class EnvExec extends EasCommand {
16
16
  private isNonInteractive;
17
17
  runAsync(): Promise<void>;
18
18
  private sanitizeFlagsAndArgs;
19
- private runCommandNonInteractiveWithEnvVarsAsync;
20
19
  protected catch(err: Error): Promise<any>;
20
+ private runCommandNonInteractiveWithEnvVarsAsync;
21
21
  private runCommandWithEnvVarsAsync;
22
22
  private loadEnvironmentVariablesAsync;
23
23
  }
@@ -67,21 +67,17 @@ class EnvExec extends EasCommand_1.default {
67
67
  if (!(0, variableUtils_1.isEnvironment)(environment)) {
68
68
  throw new Error("Invalid environment. Use one of 'production', 'preview', or 'development'.");
69
69
  }
70
+ const firstChar = bash_command[0];
71
+ const lastChar = bash_command[bash_command.length - 1];
72
+ const cleanCommand = (firstChar === '"' && lastChar === '"') || (firstChar === "'" && lastChar === "'")
73
+ ? bash_command.slice(1, -1)
74
+ : bash_command;
70
75
  return {
71
76
  nonInteractive: rawFlags['non-interactive'],
72
77
  environment,
73
- command: bash_command,
78
+ command: cleanCommand,
74
79
  };
75
80
  }
76
- async runCommandNonInteractiveWithEnvVarsAsync({ command, environmentVariables, }) {
77
- await (0, spawn_async_1.default)('bash', ['-c', command], {
78
- stdio: 'inherit',
79
- env: {
80
- ...process.env,
81
- ...environmentVariables,
82
- },
83
- });
84
- }
85
81
  // eslint-disable-next-line async-protect/async-suffix
86
82
  async catch(err) {
87
83
  // when in non-interactive, make the behavior of this command a pure passthrough, outputting only the subprocess' stdout and stderr and exiting with the
@@ -93,9 +89,20 @@ class EnvExec extends EasCommand_1.default {
93
89
  await super.catch(err);
94
90
  }
95
91
  }
92
+ async runCommandNonInteractiveWithEnvVarsAsync({ command, environmentVariables, }) {
93
+ await (0, spawn_async_1.default)(command, [], {
94
+ shell: true,
95
+ stdio: 'inherit',
96
+ env: {
97
+ ...process.env,
98
+ ...environmentVariables,
99
+ },
100
+ });
101
+ }
96
102
  async runCommandWithEnvVarsAsync({ command, environmentVariables, }) {
97
103
  log_1.default.log(`Running command: ${chalk_1.default.bold(command)}`);
98
- const spawnPromise = (0, spawn_async_1.default)('bash', ['-c', command], {
104
+ const spawnPromise = (0, spawn_async_1.default)(command, [], {
105
+ shell: true,
99
106
  stdio: ['inherit', 'pipe', 'pipe'],
100
107
  env: {
101
108
  ...process.env,
@@ -9,9 +9,11 @@ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasComm
9
9
  const builds_1 = require("../../commandUtils/builds");
10
10
  const flags_1 = require("../../commandUtils/flags");
11
11
  const generated_1 = require("../../graphql/generated");
12
+ const FingerprintMutation_1 = require("../../graphql/mutations/FingerprintMutation");
12
13
  const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
13
14
  const log_1 = tslib_1.__importDefault(require("../../log"));
14
15
  const ora_1 = require("../../ora");
16
+ const maybeUploadFingerprintAsync_1 = require("../../project/maybeUploadFingerprintAsync");
15
17
  const projectUtils_1 = require("../../project/projectUtils");
16
18
  const workflow_1 = require("../../project/workflow");
17
19
  const prompts_1 = require("../../prompts");
@@ -80,6 +82,18 @@ class FingerprintCompare extends EasCommand_1.default {
80
82
  log_1.default.error('Project fingerprints can only be computed for projects with SDK 52 or higher');
81
83
  return;
82
84
  }
85
+ const uploadedFingerprint = await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
86
+ hash: fingerprint.hash,
87
+ fingerprint: {
88
+ fingerprintSources: fingerprint.sources,
89
+ isDebugFingerprintSource: log_1.default.isDebug,
90
+ },
91
+ graphqlClient,
92
+ });
93
+ await FingerprintMutation_1.FingerprintMutation.createFingerprintAsync(graphqlClient, projectId, {
94
+ hash: uploadedFingerprint.hash,
95
+ source: uploadedFingerprint.fingerprintSource,
96
+ });
83
97
  if (fingerprint.hash === projectFingerprint.hash) {
84
98
  log_1.default.log(`✅ Project fingerprint matches build`);
85
99
  return;
@@ -269,10 +269,10 @@ class UpdatePublish extends EasCommand_1.default {
269
269
  const runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMappingFromExpoUpdates = await Promise.all(runtimeToPlatformsAndFingerprintInfoMapping.map(async (info) => {
270
270
  return {
271
271
  ...info,
272
- fingerprintSource: info.fingerprint
272
+ expoUpdatesRuntimeFingerprintSource: info.expoUpdatesRuntimeFingerprint
273
273
  ? (await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
274
274
  hash: info.runtimeVersion,
275
- fingerprint: info.fingerprint,
275
+ fingerprint: info.expoUpdatesRuntimeFingerprint,
276
276
  graphqlClient,
277
277
  })).fingerprintSource ?? null
278
278
  : null,
@@ -296,7 +296,7 @@ class UpdatePublish extends EasCommand_1.default {
296
296
  const gitCommitHash = await vcsClient.getCommitHashAsync();
297
297
  const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
298
298
  // Sort the updates into different groups based on their platform specific runtime versions
299
- const updateGroups = runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMapping.map(({ runtimeVersion, platforms, fingerprintSource, fingerprintInfoGroup }) => {
299
+ const updateGroups = runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMapping.map(({ runtimeVersion, platforms, fingerprintInfoGroup }) => {
300
300
  const localUpdateInfoGroup = Object.fromEntries(platforms.map(platform => [
301
301
  platform,
302
302
  unsortedUpdateInfoGroups[platform],
@@ -323,9 +323,6 @@ class UpdatePublish extends EasCommand_1.default {
323
323
  branchId: branch.id,
324
324
  updateInfoGroup: localUpdateInfoGroup,
325
325
  rolloutInfoGroup: localRolloutInfoGroup,
326
- runtimeFingerprintSource: fingerprintSource
327
- ? (0, graphql_1.transformFingerprintSource)(fingerprintSource)
328
- : null,
329
326
  fingerprintInfoGroup: transformedFingerprintInfoGroup,
330
327
  runtimeVersion,
331
328
  message: updateMessage,
@@ -123,8 +123,8 @@ class UpdateRollBackToEmbedded extends EasCommand_1.default {
123
123
  platform,
124
124
  runtimeVersionInfo: {
125
125
  runtimeVersion: selectedRuntime,
126
- fingerprint: null,
127
- fingerprintHash: null,
126
+ expoUpdatesRuntimeFingerprint: null,
127
+ expoUpdatesRuntimeFingerprintHash: null,
128
128
  },
129
129
  })));
130
130
  let newUpdates;
@@ -162,13 +162,18 @@ async function promptUsernameAsync() {
162
162
  // Get the email address that was last used and set it as
163
163
  // the default value for quicker authentication.
164
164
  const lastAppleId = await getCachedUsernameAsync();
165
- const { username } = await (0, prompts_1.promptAsync)({
165
+ let { username } = await (0, prompts_1.promptAsync)({
166
166
  type: 'text',
167
167
  name: 'username',
168
168
  message: `Apple ID:`,
169
169
  validate: (val) => val !== '',
170
170
  initial: lastAppleId ?? undefined,
171
171
  });
172
+ // https://github.com/expo/eas-cli/issues/2254
173
+ // user got an invalid unprintable character in their username, which was saved to cache and used to prefill the prompt
174
+ // which made them accept the prefilled value not knowing it contains the character and fail to log in
175
+ // this replace makes sure no such characters are used or cached
176
+ username = username.replace(/[\x00-\x1F]/gi, '');
172
177
  if (username && username !== lastAppleId) {
173
178
  await cacheUsernameAsync(username);
174
179
  }