eas-cli 13.2.3 → 13.4.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 (63) hide show
  1. package/README.md +359 -162
  2. package/build/build/build.js +3 -3
  3. package/build/build/evaluateConfigWithEnvVarsAsync.js +18 -2
  4. package/build/build/utils/url.d.ts +1 -0
  5. package/build/build/utils/url.js +5 -1
  6. package/build/commandUtils/flags.d.ts +5 -4
  7. package/build/commandUtils/flags.js +6 -8
  8. package/build/commands/env/create.d.ts +6 -6
  9. package/build/commands/env/create.js +27 -28
  10. package/build/commands/env/delete.d.ts +5 -5
  11. package/build/commands/env/delete.js +15 -13
  12. package/build/commands/env/exec.d.ts +0 -1
  13. package/build/commands/env/exec.js +1 -2
  14. package/build/commands/env/get.d.ts +5 -5
  15. package/build/commands/env/get.js +16 -13
  16. package/build/commands/env/link.d.ts +1 -1
  17. package/build/commands/env/link.js +12 -13
  18. package/build/commands/env/list.d.ts +5 -5
  19. package/build/commands/env/list.js +14 -12
  20. package/build/commands/env/pull.d.ts +1 -2
  21. package/build/commands/env/pull.js +8 -9
  22. package/build/commands/env/push.d.ts +1 -2
  23. package/build/commands/env/push.js +9 -10
  24. package/build/commands/env/unlink.d.ts +1 -1
  25. package/build/commands/env/unlink.js +11 -10
  26. package/build/commands/env/update.d.ts +6 -6
  27. package/build/commands/env/update.js +18 -15
  28. package/build/commands/secret/create.d.ts +1 -0
  29. package/build/commands/secret/create.js +3 -0
  30. package/build/commands/secret/delete.d.ts +1 -0
  31. package/build/commands/secret/delete.js +3 -0
  32. package/build/commands/secret/list.d.ts +1 -0
  33. package/build/commands/secret/list.js +3 -0
  34. package/build/commands/secret/push.d.ts +1 -0
  35. package/build/commands/secret/push.js +3 -0
  36. package/build/commands/update/index.js +19 -2
  37. package/build/commands/workflow/create.d.ts +18 -0
  38. package/build/commands/workflow/create.js +100 -0
  39. package/build/commands/workflow/run.d.ts +0 -2
  40. package/build/commands/workflow/run.js +25 -6
  41. package/build/commands/workflow/validate.d.ts +9 -1
  42. package/build/commands/workflow/validate.js +47 -50
  43. package/build/graphql/generated.d.ts +199 -28
  44. package/build/graphql/generated.js +10 -1
  45. package/build/graphql/mutations/EnvironmentVariableMutation.d.ts +1 -0
  46. package/build/graphql/mutations/WorkflowRevisionMutation.d.ts +33 -0
  47. package/build/graphql/mutations/WorkflowRevisionMutation.js +32 -0
  48. package/build/graphql/types/Update.js +9 -0
  49. package/build/project/publish.d.ts +23 -1
  50. package/build/project/publish.js +71 -11
  51. package/build/project/resolveRuntimeVersionAsync.d.ts +2 -0
  52. package/build/project/resolveRuntimeVersionAsync.js +4 -0
  53. package/build/update/republish.js +19 -0
  54. package/build/utils/expodash/mapMapAsync.d.ts +1 -0
  55. package/build/utils/expodash/mapMapAsync.js +12 -0
  56. package/build/utils/fingerprintCli.d.ts +21 -3
  57. package/build/utils/fingerprintCli.js +62 -13
  58. package/build/utils/prompts.d.ts +1 -1
  59. package/build/utils/prompts.js +1 -1
  60. package/build/utils/workflowFile.d.ts +16 -0
  61. package/build/utils/workflowFile.js +64 -0
  62. package/oclif.manifest.json +84 -52
  63. package/package.json +10 -4
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.WorkflowCreate = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const promises_1 = tslib_1.__importDefault(require("fs/promises"));
8
+ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
9
+ const path_1 = tslib_1.__importDefault(require("path"));
10
+ const prompts_1 = tslib_1.__importDefault(require("prompts"));
11
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
12
+ const flags_1 = require("../../commandUtils/flags");
13
+ const log_1 = tslib_1.__importDefault(require("../../log"));
14
+ const workflowFile_1 = require("../../utils/workflowFile");
15
+ const DEFAULT_WORKFLOW_NAME = 'workflow.yml';
16
+ const HELLO_WORLD_TEMPLATE = `name: Hello World
17
+
18
+ on:
19
+ push:
20
+ branches: ['*']
21
+
22
+ jobs:
23
+ hello_world:
24
+ steps:
25
+ - uses: eas/checkout
26
+ - run: echo "Hello, World"
27
+ `;
28
+ class WorkflowCreate extends EasCommand_1.default {
29
+ async runAsync() {
30
+ const { args: { name: argFileName }, flags, } = await this.parse(_a);
31
+ const { projectDir } = await this.getContextAsync(_a, {
32
+ nonInteractive: flags['non-interactive'],
33
+ });
34
+ let fileName = argFileName;
35
+ if (!fileName) {
36
+ const response = await (0, prompts_1.default)({
37
+ type: 'text',
38
+ name: 'fileName',
39
+ message: 'What would you like to name your workflow file?',
40
+ initial: DEFAULT_WORKFLOW_NAME,
41
+ validate: value => {
42
+ try {
43
+ workflowFile_1.WorkflowFile.validateYamlExtension(value);
44
+ return true;
45
+ }
46
+ catch (error) {
47
+ return error instanceof Error ? error.message : 'Invalid file name';
48
+ }
49
+ },
50
+ });
51
+ if (!response.fileName) {
52
+ log_1.default.warn('Workflow creation cancelled.');
53
+ process.exit(0);
54
+ }
55
+ fileName = response.fileName;
56
+ }
57
+ try {
58
+ await this.ensureWorkflowsDirectoryExistsAsync({ projectDir });
59
+ await this.createWorkflowFileAsync({ fileName, projectDir });
60
+ }
61
+ catch (error) {
62
+ log_1.default.error('Failed to create workflow file.');
63
+ throw error;
64
+ }
65
+ }
66
+ async ensureWorkflowsDirectoryExistsAsync({ projectDir, }) {
67
+ try {
68
+ await promises_1.default.access(path_1.default.join(projectDir, '.eas', 'workflows'));
69
+ }
70
+ catch {
71
+ await promises_1.default.mkdir(path_1.default.join(projectDir, '.eas', 'workflows'), { recursive: true });
72
+ log_1.default.withTick(`Created directory ${chalk_1.default.bold(path_1.default.join(projectDir, '.eas', 'workflows'))}`);
73
+ }
74
+ }
75
+ async createWorkflowFileAsync({ fileName, projectDir, }) {
76
+ workflowFile_1.WorkflowFile.validateYamlExtension(fileName);
77
+ const filePath = path_1.default.join(projectDir, '.eas', 'workflows', fileName);
78
+ if (await fs_extra_1.default.pathExists(filePath)) {
79
+ throw new Error(`Workflow file already exists: ${filePath}`);
80
+ }
81
+ await promises_1.default.writeFile(filePath, HELLO_WORLD_TEMPLATE);
82
+ log_1.default.withTick(`Created ${chalk_1.default.bold(filePath)}`);
83
+ }
84
+ }
85
+ exports.WorkflowCreate = WorkflowCreate;
86
+ _a = WorkflowCreate;
87
+ WorkflowCreate.description = 'create a new workflow configuration YAML file';
88
+ WorkflowCreate.args = [
89
+ {
90
+ name: 'name',
91
+ description: 'Name of the workflow file (must end with .yml or .yaml)',
92
+ required: false,
93
+ },
94
+ ];
95
+ WorkflowCreate.flags = {
96
+ ...flags_1.EASNonInteractiveFlag,
97
+ };
98
+ WorkflowCreate.contextDefinition = {
99
+ ..._a.ContextOptions.ProjectDir,
100
+ };
@@ -1,8 +1,6 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export default class WorkflowRun extends EasCommand {
3
3
  static description: string;
4
- static hidden: boolean;
5
- static state: string;
6
4
  static args: {
7
5
  name: string;
8
6
  description: string;
@@ -2,28 +2,34 @@
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
- const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
+ const core_1 = require("@urql/core");
6
6
  const path = tslib_1.__importStar(require("node:path"));
7
7
  const url_1 = require("../../build/utils/url");
8
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
9
  const flags_1 = require("../../commandUtils/flags");
10
10
  const generated_1 = require("../../graphql/generated");
11
+ const WorkflowRevisionMutation_1 = require("../../graphql/mutations/WorkflowRevisionMutation");
11
12
  const WorkflowRunMutation_1 = require("../../graphql/mutations/WorkflowRunMutation");
12
13
  const log_1 = tslib_1.__importStar(require("../../log"));
13
14
  const projectUtils_1 = require("../../project/projectUtils");
14
15
  const uploadAccountScopedEasJsonAsync_1 = require("../../project/uploadAccountScopedEasJsonAsync");
15
16
  const uploadAccountScopedProjectSourceAsync_1 = require("../../project/uploadAccountScopedProjectSourceAsync");
17
+ const workflowFile_1 = require("../../utils/workflowFile");
16
18
  class WorkflowRun extends EasCommand_1.default {
17
19
  async runAsync() {
18
20
  const { flags, args } = await this.parse(_a);
19
- log_1.default.warn('Workflows are in beta and subject to breaking changes.');
20
21
  const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, vcsClient, projectDir, } = await this.getContextAsync(_a, {
21
22
  nonInteractive: flags['non-interactive'],
22
23
  withServerSideEnvironment: null,
23
24
  });
24
25
  let yamlConfig;
25
26
  try {
26
- yamlConfig = await node_fs_1.default.promises.readFile(path.join(projectDir, args.file), 'utf8');
27
+ const workflowFileContents = await workflowFile_1.WorkflowFile.readWorkflowFileContentsAsync({
28
+ projectDir,
29
+ filePath: args.file,
30
+ });
31
+ log_1.default.log(`Using workflow file from ${workflowFileContents.filePath}`);
32
+ yamlConfig = workflowFileContents.yamlConfig;
27
33
  }
28
34
  catch (err) {
29
35
  log_1.default.error('Failed to read workflow file.');
@@ -31,6 +37,22 @@ class WorkflowRun extends EasCommand_1.default {
31
37
  }
32
38
  const { projectId, exp: { slug: projectName }, } = await getDynamicPrivateProjectConfigAsync();
33
39
  const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
40
+ try {
41
+ await WorkflowRevisionMutation_1.WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
42
+ appId: projectId,
43
+ yamlConfig,
44
+ });
45
+ }
46
+ catch (error) {
47
+ if (error instanceof core_1.CombinedError) {
48
+ workflowFile_1.WorkflowFile.maybePrintWorkflowFileValidationErrors({
49
+ error,
50
+ accountName: account.name,
51
+ projectName,
52
+ });
53
+ throw error;
54
+ }
55
+ }
34
56
  let projectArchiveBucketKey;
35
57
  let easJsonBucketKey;
36
58
  try {
@@ -75,9 +97,6 @@ class WorkflowRun extends EasCommand_1.default {
75
97
  }
76
98
  _a = WorkflowRun;
77
99
  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
100
  WorkflowRun.args = [{ name: 'file', description: 'Path to the workflow file to run' }];
82
101
  WorkflowRun.flags = {
83
102
  ...flags_1.EASNonInteractiveFlag,
@@ -1,11 +1,19 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
2
  export declare class WorkflowValidate extends EasCommand {
3
3
  static description: string;
4
- static hidden: boolean;
5
4
  static args: {
6
5
  name: string;
7
6
  description: string;
8
7
  required: boolean;
9
8
  }[];
9
+ static flags: {
10
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ static contextDefinition: {
13
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
14
+ projectDir: import("../../commandUtils/context/ProjectDirContextField").default;
15
+ getDynamicPublicProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPublicProjectConfigContextField;
16
+ getDynamicPrivateProjectConfigAsync: import("../../commandUtils/context/DynamicProjectConfigContextField").DynamicPrivateProjectConfigContextField;
17
+ };
10
18
  runAsync(): Promise<void>;
11
19
  }
@@ -1,19 +1,44 @@
1
1
  "use strict";
2
+ var _a;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.WorkflowValidate = void 0;
4
5
  const tslib_1 = require("tslib");
5
- const promises_1 = tslib_1.__importDefault(require("fs/promises"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
6
+ const core_1 = require("@urql/core");
7
7
  const YAML = tslib_1.__importStar(require("yaml"));
8
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const flags_1 = require("../../commandUtils/flags");
10
+ const WorkflowRevisionMutation_1 = require("../../graphql/mutations/WorkflowRevisionMutation");
9
11
  const log_1 = tslib_1.__importDefault(require("../../log"));
10
12
  const ora_1 = require("../../ora");
13
+ const projectUtils_1 = require("../../project/projectUtils");
14
+ const workflowFile_1 = require("../../utils/workflowFile");
11
15
  class WorkflowValidate extends EasCommand_1.default {
12
16
  async runAsync() {
13
- const { args: { path: filePath }, } = await this.parse(WorkflowValidate);
17
+ const { args: { path: filePath }, flags, } = await this.parse(_a);
18
+ const { getDynamicPrivateProjectConfigAsync, loggedIn: { graphqlClient }, projectDir, } = await this.getContextAsync(_a, {
19
+ nonInteractive: flags['non-interactive'],
20
+ withServerSideEnvironment: null,
21
+ });
22
+ const { projectId, exp: { slug: projectName }, } = await getDynamicPrivateProjectConfigAsync();
23
+ const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
14
24
  const spinner = (0, ora_1.ora)().start('Validating the workflow YAML file…');
15
25
  try {
16
- await validateYAMLAsync(filePath);
26
+ const workflowFileContents = await workflowFile_1.WorkflowFile.readWorkflowFileContentsAsync({
27
+ projectDir,
28
+ filePath,
29
+ });
30
+ log_1.default.log(`Using workflow file from ${workflowFileContents.filePath}`);
31
+ const parsedYaml = YAML.parse(workflowFileContents.yamlConfig);
32
+ // Check if the parsed result is empty or null
33
+ if (parsedYaml === null ||
34
+ parsedYaml === undefined ||
35
+ (typeof parsedYaml === 'object' && Object.keys(parsedYaml).length === 0)) {
36
+ throw new Error('YAML file is empty or contains only comments.');
37
+ }
38
+ await WorkflowRevisionMutation_1.WorkflowRevisionMutation.validateWorkflowYamlConfigAsync(graphqlClient, {
39
+ appId: projectId,
40
+ yamlConfig: workflowFileContents.yamlConfig,
41
+ });
17
42
  spinner.succeed('Workflow configuration YAML is valid.');
18
43
  }
19
44
  catch (error) {
@@ -21,19 +46,27 @@ class WorkflowValidate extends EasCommand_1.default {
21
46
  if (error instanceof YAML.YAMLParseError) {
22
47
  log_1.default.error(`YAML syntax error: ${error.message}`);
23
48
  }
49
+ else if (error instanceof core_1.CombinedError) {
50
+ workflowFile_1.WorkflowFile.maybePrintWorkflowFileValidationErrors({
51
+ error,
52
+ accountName: account.name,
53
+ projectName,
54
+ });
55
+ throw error;
56
+ }
24
57
  else if (error instanceof Error) {
25
58
  log_1.default.error(error.message);
26
59
  }
27
60
  else {
28
61
  log_1.default.error(`Unexpected error: ${String(error)}`);
29
62
  }
30
- process.exit(1);
63
+ throw error;
31
64
  }
32
65
  }
33
66
  }
34
67
  exports.WorkflowValidate = WorkflowValidate;
68
+ _a = WorkflowValidate;
35
69
  WorkflowValidate.description = 'validate a workflow configuration yaml file';
36
- WorkflowValidate.hidden = true;
37
70
  WorkflowValidate.args = [
38
71
  {
39
72
  name: 'path',
@@ -41,47 +74,11 @@ WorkflowValidate.args = [
41
74
  required: true,
42
75
  },
43
76
  ];
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
- }
77
+ WorkflowValidate.flags = {
78
+ ...flags_1.EASNonInteractiveFlag,
79
+ };
80
+ WorkflowValidate.contextDefinition = {
81
+ ..._a.ContextOptions.DynamicProjectConfig,
82
+ ..._a.ContextOptions.ProjectDir,
83
+ ..._a.ContextOptions.LoggedIn,
84
+ };