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.
- package/README.md +87 -87
- package/build/build/local.js +4 -1
- package/build/commandUtils/new/commands.js +13 -4
- package/build/commandUtils/new/configs.d.ts +2 -3
- package/build/commandUtils/new/configs.js +27 -36
- package/build/commandUtils/new/projectFiles.js +7 -16
- package/build/commandUtils/new/templates/.eas/workflows/{publish-preview-update.yml → create-draft.yml} +4 -1
- package/build/commandUtils/new/templates/AGENTS.md +163 -0
- package/build/commandUtils/new/templates/CLAUDE.md +9 -0
- package/build/commandUtils/new/utils.d.ts +6 -0
- package/build/commandUtils/new/utils.js +21 -0
- package/build/commands/build/index.js +8 -0
- package/build/commands/project/new.js +10 -7
- package/build/commands/workflow/run.js +10 -7
- package/build/graphql/generated.d.ts +35 -0
- package/build/graphql/queries/AccountUsageQuery.d.ts +5 -0
- package/build/graphql/queries/AccountUsageQuery.js +40 -0
- package/build/onboarding/git.d.ts +2 -1
- package/build/onboarding/git.js +2 -1
- package/build/onboarding/installDependencies.js +1 -0
- package/build/onboarding/runCommand.js +6 -1
- package/build/utils/usage/checkForOverages.d.ts +12 -0
- package/build/utils/usage/checkForOverages.js +59 -0
- package/oclif.manifest.json +2 -2
- package/package.json +5 -5
|
@@ -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.
|
|
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
|
-
|
|
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)(
|
|
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
|
}>;
|
package/build/onboarding/git.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "16.
|
|
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.
|
|
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.
|
|
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.
|
|
16
|
-
"@expo/eas-json": "16.
|
|
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": "
|
|
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": "
|
|
245
|
+
"gitHead": "45481f9758ef94818b46540c4ff3820e556bd3f8"
|
|
246
246
|
}
|