eas-cli 16.14.1 → 16.16.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 (40) hide show
  1. package/README.md +137 -84
  2. package/build/commandUtils/workflow/fetchLogs.d.ts +2 -0
  3. package/build/commandUtils/workflow/fetchLogs.js +16 -0
  4. package/build/commandUtils/workflow/stateMachine.d.ts +44 -0
  5. package/build/commandUtils/workflow/stateMachine.js +212 -0
  6. package/build/commandUtils/workflow/types.d.ts +39 -0
  7. package/build/commandUtils/workflow/types.js +13 -0
  8. package/build/commandUtils/workflow/utils.d.ts +12 -0
  9. package/build/commandUtils/workflow/utils.js +116 -0
  10. package/build/commands/deploy/index.js +47 -49
  11. package/build/commands/workflow/cancel.js +3 -6
  12. package/build/commands/workflow/logs.d.ts +18 -0
  13. package/build/commands/workflow/logs.js +94 -0
  14. package/build/commands/workflow/run.d.ts +105 -0
  15. package/build/commands/workflow/run.js +280 -0
  16. package/build/commands/workflow/runs.js +4 -3
  17. package/build/commands/workflow/view.d.ts +17 -0
  18. package/build/commands/workflow/view.js +95 -0
  19. package/build/credentials/ios/appstore/bundleIdCapabilities.d.ts +4 -17
  20. package/build/credentials/ios/appstore/bundleIdCapabilities.js +45 -625
  21. package/build/credentials/ios/appstore/capabilityIdentifiers.js +33 -34
  22. package/build/credentials/ios/appstore/capabilityList.d.ts +33 -0
  23. package/build/credentials/ios/appstore/capabilityList.js +646 -0
  24. package/build/graphql/generated.d.ts +236 -19
  25. package/build/graphql/queries/WorkflowJobQuery.d.ts +7 -0
  26. package/build/graphql/queries/WorkflowJobQuery.js +29 -0
  27. package/build/graphql/queries/WorkflowRunQuery.js +13 -13
  28. package/build/graphql/types/WorkflowJob.d.ts +1 -0
  29. package/build/graphql/types/WorkflowJob.js +32 -0
  30. package/build/graphql/types/WorkflowRun.js +18 -0
  31. package/build/worker/assets.d.ts +19 -16
  32. package/build/worker/assets.js +51 -22
  33. package/build/worker/upload.d.ts +21 -9
  34. package/build/worker/upload.js +98 -80
  35. package/build/worker/utils/multipart.d.ts +11 -0
  36. package/build/worker/utils/multipart.js +98 -0
  37. package/oclif.manifest.json +85 -1
  38. package/package.json +2 -2
  39. package/build/commandUtils/workflows.d.ts +0 -20
  40. package/build/commandUtils/workflows.js +0 -21
@@ -0,0 +1,18 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class WorkflowLogView extends EasCommand {
3
+ static description: string;
4
+ static flags: {
5
+ 'all-steps': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
6
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ static args: {
10
+ name: string;
11
+ description: string;
12
+ }[];
13
+ static contextDefinition: {
14
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
15
+ projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
16
+ };
17
+ runAsync(): Promise<void>;
18
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
5
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
6
+ const flags_1 = require("../../commandUtils/flags");
7
+ const stateMachine_1 = require("../../commandUtils/workflow/stateMachine");
8
+ const log_1 = tslib_1.__importDefault(require("../../log"));
9
+ const json_1 = require("../../utils/json");
10
+ function printLogsForAllSteps(logs) {
11
+ [...logs.keys()].forEach(step => {
12
+ const logLines = logs.get(step);
13
+ if (logLines) {
14
+ log_1.default.log(`Step: ${step}`);
15
+ logLines.forEach(line => {
16
+ log_1.default.log(` ${line.time} ${line.msg}`);
17
+ });
18
+ }
19
+ log_1.default.addNewLineIfNone();
20
+ });
21
+ }
22
+ class WorkflowLogView extends EasCommand_1.default {
23
+ static description = 'view logs for a workflow run, selecting a job and step to view. You can pass in either a workflow run ID or a job ID. If no ID is passed in, you will be prompted to select from recent workflow runs for the current project.';
24
+ static flags = {
25
+ ...flags_1.EasJsonOnlyFlag,
26
+ ...flags_1.EASNonInteractiveFlag,
27
+ 'all-steps': core_1.Flags.boolean({
28
+ description: 'Print all logs, rather than prompting for a specific step. This will be automatically set when in non-interactive mode.',
29
+ default: false,
30
+ }),
31
+ };
32
+ static args = [
33
+ { name: 'id', description: 'ID of the workflow run or workflow job to view logs for' },
34
+ ];
35
+ static contextDefinition = {
36
+ ...this.ContextOptions.ProjectId,
37
+ ...this.ContextOptions.LoggedIn,
38
+ };
39
+ async runAsync() {
40
+ const { args, flags } = await this.parse(WorkflowLogView);
41
+ const nonInteractive = flags['non-interactive'];
42
+ const allSteps = nonInteractive ? true : flags['all-steps'];
43
+ log_1.default.debug(`allSteps = ${allSteps}`);
44
+ log_1.default.debug(`nonInteractive = ${nonInteractive}`);
45
+ log_1.default.debug(`flags.json = ${flags.json}`);
46
+ log_1.default.debug(`args.id = ${args.id}`);
47
+ const { loggedIn: { graphqlClient }, projectId, } = await this.getContextAsync(WorkflowLogView, {
48
+ nonInteractive,
49
+ });
50
+ if (flags.json) {
51
+ (0, json_1.enableJsonOutput)();
52
+ }
53
+ const finalSelectionState = await (0, stateMachine_1.executeWorkflowSelectionActionsAsync)({
54
+ graphqlClient,
55
+ projectId,
56
+ nonInteractive,
57
+ allSteps,
58
+ state: stateMachine_1.WorkflowCommandSelectionStateValue.WORKFLOW_JOB_SELECTION,
59
+ jobId: args.id,
60
+ });
61
+ if (finalSelectionState.state === stateMachine_1.WorkflowCommandSelectionStateValue.ERROR) {
62
+ log_1.default.error(finalSelectionState.message);
63
+ return;
64
+ }
65
+ const logs = finalSelectionState?.logs;
66
+ if (allSteps) {
67
+ if (logs) {
68
+ if (flags.json) {
69
+ (0, json_1.printJsonOnlyOutput)(Object.fromEntries(logs));
70
+ }
71
+ else {
72
+ printLogsForAllSteps(logs);
73
+ }
74
+ }
75
+ }
76
+ else {
77
+ const selectedStep = finalSelectionState?.step;
78
+ const logLines = logs?.get(selectedStep);
79
+ if (logLines) {
80
+ if (flags.json) {
81
+ const output = {};
82
+ output[selectedStep] = logLines ?? null;
83
+ (0, json_1.printJsonOnlyOutput)(output);
84
+ }
85
+ else {
86
+ logLines.forEach(line => {
87
+ log_1.default.log(` ${line.time} ${line.msg}`);
88
+ });
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ exports.default = WorkflowLogView;
@@ -1,3 +1,45 @@
1
+ /**
2
+ * EAS Workflow Run Command
3
+ *
4
+ * This command runs an EAS workflow with support for interactive input prompting.
5
+ *
6
+ * Input Sources (in order of precedence):
7
+ * 1. Command line flags (-F key=value)
8
+ * 2. STDIN JSON input (echo '{"key": "value"}' | eas workflow:run)
9
+ * 3. Interactive prompts (when required inputs are missing and not in non-interactive mode)
10
+ *
11
+ * Interactive Prompting:
12
+ * - When running in interactive mode (default), the command will automatically prompt
13
+ * for any required inputs that are not provided via flags or STDIN
14
+ * - Input types supported: string, boolean, number, choice, environment
15
+ * - Each input type has appropriate validation and default values
16
+ * - Use --non-interactive flag to disable prompting and require all inputs via flags
17
+ *
18
+ * Example workflow with inputs:
19
+ * ```yaml
20
+ * on:
21
+ * workflow_dispatch:
22
+ * inputs:
23
+ * environment:
24
+ * type: string
25
+ * required: true
26
+ * description: "Environment to deploy to"
27
+ * debug:
28
+ * type: boolean
29
+ * default: false
30
+ * description: "Enable debug mode"
31
+ * version:
32
+ * type: number
33
+ * required: true
34
+ * description: "Version number"
35
+ * deployment_type:
36
+ * type: choice
37
+ * options: ["staging", "production"]
38
+ * default: "staging"
39
+ * description: "Type of deployment"
40
+ * ```
41
+ */
42
+ import { z } from 'zod';
1
43
  import EasCommand from '../../commandUtils/EasCommand';
2
44
  export default class WorkflowRun extends EasCommand {
3
45
  static description: string;
@@ -8,6 +50,7 @@ export default class WorkflowRun extends EasCommand {
8
50
  static flags: {
9
51
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
52
  wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
53
+ input: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined>;
11
54
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
55
  };
13
56
  static contextDefinition: {
@@ -19,3 +62,65 @@ export default class WorkflowRun extends EasCommand {
19
62
  };
20
63
  runAsync(): Promise<void>;
21
64
  }
65
+ export declare function parseInputs(inputFlags: string[]): Record<string, string>;
66
+ export declare function maybeReadStdinAsync(): Promise<string | null>;
67
+ export declare function parseJsonInputs(jsonString: string): Record<string, string>;
68
+ export declare const WorkflowDispatchInputZ: z.ZodIntersection<z.ZodObject<{
69
+ description: z.ZodOptional<z.ZodPipeline<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodString>>;
70
+ required: z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodPipeline<z.ZodNumber, z.ZodBoolean>, z.ZodEffects<z.ZodBoolean, boolean, unknown>]>>;
71
+ }, "strip", z.ZodTypeAny, {
72
+ required: boolean;
73
+ description?: string | undefined;
74
+ }, {
75
+ description?: string | number | undefined;
76
+ required?: unknown;
77
+ }>, z.ZodUnion<[z.ZodObject<{
78
+ type: z.ZodDefault<z.ZodLiteral<"string">>;
79
+ default: z.ZodOptional<z.ZodPipeline<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodString>>;
80
+ }, "strip", z.ZodTypeAny, {
81
+ type: "string";
82
+ default?: string | undefined;
83
+ }, {
84
+ default?: string | number | undefined;
85
+ type?: "string" | undefined;
86
+ }>, z.ZodObject<{
87
+ type: z.ZodLiteral<"boolean">;
88
+ default: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodPipeline<z.ZodNumber, z.ZodBoolean>, z.ZodEffects<z.ZodBoolean, boolean, unknown>]>>;
89
+ }, "strip", z.ZodTypeAny, {
90
+ type: "boolean";
91
+ default?: boolean | undefined;
92
+ }, {
93
+ type: "boolean";
94
+ default?: unknown;
95
+ }>, z.ZodObject<{
96
+ type: z.ZodLiteral<"number">;
97
+ default: z.ZodOptional<z.ZodNumber>;
98
+ }, "strip", z.ZodTypeAny, {
99
+ type: "number";
100
+ default?: number | undefined;
101
+ }, {
102
+ type: "number";
103
+ default?: number | undefined;
104
+ }>, z.ZodObject<{
105
+ type: z.ZodLiteral<"choice">;
106
+ default: z.ZodOptional<z.ZodPipeline<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodString>>;
107
+ options: z.ZodArray<z.ZodPipeline<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodString>, "many">;
108
+ }, "strip", z.ZodTypeAny, {
109
+ type: "choice";
110
+ options: string[];
111
+ default?: string | undefined;
112
+ }, {
113
+ type: "choice";
114
+ options: (string | number)[];
115
+ default?: string | number | undefined;
116
+ }>, z.ZodObject<{
117
+ type: z.ZodLiteral<"environment">;
118
+ default: z.ZodOptional<z.ZodString>;
119
+ }, "strip", z.ZodTypeAny, {
120
+ type: "environment";
121
+ default?: string | undefined;
122
+ }, {
123
+ type: "environment";
124
+ default?: string | undefined;
125
+ }>]>>;
126
+ export declare function parseWorkflowInputsFromYaml(yamlConfig: string): Record<string, z.infer<typeof WorkflowDispatchInputZ>>;
@@ -1,5 +1,47 @@
1
1
  "use strict";
2
+ /**
3
+ * EAS Workflow Run Command
4
+ *
5
+ * This command runs an EAS workflow with support for interactive input prompting.
6
+ *
7
+ * Input Sources (in order of precedence):
8
+ * 1. Command line flags (-F key=value)
9
+ * 2. STDIN JSON input (echo '{"key": "value"}' | eas workflow:run)
10
+ * 3. Interactive prompts (when required inputs are missing and not in non-interactive mode)
11
+ *
12
+ * Interactive Prompting:
13
+ * - When running in interactive mode (default), the command will automatically prompt
14
+ * for any required inputs that are not provided via flags or STDIN
15
+ * - Input types supported: string, boolean, number, choice, environment
16
+ * - Each input type has appropriate validation and default values
17
+ * - Use --non-interactive flag to disable prompting and require all inputs via flags
18
+ *
19
+ * Example workflow with inputs:
20
+ * ```yaml
21
+ * on:
22
+ * workflow_dispatch:
23
+ * inputs:
24
+ * environment:
25
+ * type: string
26
+ * required: true
27
+ * description: "Environment to deploy to"
28
+ * debug:
29
+ * type: boolean
30
+ * default: false
31
+ * description: "Enable debug mode"
32
+ * version:
33
+ * type: number
34
+ * required: true
35
+ * description: "Version number"
36
+ * deployment_type:
37
+ * type: choice
38
+ * options: ["staging", "production"]
39
+ * default: "staging"
40
+ * description: "Type of deployment"
41
+ * ```
42
+ */
2
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.parseWorkflowInputsFromYaml = exports.WorkflowDispatchInputZ = exports.parseJsonInputs = exports.maybeReadStdinAsync = exports.parseInputs = void 0;
3
45
  const tslib_1 = require("tslib");
4
46
  const core_1 = require("@oclif/core");
5
47
  const core_2 = require("@urql/core");
@@ -7,6 +49,8 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
49
  const fs = tslib_1.__importStar(require("node:fs"));
8
50
  const path = tslib_1.__importStar(require("node:path"));
9
51
  const slash_1 = tslib_1.__importDefault(require("slash"));
52
+ const YAML = tslib_1.__importStar(require("yaml"));
53
+ const zod_1 = require("zod");
10
54
  const url_1 = require("../../build/utils/url");
11
55
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
12
56
  const flags_1 = require("../../commandUtils/flags");
@@ -19,6 +63,7 @@ const ora_1 = require("../../ora");
19
63
  const projectUtils_1 = require("../../project/projectUtils");
20
64
  const uploadAccountScopedFileAsync_1 = require("../../project/uploadAccountScopedFileAsync");
21
65
  const uploadAccountScopedProjectSourceAsync_1 = require("../../project/uploadAccountScopedProjectSourceAsync");
66
+ const prompts_1 = require("../../prompts");
22
67
  const json_1 = require("../../utils/json");
23
68
  const promise_1 = require("../../utils/promise");
24
69
  const workflowFile_1 = require("../../utils/workflowFile");
@@ -38,6 +83,13 @@ class WorkflowRun extends EasCommand_1.default {
38
83
  description: 'Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.',
39
84
  summary: 'Wait for workflow run to complete',
40
85
  }),
86
+ input: core_1.Flags.string({
87
+ char: 'F',
88
+ aliases: ['f', 'field'],
89
+ multiple: true,
90
+ description: 'Add a parameter in key=value format. Use multiple instances of this flag to set multiple inputs.',
91
+ summary: 'Set workflow inputs',
92
+ }),
41
93
  ...flags_1.EasJsonOnlyFlag,
42
94
  };
43
95
  static contextDefinition = {
@@ -86,6 +138,33 @@ class WorkflowRun extends EasCommand_1.default {
86
138
  throw error;
87
139
  }
88
140
  }
141
+ let inputs;
142
+ // Check for stdin input
143
+ const stdinData = await maybeReadStdinAsync();
144
+ const inputsFromFlags = [...(flags.input ?? [])];
145
+ // Validate that both stdin and -F flags are not provided simultaneously
146
+ if (stdinData && inputsFromFlags.length > 0) {
147
+ throw new Error('Cannot use both stdin JSON input and -F flags simultaneously. Please use only one input method.');
148
+ }
149
+ if (stdinData) {
150
+ inputs = parseJsonInputs(stdinData);
151
+ }
152
+ else if (inputsFromFlags.length > 0) {
153
+ inputs = parseInputs(inputsFromFlags);
154
+ }
155
+ // Parse workflow inputs from YAML and prompt for missing required inputs
156
+ const inputSpecs = parseWorkflowInputsFromYaml(yamlConfig);
157
+ if (!flags['non-interactive']) {
158
+ inputs = await maybePromptForMissingInputsAsync({ inputSpecs, inputs: inputs ?? {} });
159
+ }
160
+ if (inputs && Object.keys(inputs).length > 0) {
161
+ log_1.default.addNewLineIfNone();
162
+ log_1.default.newLine();
163
+ log_1.default.log('Running with inputs:');
164
+ for (const [key, value] of Object.entries(inputs)) {
165
+ log_1.default.log(`- ${chalk_1.default.bold(key)}: ${JSON.stringify(value)}`);
166
+ }
167
+ }
89
168
  let projectArchiveBucketKey;
90
169
  let easJsonBucketKey = null;
91
170
  let packageJsonBucketKey = null;
@@ -134,6 +213,7 @@ class WorkflowRun extends EasCommand_1.default {
134
213
  yamlConfig,
135
214
  },
136
215
  workflowRunInput: {
216
+ inputs,
137
217
  projectSource: {
138
218
  type: generated_1.WorkflowProjectSourceType.Gcs,
139
219
  projectArchiveBucketKey,
@@ -226,3 +306,203 @@ async function fileExistsAsync(filePath) {
226
306
  .then(() => true)
227
307
  .catch(() => false);
228
308
  }
309
+ function parseInputs(inputFlags) {
310
+ const inputs = {};
311
+ for (const inputFlag of inputFlags) {
312
+ const equalIndex = inputFlag.indexOf('=');
313
+ if (equalIndex === -1) {
314
+ throw new Error(`Invalid input format: ${inputFlag}. Expected key=value format.`);
315
+ }
316
+ const key = inputFlag.substring(0, equalIndex);
317
+ const value = inputFlag.substring(equalIndex + 1);
318
+ if (!key) {
319
+ throw new Error(`Invalid input format: ${inputFlag}. Key cannot be empty.`);
320
+ }
321
+ inputs[key] = value;
322
+ }
323
+ return inputs;
324
+ }
325
+ exports.parseInputs = parseInputs;
326
+ async function maybeReadStdinAsync() {
327
+ // Check if there's data on stdin
328
+ if (process.stdin.isTTY) {
329
+ return null;
330
+ }
331
+ return await new Promise((resolve, reject) => {
332
+ let data = '';
333
+ process.stdin.setEncoding('utf8');
334
+ process.stdin.on('readable', () => {
335
+ let chunk;
336
+ while ((chunk = process.stdin.read()) !== null) {
337
+ data += chunk;
338
+ }
339
+ });
340
+ process.stdin.on('end', () => {
341
+ const trimmedData = data.trim();
342
+ resolve(trimmedData || null);
343
+ });
344
+ process.stdin.on('error', err => {
345
+ reject(err);
346
+ });
347
+ });
348
+ }
349
+ exports.maybeReadStdinAsync = maybeReadStdinAsync;
350
+ function parseJsonInputs(jsonString) {
351
+ try {
352
+ const parsed = JSON.parse(jsonString);
353
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
354
+ throw new Error('JSON input must be an object.');
355
+ }
356
+ return parsed;
357
+ }
358
+ catch (error) {
359
+ throw new Error(`Invalid JSON input.`, { cause: error });
360
+ }
361
+ }
362
+ exports.parseJsonInputs = parseJsonInputs;
363
+ // `z.coerce.boolean()` does `Boolean(val)` under the hood,
364
+ // which is not what we want. See:
365
+ // https://github.com/colinhacks/zod/issues/2985#issuecomment-2230692578
366
+ const booleanLike = zod_1.z.union([
367
+ zod_1.z.boolean(),
368
+ zod_1.z.number().pipe(zod_1.z.coerce.boolean()),
369
+ zod_1.z.preprocess(val => {
370
+ if (typeof val === 'string') {
371
+ if (val.toLowerCase() === 'true') {
372
+ return true;
373
+ }
374
+ if (val.toLowerCase() === 'false') {
375
+ return false;
376
+ }
377
+ }
378
+ return val;
379
+ }, zod_1.z.boolean()),
380
+ ]);
381
+ const stringLike = zod_1.z
382
+ .union([
383
+ // We're going to coerce numbers and strings into strings.
384
+ zod_1.z.number(),
385
+ zod_1.z.string(),
386
+ // We do not allow other primitives, like:
387
+ // - bigints, symbols - because YAML does not support them,
388
+ // - booleans - because YAML accepts `True` and `true` as boolean input
389
+ // and parses both as JS `true` -- if we stringified that,
390
+ // we would lose the capital "T" which may not be what the user expects,
391
+ // - nulls - user should do `"null"` or not pass the property at all.
392
+ ])
393
+ .pipe(zod_1.z.coerce.string());
394
+ exports.WorkflowDispatchInputZ = zod_1.z
395
+ .object({
396
+ description: stringLike.optional().describe('Description of the input'),
397
+ required: booleanLike.default(false).describe('Whether the input is required'),
398
+ })
399
+ .and(zod_1.z.union([
400
+ zod_1.z.object({
401
+ type: zod_1.z.literal('string').default('string'),
402
+ default: stringLike.optional().describe('Default value for the input'),
403
+ }),
404
+ zod_1.z.object({
405
+ type: zod_1.z.literal('boolean'),
406
+ default: booleanLike.optional().describe('Default value for the input'),
407
+ }),
408
+ zod_1.z.object({
409
+ type: zod_1.z.literal('number'),
410
+ default: zod_1.z.number().optional().describe('Default value for the input'),
411
+ }),
412
+ zod_1.z.object({
413
+ type: zod_1.z.literal('choice'),
414
+ default: stringLike.optional().describe('Default value for the input'),
415
+ options: zod_1.z.array(stringLike).min(1).describe('Options for choice type inputs'),
416
+ }),
417
+ zod_1.z.object({
418
+ type: zod_1.z.literal('environment'),
419
+ default: zod_1.z.string().optional().describe('Default value for the input'),
420
+ }),
421
+ ]));
422
+ function parseWorkflowInputsFromYaml(yamlConfig) {
423
+ try {
424
+ const parsed = YAML.parse(yamlConfig);
425
+ return zod_1.z
426
+ .record(zod_1.z.string(), exports.WorkflowDispatchInputZ)
427
+ .default({})
428
+ .parse(parsed?.on?.workflow_dispatch?.inputs);
429
+ }
430
+ catch (error) {
431
+ log_1.default.warn('Failed to parse workflow inputs from YAML:', error);
432
+ return {};
433
+ }
434
+ }
435
+ exports.parseWorkflowInputsFromYaml = parseWorkflowInputsFromYaml;
436
+ async function maybePromptForMissingInputsAsync({ inputSpecs, inputs, }) {
437
+ const requiredInputs = Object.entries(inputSpecs).filter(([_, spec]) => spec.required);
438
+ const missingRequiredInputs = requiredInputs.filter(([key]) => inputs[key] === undefined);
439
+ if (missingRequiredInputs.length === 0) {
440
+ return inputs;
441
+ }
442
+ log_1.default.addNewLineIfNone();
443
+ log_1.default.log('Some required inputs are missing. Please provide them:');
444
+ const nextInputs = { ...inputs };
445
+ for (const [key, spec] of missingRequiredInputs) {
446
+ const value = await promptForMissingInputAsync({ key, spec });
447
+ nextInputs[key] = value;
448
+ }
449
+ return nextInputs;
450
+ }
451
+ async function promptForMissingInputAsync({ key, spec, }) {
452
+ const message = spec.description ? `${key} (${spec.description})` : key;
453
+ switch (spec.type) {
454
+ case 'boolean': {
455
+ const { value } = await (0, prompts_1.promptAsync)({
456
+ type: 'confirm',
457
+ name: 'value',
458
+ message,
459
+ initial: spec.default,
460
+ });
461
+ return value;
462
+ }
463
+ case 'number': {
464
+ const { value } = await (0, prompts_1.promptAsync)({
465
+ type: 'number',
466
+ name: 'value',
467
+ message,
468
+ initial: spec.default,
469
+ validate: (val) => {
470
+ if (isNaN(val)) {
471
+ return 'Please enter a valid number';
472
+ }
473
+ return true;
474
+ },
475
+ });
476
+ return value;
477
+ }
478
+ case 'choice': {
479
+ const { value } = await (0, prompts_1.promptAsync)({
480
+ type: 'select',
481
+ name: 'value',
482
+ message,
483
+ choices: spec.options.map(option => ({
484
+ title: option,
485
+ value: option,
486
+ })),
487
+ initial: spec.default,
488
+ });
489
+ return value;
490
+ }
491
+ case 'string':
492
+ case 'environment': {
493
+ const { value } = await (0, prompts_1.promptAsync)({
494
+ type: 'text',
495
+ name: 'value',
496
+ message,
497
+ initial: spec.default,
498
+ validate: (val) => {
499
+ if (spec.required && (!val || val.trim() === '')) {
500
+ return 'This field is required';
501
+ }
502
+ return true;
503
+ },
504
+ });
505
+ return value;
506
+ }
507
+ }
508
+ }
@@ -5,7 +5,7 @@ const core_1 = require("@oclif/core");
5
5
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
6
6
  const flags_1 = require("../../commandUtils/flags");
7
7
  const pagination_1 = require("../../commandUtils/pagination");
8
- const workflows_1 = require("../../commandUtils/workflows");
8
+ const utils_1 = require("../../commandUtils/workflow/utils");
9
9
  const generated_1 = require("../../graphql/generated");
10
10
  const AppQuery_1 = require("../../graphql/queries/AppQuery");
11
11
  const WorkflowRunQuery_1 = require("../../graphql/queries/WorkflowRunQuery");
@@ -49,7 +49,7 @@ class WorkflowRunList extends EasCommand_1.default {
49
49
  else {
50
50
  runs = await AppQuery_1.AppQuery.byIdWorkflowRunsFilteredByStatusAsync(graphqlClient, projectId, status, limit);
51
51
  }
52
- const result = (0, workflows_1.processWorkflowRuns)(runs);
52
+ const result = (0, utils_1.processWorkflowRuns)(runs);
53
53
  if (flags.json) {
54
54
  (0, json_1.printJsonOnlyOutput)(result);
55
55
  return;
@@ -62,8 +62,9 @@ class WorkflowRunList extends EasCommand_1.default {
62
62
  { label: 'Status', value: run.status },
63
63
  { label: 'Started At', value: run.startedAt },
64
64
  { label: 'Finished At', value: run.finishedAt },
65
+ { label: 'Trigger Type', value: run.triggerType },
66
+ { label: 'Trigger', value: run.trigger ?? 'null' },
65
67
  { label: 'Git Commit Message', value: run.gitCommitMessage ?? 'null' },
66
- { label: 'Git Commit Hash', value: run.gitCommitHash ?? 'null' },
67
68
  ]));
68
69
  log_1.default.addNewLineIfNone();
69
70
  });
@@ -0,0 +1,17 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class WorkflowView extends EasCommand {
3
+ static description: string;
4
+ static flags: {
5
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
6
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ static args: {
9
+ name: string;
10
+ description: string;
11
+ }[];
12
+ static contextDefinition: {
13
+ loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
14
+ projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
15
+ };
16
+ runAsync(): Promise<void>;
17
+ }