eas-cli 13.0.1 → 13.1.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.
@@ -14,7 +14,7 @@ const projectUtils_1 = require("../project/projectUtils");
14
14
  const UpdatesModule_1 = require("../update/android/UpdatesModule");
15
15
  const UpdatesModule_2 = require("../update/ios/UpdatesModule");
16
16
  const easCli_1 = require("../utils/easCli");
17
- async function collectMetadataAsync(ctx, runtimeMetadata) {
17
+ async function collectMetadataAsync(ctx, runtimeAndFingerprintMetadata) {
18
18
  const channelObject = await resolveChannelAsync(ctx);
19
19
  const distribution = ctx.buildProfile.distribution ?? types_1.BuildDistributionType.STORE;
20
20
  const metadata = {
@@ -24,8 +24,9 @@ async function collectMetadataAsync(ctx, runtimeMetadata) {
24
24
  workflow: ctx.workflow,
25
25
  credentialsSource: ctx.buildProfile.credentialsSource,
26
26
  sdkVersion: ctx.exp.sdkVersion,
27
- runtimeVersion: runtimeMetadata?.runtimeVersion,
28
- fingerprintSource: runtimeMetadata?.fingerprintSource,
27
+ runtimeVersion: runtimeAndFingerprintMetadata?.runtimeVersion,
28
+ fingerprintHash: runtimeAndFingerprintMetadata?.fingerprintHash,
29
+ fingerprintSource: runtimeAndFingerprintMetadata?.fingerprintSource,
29
30
  reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
30
31
  ...channelObject,
31
32
  distribution,
@@ -4,3 +4,4 @@ export declare function getBuildLogsUrl(build: BuildFragment, hash?: string): st
4
4
  export declare function getArtifactUrl(artifactId: string): string;
5
5
  export declare function getInternalDistributionInstallUrl(build: BuildFragment): string;
6
6
  export declare function getUpdateGroupUrl(accountName: string, projectName: string, updateGroupId: string): string;
7
+ export declare function getWorkflowRunUrl(accountName: string, projectName: string, workflowRunId: string): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUpdateGroupUrl = exports.getInternalDistributionInstallUrl = exports.getArtifactUrl = exports.getBuildLogsUrl = exports.getProjectDashboardUrl = void 0;
3
+ exports.getWorkflowRunUrl = exports.getUpdateGroupUrl = exports.getInternalDistributionInstallUrl = exports.getArtifactUrl = exports.getBuildLogsUrl = exports.getProjectDashboardUrl = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const api_1 = require("../../api");
@@ -33,3 +33,7 @@ function getUpdateGroupUrl(accountName, projectName, updateGroupId) {
33
33
  return new URL(`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(projectName)}/updates/${encodeURIComponent(updateGroupId)}`, (0, api_1.getExpoWebsiteBaseUrl)()).toString();
34
34
  }
35
35
  exports.getUpdateGroupUrl = getUpdateGroupUrl;
36
+ function getWorkflowRunUrl(accountName, projectName, workflowRunId) {
37
+ return new URL(`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(projectName)}/workflows/${workflowRunId}`, (0, api_1.getExpoWebsiteBaseUrl)()).toString();
38
+ }
39
+ exports.getWorkflowRunUrl = getWorkflowRunUrl;
@@ -211,7 +211,7 @@ class UpdatePublish extends EasCommand_1.default {
211
211
  ...info,
212
212
  fingerprintSource: info.fingerprint
213
213
  ? (await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
214
- runtimeVersion: info.runtimeVersion,
214
+ hash: info.runtimeVersion,
215
215
  fingerprint: info.fingerprint,
216
216
  graphqlClient,
217
217
  })).fingerprintSource ?? null
@@ -0,0 +1,21 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class WorkflowRun extends EasCommand {
3
+ static description: string;
4
+ static hidden: boolean;
5
+ static state: string;
6
+ static args: {
7
+ name: string;
8
+ description: string;
9
+ }[];
10
+ static flags: {
11
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ static contextDefinition: {
14
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
15
+ vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
16
+ projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
17
+ getDynamicPublicProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPublicProjectConfigContextField;
18
+ getDynamicPrivateProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPrivateProjectConfigContextField;
19
+ };
20
+ runAsync(): Promise<void>;
21
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
6
+ const path = tslib_1.__importStar(require("node:path"));
7
+ const url_1 = require("../../build/utils/url");
8
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const flags_1 = require("../../commandUtils/flags");
10
+ const generated_1 = require("../../graphql/generated");
11
+ const WorkflowRunMutation_1 = require("../../graphql/mutations/WorkflowRunMutation");
12
+ const log_1 = tslib_1.__importStar(require("../../log"));
13
+ const projectUtils_1 = require("../../project/projectUtils");
14
+ const uploadAccountScopedEasJsonAsync_1 = require("../../project/uploadAccountScopedEasJsonAsync");
15
+ const uploadAccountScopedProjectSourceAsync_1 = require("../../project/uploadAccountScopedProjectSourceAsync");
16
+ class WorkflowRun extends EasCommand_1.default {
17
+ async runAsync() {
18
+ const { flags, args } = await this.parse(_a);
19
+ log_1.default.warn('Workflows are in beta and subject to breaking changes.');
20
+ const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, vcsClient, projectDir, } = await this.getContextAsync(_a, {
21
+ nonInteractive: flags['non-interactive'],
22
+ withServerSideEnvironment: null,
23
+ });
24
+ let yamlConfig;
25
+ try {
26
+ yamlConfig = await node_fs_1.default.promises.readFile(path.join(projectDir, args.file), 'utf8');
27
+ }
28
+ catch (err) {
29
+ log_1.default.error('Failed to read workflow file.');
30
+ throw err;
31
+ }
32
+ const { projectId, exp: { slug: projectName }, } = await getDynamicPrivateProjectConfigAsync();
33
+ const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
34
+ let projectArchiveBucketKey;
35
+ let easJsonBucketKey;
36
+ try {
37
+ ({ projectArchiveBucketKey } = await (0, uploadAccountScopedProjectSourceAsync_1.uploadAccountScopedProjectSourceAsync)({
38
+ graphqlClient,
39
+ vcsClient,
40
+ accountId: account.id,
41
+ }));
42
+ ({ easJsonBucketKey } = await (0, uploadAccountScopedEasJsonAsync_1.uploadAccountScopedEasJsonAsync)({
43
+ graphqlClient,
44
+ accountId: account.id,
45
+ projectDir,
46
+ }));
47
+ }
48
+ catch (err) {
49
+ log_1.default.error('Failed to upload project sources.');
50
+ throw err;
51
+ }
52
+ try {
53
+ const { id: workflowRunId } = await WorkflowRunMutation_1.WorkflowRunMutation.createWorkflowRunAsync(graphqlClient, {
54
+ appId: projectId,
55
+ workflowRevisionInput: {
56
+ fileName: path.basename(args.file),
57
+ yamlConfig,
58
+ },
59
+ workflowRunInput: {
60
+ projectSource: {
61
+ type: generated_1.WorkflowProjectSourceType.Gcs,
62
+ projectArchiveBucketKey,
63
+ easJsonBucketKey,
64
+ },
65
+ },
66
+ });
67
+ log_1.default.newLine();
68
+ log_1.default.succeed(`Workflow started successfully. ${(0, log_1.link)((0, url_1.getWorkflowRunUrl)(account.name, projectName, workflowRunId))}`);
69
+ }
70
+ catch (err) {
71
+ log_1.default.error('Failed to start the workflow with the API.');
72
+ throw err;
73
+ }
74
+ }
75
+ }
76
+ _a = WorkflowRun;
77
+ WorkflowRun.description = 'Run an EAS workflow';
78
+ // TODO(@sjchmiela): Keep command hidden until workflows are live
79
+ WorkflowRun.hidden = true;
80
+ WorkflowRun.state = 'beta';
81
+ WorkflowRun.args = [{ name: 'file', description: 'Path to the workflow file to run' }];
82
+ WorkflowRun.flags = {
83
+ ...flags_1.EASNonInteractiveFlag,
84
+ };
85
+ WorkflowRun.contextDefinition = {
86
+ ..._a.ContextOptions.DynamicProjectConfig,
87
+ ..._a.ContextOptions.ProjectDir,
88
+ ..._a.ContextOptions.Vcs,
89
+ ..._a.ContextOptions.LoggedIn,
90
+ };
91
+ exports.default = WorkflowRun;
@@ -0,0 +1,11 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export declare class WorkflowValidate extends EasCommand {
3
+ static description: string;
4
+ static hidden: boolean;
5
+ static args: {
6
+ name: string;
7
+ description: string;
8
+ required: boolean;
9
+ }[];
10
+ runAsync(): Promise<void>;
11
+ }
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowValidate = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const promises_1 = tslib_1.__importDefault(require("fs/promises"));
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ const YAML = tslib_1.__importStar(require("yaml"));
8
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const log_1 = tslib_1.__importDefault(require("../../log"));
10
+ const ora_1 = require("../../ora");
11
+ class WorkflowValidate extends EasCommand_1.default {
12
+ async runAsync() {
13
+ const { args: { path: filePath }, } = await this.parse(WorkflowValidate);
14
+ const spinner = (0, ora_1.ora)().start('Validating the workflow YAML file…');
15
+ try {
16
+ await validateYAMLAsync(filePath);
17
+ spinner.succeed('Workflow configuration YAML is valid.');
18
+ }
19
+ catch (error) {
20
+ spinner.fail('Workflow configuration YAML is not valid.');
21
+ if (error instanceof YAML.YAMLParseError) {
22
+ log_1.default.error(`YAML syntax error: ${error.message}`);
23
+ }
24
+ else if (error instanceof Error) {
25
+ log_1.default.error(error.message);
26
+ }
27
+ else {
28
+ log_1.default.error(`Unexpected error: ${String(error)}`);
29
+ }
30
+ process.exit(1);
31
+ }
32
+ }
33
+ }
34
+ exports.WorkflowValidate = WorkflowValidate;
35
+ WorkflowValidate.description = 'validate a workflow configuration yaml file';
36
+ WorkflowValidate.hidden = true;
37
+ WorkflowValidate.args = [
38
+ {
39
+ name: 'path',
40
+ description: 'Path to the workflow configuration YAML file (must end with .yml or .yaml)',
41
+ required: true,
42
+ },
43
+ ];
44
+ async function checkIfFileExistsAsync(filePath) {
45
+ try {
46
+ await promises_1.default.access(filePath);
47
+ }
48
+ catch {
49
+ throw new Error(`File does not exist: ${filePath}`);
50
+ }
51
+ }
52
+ function checkIfValidYAMLFileExtension(filePath) {
53
+ const fileExtension = path_1.default.extname(filePath).toLowerCase();
54
+ if (fileExtension !== '.yml' && fileExtension !== '.yaml') {
55
+ throw new Error('File must have a .yml or .yaml extension');
56
+ }
57
+ }
58
+ async function validateYAMLAsync(filePath) {
59
+ await checkIfFileExistsAsync(filePath);
60
+ checkIfValidYAMLFileExtension(filePath);
61
+ try {
62
+ const fileContents = await promises_1.default.readFile(filePath, 'utf8');
63
+ // First check if the file is empty or only contains whitespace
64
+ if (!fileContents.trim()) {
65
+ throw new Error('YAML file is empty or contains only comments.');
66
+ }
67
+ const parsedYaml = YAML.parse(fileContents);
68
+ // Check if the parsed result is empty or null
69
+ if (parsedYaml === null ||
70
+ parsedYaml === undefined ||
71
+ (typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)) {
72
+ throw new Error('YAML file is empty or contains only comments.');
73
+ }
74
+ }
75
+ catch (error) {
76
+ if (error instanceof Error &&
77
+ error.message === 'YAML file is empty or contains only comments.') {
78
+ throw error;
79
+ }
80
+ if (error instanceof YAML.YAMLParseError || error instanceof Error) {
81
+ throw new Error(`YAML parsing error: ${error.message}`);
82
+ }
83
+ else {
84
+ throw new Error(`YAML parsing error: ${String(error)}`);
85
+ }
86
+ }
87
+ }