eas-cli 16.24.0 → 16.25.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.
@@ -46,6 +46,7 @@ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
46
46
  const core_1 = require("@oclif/core");
47
47
  const core_2 = require("@urql/core");
48
48
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
49
+ const getenv_1 = require("getenv");
49
50
  const path = tslib_1.__importStar(require("node:path"));
50
51
  const slash_1 = tslib_1.__importDefault(require("slash"));
51
52
  const url_1 = require("../../build/utils/url");
@@ -79,7 +80,7 @@ class WorkflowRun extends EasCommand_1.default {
79
80
  default: false,
80
81
  allowNo: true,
81
82
  description: 'Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.',
82
- summary: 'Wait for workflow run to complete. Defaults to false. Cannot be used with the --json flag.',
83
+ summary: 'Wait for workflow run to complete. Defaults to false.',
83
84
  }),
84
85
  input: core_1.Flags.string({
85
86
  char: 'F',
@@ -103,9 +104,6 @@ class WorkflowRun extends EasCommand_1.default {
103
104
  async runAsync() {
104
105
  const { flags, args } = await this.parse(WorkflowRun);
105
106
  if (flags.json) {
106
- if (flags.wait) {
107
- throw new Error('Cannot use --json and --wait flags simultaneously.');
108
- }
109
107
  (0, json_1.enableJsonOutput)();
110
108
  }
111
109
  const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, vcsClient, projectDir, } = await this.getContextAsync(WorkflowRun, {
@@ -295,9 +293,10 @@ class WorkflowRun extends EasCommand_1.default {
295
293
  }
296
294
  process.exit(0);
297
295
  }
298
- log_1.default.newLine();
296
+ const spinnerUsesStdErr = (0, getenv_1.boolish)('CI', false) || flags.json;
299
297
  const { status } = await waitForWorkflowRunToEndAsync(graphqlClient, {
300
298
  workflowRunId,
299
+ spinnerUsesStdErr,
301
300
  });
302
301
  if (flags.json) {
303
302
  const workflowRun = await WorkflowRunQuery_1.WorkflowRunQuery.withJobsByIdAsync(graphqlClient, workflowRunId, {
@@ -317,9 +316,12 @@ class WorkflowRun extends EasCommand_1.default {
317
316
  }
318
317
  }
319
318
  exports.default = WorkflowRun;
320
- async function waitForWorkflowRunToEndAsync(graphqlClient, { workflowRunId }) {
319
+ async function waitForWorkflowRunToEndAsync(graphqlClient, { workflowRunId, spinnerUsesStdErr }) {
321
320
  log_1.default.log('Waiting for workflow run to complete. You can press Ctrl+C to exit.');
322
- const spinner = (0, ora_1.ora)('').start();
321
+ const spinner = (0, ora_1.ora)({
322
+ stream: spinnerUsesStdErr ? process.stderr : process.stdout,
323
+ text: '',
324
+ }).start();
323
325
  spinner.prefixText = (0, chalk_1.default) `{bold.yellow Workflow run is waiting to start:}`;
324
326
  let failedFetchesCount = 0;
325
327
  while (true) {
@@ -351,6 +353,7 @@ async function waitForWorkflowRunToEndAsync(graphqlClient, { workflowRunId }) {
351
353
  }
352
354
  case generated_1.WorkflowRunStatus.Success:
353
355
  spinner.prefixText = (0, chalk_1.default) `{bold.green Workflow has completed successfully.}`;
356
+ spinner.text = '';
354
357
  spinner.succeed('');
355
358
  return workflowRun;
356
359
  }
@@ -7637,6 +7637,7 @@ export type WorkflowRun = ActivityTimelineProjectActivity & {
7637
7637
  createdAt: Scalars['DateTime']['output'];
7638
7638
  durationSeconds?: Maybe<Scalars['Int']['output']>;
7639
7639
  errors: Array<WorkflowRunError>;
7640
+ finalizedAt?: Maybe<Scalars['DateTime']['output']>;
7640
7641
  gitCommitHash?: Maybe<Scalars['String']['output']>;
7641
7642
  gitCommitMessage?: Maybe<Scalars['String']['output']>;
7642
7643
  githubRepository?: Maybe<GitHubRepository>;
@@ -12651,6 +12652,40 @@ export type CancelWorkflowRunMutation = {
12651
12652
  };
12652
12653
  };
12653
12654
  };
12655
+ export type AccountUsageForOverageWarningQueryVariables = Exact<{
12656
+ accountId: Scalars['String']['input'];
12657
+ currentDate: Scalars['DateTime']['input'];
12658
+ }>;
12659
+ export type AccountUsageForOverageWarningQuery = {
12660
+ __typename?: 'RootQuery';
12661
+ account: {
12662
+ __typename?: 'AccountQuery';
12663
+ byId: {
12664
+ __typename?: 'Account';
12665
+ id: string;
12666
+ name: string;
12667
+ subscription?: {
12668
+ __typename?: 'SubscriptionDetails';
12669
+ id: string;
12670
+ name?: string | null;
12671
+ } | null;
12672
+ usageMetrics: {
12673
+ __typename?: 'AccountUsageMetrics';
12674
+ EAS_BUILD: {
12675
+ __typename?: 'UsageMetricTotal';
12676
+ id: string;
12677
+ planMetrics: Array<{
12678
+ __typename?: 'EstimatedUsage';
12679
+ id: string;
12680
+ serviceMetric: EasServiceMetric;
12681
+ value: number;
12682
+ limit: number;
12683
+ }>;
12684
+ };
12685
+ };
12686
+ };
12687
+ };
12688
+ };
12654
12689
  export type AppByIdQueryVariables = Exact<{
12655
12690
  appId: Scalars['String']['input'];
12656
12691
  }>;
@@ -0,0 +1,5 @@
1
+ import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
2
+ import { AccountUsageForOverageWarningQuery } from '../generated';
3
+ export declare const AccountUsageQuery: {
4
+ getUsageForOverageWarningAsync(graphqlClient: ExpoGraphqlClient, accountId: string, currentDate: Date): Promise<AccountUsageForOverageWarningQuery['account']['byId']>;
5
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AccountUsageQuery = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
6
+ const client_1 = require("../client");
7
+ exports.AccountUsageQuery = {
8
+ async getUsageForOverageWarningAsync(graphqlClient, accountId, currentDate) {
9
+ const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
10
+ .query((0, graphql_tag_1.default) `
11
+ query AccountUsageForOverageWarning($accountId: String!, $currentDate: DateTime!) {
12
+ account {
13
+ byId(accountId: $accountId) {
14
+ id
15
+ name
16
+ subscription {
17
+ id
18
+ name
19
+ }
20
+ usageMetrics {
21
+ EAS_BUILD: byBillingPeriod(date: $currentDate, service: BUILDS) {
22
+ id
23
+ planMetrics {
24
+ id
25
+ serviceMetric
26
+ value
27
+ limit
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ `, { accountId, currentDate: currentDate.toISOString() }, {
35
+ additionalTypenames: ['Account', 'AccountUsageMetrics', 'UsageMetricTotal'],
36
+ })
37
+ .toPromise());
38
+ return data.account.byId;
39
+ },
40
+ };
@@ -1,8 +1,9 @@
1
- export declare function runGitCloneAsync({ targetProjectDir, githubRepositoryName, githubUsername, cloneMethod, }: {
1
+ export declare function runGitCloneAsync({ targetProjectDir, githubRepositoryName, githubUsername, cloneMethod, showOutput, }: {
2
2
  githubUsername: string;
3
3
  githubRepositoryName: string;
4
4
  targetProjectDir: string;
5
5
  cloneMethod: 'ssh' | 'https';
6
+ showOutput?: boolean;
6
7
  }): Promise<{
7
8
  targetProjectDir: string;
8
9
  }>;
@@ -6,7 +6,7 @@ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
6
6
  const runCommand_1 = require("./runCommand");
7
7
  const log_1 = tslib_1.__importDefault(require("../log"));
8
8
  const prompts_1 = require("../prompts");
9
- async function runGitCloneAsync({ targetProjectDir, githubRepositoryName, githubUsername, cloneMethod, }) {
9
+ async function runGitCloneAsync({ targetProjectDir, githubRepositoryName, githubUsername, cloneMethod, showOutput = true, }) {
10
10
  const url = cloneMethod === 'ssh'
11
11
  ? `git@github.com:${githubUsername}/${githubRepositoryName}.git`
12
12
  : `https://github.com/${githubUsername}/${githubRepositoryName}.git`;
@@ -18,6 +18,7 @@ async function runGitCloneAsync({ targetProjectDir, githubRepositoryName, github
18
18
  return line.includes('Cloning into');
19
19
  },
20
20
  showSpinner: false,
21
+ showOutput,
21
22
  });
22
23
  return { targetProjectDir };
23
24
  }
@@ -21,6 +21,7 @@ async function installDependenciesAsync({ outputLevel = 'default', projectDir, p
21
21
  !(line === packageManager));
22
22
  },
23
23
  showOutput: outputLevel !== 'none',
24
+ showSpinner: outputLevel !== 'none',
24
25
  });
25
26
  }
26
27
  exports.installDependenciesAsync = installDependenciesAsync;
@@ -7,7 +7,9 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const log_1 = tslib_1.__importDefault(require("../log"));
8
8
  const ora_1 = require("../ora");
9
9
  async function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shouldPrintStderrLineAsStdout, showSpinner = true, showOutput = true, }) {
10
- log_1.default.log(`🏗️ Running ${chalk_1.default.bold(`${command} ${args.join(' ')}`)}...`);
10
+ if (showOutput) {
11
+ log_1.default.log(`🏗️ Running ${chalk_1.default.bold(`${command} ${args.join(' ')}`)}...`);
12
+ }
11
13
  let spinner;
12
14
  if (showSpinner) {
13
15
  spinner = (0, ora_1.ora)(`${chalk_1.default.bold(`${command} ${args.join(' ')}`)}`).start();
@@ -53,6 +55,9 @@ async function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shoul
53
55
  }
54
56
  throw error;
55
57
  }
58
+ if (!showOutput) {
59
+ return;
60
+ }
56
61
  if (showSpinner) {
57
62
  spinner?.succeed(`${chalk_1.default.bold(`${command} ${args.join(' ')}`)} succeeded`);
58
63
  }
@@ -0,0 +1,12 @@
1
+ import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
2
+ export declare function maybeWarnAboutUsageOveragesAsync({ graphqlClient, accountId, }: {
3
+ graphqlClient: ExpoGraphqlClient;
4
+ accountId: string;
5
+ }): Promise<void>;
6
+ export declare function calculatePercentUsed(value: number, limit: number): number;
7
+ export declare function createProgressBar(percentUsed: number, width?: number): string;
8
+ export declare function displayOverageWarning({ percentUsed, hasFreePlan, name, }: {
9
+ percentUsed: number;
10
+ hasFreePlan: boolean;
11
+ name: string;
12
+ }): void;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.displayOverageWarning = exports.createProgressBar = exports.calculatePercentUsed = exports.maybeWarnAboutUsageOveragesAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const AccountUsageQuery_1 = require("../../graphql/queries/AccountUsageQuery");
7
+ const log_1 = tslib_1.__importStar(require("../../log"));
8
+ const THRESHOLD_PERCENT = 85;
9
+ async function maybeWarnAboutUsageOveragesAsync({ graphqlClient, accountId, }) {
10
+ try {
11
+ const currentDate = new Date();
12
+ const { name, subscription, usageMetrics: { EAS_BUILD }, } = await AccountUsageQuery_1.AccountUsageQuery.getUsageForOverageWarningAsync(graphqlClient, accountId, currentDate);
13
+ const planMetric = EAS_BUILD?.planMetrics?.[0];
14
+ if (!planMetric || !subscription) {
15
+ return;
16
+ }
17
+ const percentUsed = calculatePercentUsed(planMetric.value, planMetric.limit);
18
+ if (percentUsed >= THRESHOLD_PERCENT) {
19
+ const hasFreePlan = subscription.name === 'Free';
20
+ displayOverageWarning({ percentUsed, hasFreePlan, name });
21
+ }
22
+ }
23
+ catch (error) {
24
+ // Silently fail if we can't fetch usage data - we don't want to block the user's workflow
25
+ log_1.default.debug(`Failed to fetch usage data: ${error}`);
26
+ }
27
+ }
28
+ exports.maybeWarnAboutUsageOveragesAsync = maybeWarnAboutUsageOveragesAsync;
29
+ function calculatePercentUsed(value, limit) {
30
+ if (limit === 0) {
31
+ return 0;
32
+ }
33
+ return Math.min(Math.floor((value / limit) * 100), 100);
34
+ }
35
+ exports.calculatePercentUsed = calculatePercentUsed;
36
+ function createProgressBar(percentUsed, width = 30) {
37
+ const filledWidth = Math.round((percentUsed / 100) * width);
38
+ const emptyWidth = width - filledWidth;
39
+ const filled = '█'.repeat(filledWidth);
40
+ const empty = '░'.repeat(emptyWidth);
41
+ return `${filled}${empty}`;
42
+ }
43
+ exports.createProgressBar = createProgressBar;
44
+ function displayOverageWarning({ percentUsed, hasFreePlan, name, }) {
45
+ log_1.default.warn(chalk_1.default.bold(`You've used ${percentUsed}% of your included build credits for this month. `) +
46
+ createProgressBar(percentUsed));
47
+ const billingUrl = `https://expo.dev/accounts/${name}/settings/billing`;
48
+ const warning = hasFreePlan
49
+ ? "You won't be able to start new builds once you reach the limit. " +
50
+ (0, log_1.link)(billingUrl, { text: 'Upgrade your plan to continue service.', dim: false })
51
+ : 'Additional usage beyond your limit will be charged at pay-as-you-go rates. ' +
52
+ (0, log_1.link)(billingUrl, {
53
+ text: 'See usage in billing.',
54
+ dim: false,
55
+ });
56
+ log_1.default.warn(warning);
57
+ log_1.default.newLine();
58
+ }
59
+ exports.displayOverageWarning = displayOverageWarning;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "16.24.0",
2
+ "version": "16.25.0",
3
3
  "commands": {
4
4
  "analytics": {
5
5
  "id": "analytics",
@@ -4198,7 +4198,7 @@
4198
4198
  "wait": {
4199
4199
  "name": "wait",
4200
4200
  "type": "boolean",
4201
- "summary": "Wait for workflow run to complete. Defaults to false. Cannot be used with the --json flag.",
4201
+ "summary": "Wait for workflow run to complete. Defaults to false.",
4202
4202
  "description": "Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.",
4203
4203
  "allowNo": true
4204
4204
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eas-cli",
3
3
  "description": "EAS command line tool",
4
- "version": "16.24.0",
4
+ "version": "16.25.0",
5
5
  "author": "Expo <support@expo.dev>",
6
6
  "bin": {
7
7
  "eas": "./bin/run"
@@ -12,8 +12,8 @@
12
12
  "@expo/code-signing-certificates": "0.0.5",
13
13
  "@expo/config": "10.0.6",
14
14
  "@expo/config-plugins": "9.0.12",
15
- "@expo/eas-build-job": "1.0.239",
16
- "@expo/eas-json": "16.23.0",
15
+ "@expo/eas-build-job": "1.0.243",
16
+ "@expo/eas-json": "16.25.0",
17
17
  "@expo/env": "^1.0.0",
18
18
  "@expo/json-file": "8.3.3",
19
19
  "@expo/logger": "1.0.221",
@@ -71,7 +71,7 @@
71
71
  "node-forge": "1.3.1",
72
72
  "node-stream-zip": "1.15.0",
73
73
  "nullthrows": "1.1.1",
74
- "ora": "9.0.0",
74
+ "ora": "5.1.0",
75
75
  "pkg-dir": "4.2.0",
76
76
  "pngjs": "7.0.0",
77
77
  "promise-limit": "2.7.0",
@@ -242,5 +242,5 @@
242
242
  "node": "20.11.0",
243
243
  "yarn": "1.22.21"
244
244
  },
245
- "gitHead": "184616e874a6d91546c0874ce8319fdc6fdea4bf"
245
+ "gitHead": "45481f9758ef94818b46540c4ff3820e556bd3f8"
246
246
  }