bdy 1.25.7-dev → 1.25.9-dev

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 (31) hide show
  1. package/distTs/package.json +1 -1
  2. package/distTs/src/cliCommand.js +41 -0
  3. package/distTs/src/command/agent/uninstall.js +1 -1
  4. package/distTs/src/command/artifact/delete.js +1 -2
  5. package/distTs/src/command/artifact/version/delete.js +1 -2
  6. package/distTs/src/command/context/remove.js +1 -2
  7. package/distTs/src/command/distro/delete.js +1 -2
  8. package/distTs/src/command/distro/route/delete.js +1 -2
  9. package/distTs/src/command/environment/delete.js +1 -2
  10. package/distTs/src/command/pipeline/delete.js +1 -2
  11. package/distTs/src/command/pipeline/run/approve.js +3 -2
  12. package/distTs/src/command/pipeline/run/cancel.js +3 -2
  13. package/distTs/src/command/pipeline/run/find.js +87 -0
  14. package/distTs/src/command/pipeline/run/findFilters.js +68 -0
  15. package/distTs/src/command/pipeline/run/retry.js +5 -2
  16. package/distTs/src/command/pipeline/run/start.js +3 -2
  17. package/distTs/src/command/pipeline/run/status.js +3 -2
  18. package/distTs/src/command/pipeline/run.js +3 -0
  19. package/distTs/src/command/project/list.js +13 -2
  20. package/distTs/src/command/sandbox/destroy.js +1 -2
  21. package/distTs/src/command/sandbox/endpoint/delete.js +1 -2
  22. package/distTs/src/command/sandbox/exec/kill.js +1 -2
  23. package/distTs/src/command/sandbox/snapshot/delete.js +1 -2
  24. package/distTs/src/command/target/delete.js +1 -1
  25. package/distTs/src/command/target/exec/kill.js +2 -3
  26. package/distTs/src/input.js +48 -6
  27. package/distTs/src/output/pipeline.js +84 -13
  28. package/distTs/src/output.js +17 -0
  29. package/distTs/src/texts.js +156 -31
  30. package/distTs/src/types/pipelineRunFind.js +2 -0
  31. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.25.7-dev",
4
+ "version": "1.25.9-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",
@@ -58,7 +58,11 @@ class CliCommand extends commander_1.Command {
58
58
  constructor(name, metadata = {}) {
59
59
  super(name);
60
60
  this.metadata = metadata;
61
+ // Route options after a subcommand name to that subcommand, including
62
+ // --examples and its format, instead of consuming them in a parent group.
63
+ this.enablePositionalOptions();
61
64
  this.option('--context <name>', texts_1.OPTION_CONTEXT);
65
+ this.option('--examples', texts_1.OPTION_EXAMPLES);
62
66
  }
63
67
  addOption(option) {
64
68
  if (option.long === '--format' && !option.argChoices) {
@@ -71,6 +75,43 @@ class CliCommand extends commander_1.Command {
71
75
  parseOptions(args) {
72
76
  output_1.default.errorFormat = this.defaultErrorFormat;
73
77
  output_1.default.errorExitCode = 1;
78
+ const delimiter = args.indexOf('--');
79
+ const optionArgs = delimiter < 0 ? args : args.slice(0, delimiter);
80
+ const examplesIndex = optionArgs.indexOf('--examples');
81
+ let subcommandBeforeExamples = false;
82
+ for (let i = 0; i < examplesIndex; i += 1) {
83
+ const arg = optionArgs[i];
84
+ const option = this.options.find((item) => item.long === arg || item.short === arg);
85
+ if (option?.required || option?.optional) {
86
+ i += 1;
87
+ }
88
+ else if (this.commands.some((child) => child.name() === arg || child.aliases().includes(arg))) {
89
+ subcommandBeforeExamples = true;
90
+ break;
91
+ }
92
+ }
93
+ if (examplesIndex >= 0 &&
94
+ !optionArgs.includes('--help') &&
95
+ !optionArgs.includes('-h') &&
96
+ !subcommandBeforeExamples) {
97
+ const formats = optionArgs.flatMap((arg, index) => arg === '--format'
98
+ ? [optionArgs[index + 1]]
99
+ : arg.startsWith('--format=')
100
+ ? [arg.slice('--format='.length)]
101
+ : []);
102
+ const format = formats.length ? formats.at(-1) : 'text';
103
+ if (typeof format !== 'string' || !['text', 'json', 'jsonl'].includes(format)) {
104
+ this.error(`Invalid examples format '${format}'. Choose text, json or jsonl.`);
105
+ }
106
+ const path = [this.name()];
107
+ let parent = this.parent;
108
+ while (parent) {
109
+ path.unshift(parent.name());
110
+ parent = parent.parent;
111
+ }
112
+ output_1.default.examples(path.join(' '), this.examples, format);
113
+ output_1.default.exitNormal();
114
+ }
74
115
  const formatOption = this.options.find((option) => option.long === '--format');
75
116
  const exitCodeOption = this.options.some((option) => option.long === '--exit-code');
76
117
  if ((formatOption && this.defaultErrorFormat === 'text') ||
@@ -16,7 +16,7 @@ commandAgentUninstall.action(async (options) => {
16
16
  if (!hasRights) {
17
17
  output_1.default.exitError(texts_1.ERR_AGENT_ADMIN_RIGHTS);
18
18
  }
19
- const confirmed = options.force || (await output_1.default.confirm(texts_1.TXY_AGENT_CONFIRM_DELETE));
19
+ const confirmed = await output_1.default.confirmDestructive(options.force, texts_1.TXY_AGENT_CONFIRM_DELETE);
20
20
  if (!confirmed)
21
21
  output_1.default.exitNormal();
22
22
  try {
@@ -30,8 +30,7 @@ commandArtifactDelete.action(async (identifier, options) => {
30
30
  if (!data.artifact_id) {
31
31
  output_1.default.exitError(texts_1.ERR_ARTIFACT_NOT_FOUND);
32
32
  }
33
- const confirmed = options.force ||
34
- (await output_1.default.confirm((0, texts_1.TXT_ARTIFACT_DELETE_CONFIRM)(identifier)));
33
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_ARTIFACT_DELETE_CONFIRM)(identifier));
35
34
  if (confirmed) {
36
35
  await client.deleteArtifact(workspace, data.artifact_id);
37
36
  output_1.default.exitSuccess(texts_1.TXT_ARTIFACT_DELETED);
@@ -34,8 +34,7 @@ commandArtifactVersionDelete.action(async (identifier, version, options) => {
34
34
  if (!data || !data.artifact_version_id) {
35
35
  output_1.default.exitError(texts_1.ERR_ARTIFACT_VERSION_NOT_FOUND);
36
36
  }
37
- const confirmed = options.force ||
38
- (await output_1.default.confirm((0, texts_1.TXT_ARTIFACT_VERSION_DELETE_CONFIRM)(identifier, version)));
37
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_ARTIFACT_VERSION_DELETE_CONFIRM)(identifier, version));
39
38
  if (!confirmed)
40
39
  output_1.default.exitNormal();
41
40
  await client.deleteArtifactVersion(workspace, data.artifact_id, data.artifact_version_id);
@@ -21,8 +21,7 @@ command.option('-f, --force', texts_1.OPTION_CONFIRM_FORCE);
21
21
  command.action(async (name, options) => {
22
22
  input_1.default.contextEditableName(name);
23
23
  cfg_1.default.getContext(name);
24
- const confirmed = options.force ||
25
- (await output_1.default.confirm((0, texts_1.TXT_CONTEXT_REMOVE_CONFIRM)(name), options.format === 'json'));
24
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_CONTEXT_REMOVE_CONFIRM)(name), options.format === 'json');
26
25
  if (confirmed)
27
26
  cfg_1.default.removeContext(name);
28
27
  if (options.format === 'json')
@@ -30,8 +30,7 @@ commandDistroDelete.action(async (identifier, options) => {
30
30
  if (!data || !data.distribution_id) {
31
31
  output_1.default.exitError(texts_1.ERR_COMMAND_DISTRO_NOT_FOUND);
32
32
  }
33
- const confirmed = options.force ||
34
- (await output_1.default.confirm((0, texts_1.TXT_COMMAND_DISTRO_DELETE_CONFIRM)(identifier)));
33
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_COMMAND_DISTRO_DELETE_CONFIRM)(identifier));
35
34
  if (confirmed) {
36
35
  await client.deleteDistribution(workspace, scope === distro_1.SCOPE.PROJECT ? project : null, data.distribution_id);
37
36
  output_1.default.exitSuccess(texts_1.TXT_COMMAND_DISTRO_DELETED);
@@ -31,8 +31,7 @@ commandDistroRouteDelete.action(async (identifier, routeId, options) => {
31
31
  if (!data?.distribution_id) {
32
32
  output_1.default.exitError(texts_1.ERR_COMMAND_DISTRO_NOT_FOUND);
33
33
  }
34
- const confirmed = options.force ||
35
- (await output_1.default.confirm((0, texts_1.TXT_COMMAND_ROUTE_DELETE_CONFIRM)(identifier, routeId)));
34
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_COMMAND_ROUTE_DELETE_CONFIRM)(identifier, routeId));
36
35
  if (confirmed) {
37
36
  await client.deleteRoute(workspace, scope === distro_1.SCOPE.PROJECT ? project : null, data.distribution_id, routeId);
38
37
  output_1.default.exitSuccess(texts_1.TXT_COMMAND_ROUTE_DELETED);
@@ -18,8 +18,7 @@ commandEnvironmentDelete.action(async (identifier, options) => {
18
18
  const client = input_1.default.restApiTokenClient();
19
19
  const environment_id = await input_1.default.environmentId(client, workspace, identifier, options,
20
20
  /* strictProject */ true);
21
- const confirmed = options.force ||
22
- (await output_1.default.confirm((0, texts_1.TXT_ENVIRONMENT_DELETE_CONFIRM)(identifier)));
21
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_ENVIRONMENT_DELETE_CONFIRM)(identifier));
23
22
  if (!confirmed)
24
23
  output_1.default.exitNormal();
25
24
  await client.deleteEnvironment(workspace, environment_id);
@@ -30,8 +30,7 @@ commandPipelineDelete.action(async (identifier, options) => {
30
30
  if (!data.pipeline_id) {
31
31
  output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
32
32
  }
33
- const confirmed = options.force ||
34
- (await output_1.default.confirm((0, texts_1.TXT_PIPELINE_DELETE_CONFIRM)(identifier)));
33
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_PIPELINE_DELETE_CONFIRM)(identifier));
35
34
  if (confirmed) {
36
35
  await client.deletePipeline(workspace, project, data.pipeline_id);
37
36
  output_1.default.exitSuccess(texts_1.TXT_PIPELINE_DELETED);
@@ -12,13 +12,14 @@ const pipeline_1 = require("../../../types/pipeline");
12
12
  const commandPipelineRunApprove = (0, utils_1.newCommand)('approve', texts_1.DESC_COMMAND_PIPELINE_RUN_APPLY, {
13
13
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_RUN],
14
14
  examples: texts_1.EXAMPLE_PIPELINE_RUN_APPLY,
15
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
15
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
16
16
  });
17
17
  commandPipelineRunApprove.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
18
18
  commandPipelineRunApprove.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
19
19
  commandPipelineRunApprove.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
20
20
  commandPipelineRunApprove.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
21
21
  commandPipelineRunApprove.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
22
+ commandPipelineRunApprove.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
22
23
  commandPipelineRunApprove.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
23
24
  commandPipelineRunApprove.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
24
25
  commandPipelineRunApprove.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
@@ -55,6 +56,6 @@ commandPipelineRunApprove.action(async (identifier, runId, runActionId, options)
55
56
  };
56
57
  await client.pipelineRunApply(workspace, project, pipelineId, rid, body);
57
58
  const OutputPipeline = require('../../../output/pipeline').default;
58
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
59
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
59
60
  });
60
61
  exports.default = commandPipelineRunApprove;
@@ -10,13 +10,14 @@ const execution_1 = require("./execution");
10
10
  const commandPipelineRunCancel = (0, utils_1.newCommand)('cancel', texts_1.DESC_COMMAND_PIPELINE_RUN_CANCEL, {
11
11
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_RUN],
12
12
  examples: texts_1.EXAMPLE_PIPELINE_RUN_CANCEL,
13
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
13
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
14
14
  });
15
15
  commandPipelineRunCancel.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
16
16
  commandPipelineRunCancel.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
17
17
  commandPipelineRunCancel.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
18
18
  commandPipelineRunCancel.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
19
19
  commandPipelineRunCancel.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
20
+ commandPipelineRunCancel.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
20
21
  commandPipelineRunCancel.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
21
22
  commandPipelineRunCancel.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
22
23
  commandPipelineRunCancel.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
@@ -28,6 +29,6 @@ commandPipelineRunCancel.action(async (identifier, runId, options) => {
28
29
  const pipelineId = await (0, execution_1.resolvePipelineId)(client, workspace, project, identifier);
29
30
  await client.pipelineRunCancel(workspace, project, pipelineId, rid);
30
31
  const OutputPipeline = require('../../../output/pipeline').default;
31
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
32
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
32
33
  });
33
34
  exports.default = commandPipelineRunCancel;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../../utils");
7
+ const input_1 = __importDefault(require("../../../input"));
8
+ const output_1 = __importDefault(require("../../../output"));
9
+ const execution_1 = require("./execution");
10
+ const findFilters_1 = require("./findFilters");
11
+ const texts_1 = require("../../../texts");
12
+ const command = (0, utils_1.newCommand)('find', texts_1.DESC_COMMAND_PIPELINE_RUN_FIND, {
13
+ requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_READ],
14
+ examples: texts_1.EXAMPLE_PIPELINE_RUN_FIND,
15
+ helpText: texts_1.HELP_PIPELINE_RUN_FIND,
16
+ });
17
+ command.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
18
+ command.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
19
+ command.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
20
+ command.option('--last <number>', texts_1.OPTION_PIPELINE_RUN_FIND_LAST, '100');
21
+ for (const { flag, argument, description } of findFilters_1.pipelineRunFindFilters) {
22
+ command.option(`${flag} ${argument}`, description);
23
+ }
24
+ command.option('--format <text|json>', texts_1.OPTION_FORMAT);
25
+ command.action(async (identifier, options) => {
26
+ const { last, filters } = input_1.default.pipelineRunFind(options);
27
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
28
+ const project = input_1.default.restApiProject(options.project);
29
+ const client = input_1.default.restApiTokenClient();
30
+ const pipelineId = await (0, execution_1.resolvePipelineId)(client, workspace, project, identifier);
31
+ const executions = [];
32
+ // Keep page size fixed: changing it on the last request changes page offsets.
33
+ const perPage = Math.min(last, 100);
34
+ const seen = new Set();
35
+ let scanned = 0;
36
+ let fetched = 0;
37
+ let hasMore = false;
38
+ for (let page = 1; scanned < last; page += 1) {
39
+ const result = await client.getPipelineRuns(workspace, project, pipelineId, page, perPage);
40
+ const batch = result.executions;
41
+ fetched += batch.length;
42
+ let hasMoreInBatch = false;
43
+ for (const run of batch) {
44
+ // New runs shift page offsets; repeated IDs must not consume the window.
45
+ if (seen.has(run.id))
46
+ continue;
47
+ if (scanned === last) {
48
+ hasMoreInBatch = true;
49
+ break;
50
+ }
51
+ seen.add(run.id);
52
+ scanned += 1;
53
+ if (findFilters_1.pipelineRunFindFilters.every(({ key, pick }) => {
54
+ const value = filters[key];
55
+ return value === undefined || pick(run).includes(value);
56
+ }))
57
+ executions.push(run);
58
+ }
59
+ if (!batch.length) {
60
+ hasMore = false;
61
+ break;
62
+ }
63
+ // Compare pagination progress (including duplicates) with the current total.
64
+ // total_page_count may be absent or based on an uncapped size.
65
+ const total = result.total_element_count;
66
+ const hasTotal = typeof total === 'number' && Number.isInteger(total) && total >= 0;
67
+ hasMore = hasMoreInBatch || !hasTotal || fetched < total;
68
+ if (!hasMore)
69
+ break;
70
+ if (scanned === last && !hasTotal && !hasMoreInBatch) {
71
+ // Without a total, probe for existence only. These runs are not searched
72
+ // or included in scanned; even a short page does not prove exhaustion.
73
+ const next = await client.getPipelineRuns(workspace, project, pipelineId, page + 1, perPage);
74
+ hasMore = next.executions.some((run) => !seen.has(run.id));
75
+ }
76
+ }
77
+ executions.sort((a, b) => b.id - a.id);
78
+ const result = { last, scanned, has_more: hasMore, executions };
79
+ if (options.format === 'json')
80
+ output_1.default.json(result);
81
+ else {
82
+ const OutputPipeline = require('../../../output/pipeline').default;
83
+ OutputPipeline.findRuns(result);
84
+ }
85
+ output_1.default.exitNormal();
86
+ });
87
+ exports.default = command;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pipelineRunFindFilters = void 0;
4
+ const texts_1 = require("../../../texts");
5
+ /** One source for CLI options, validation names, filter types and matching. */
6
+ exports.pipelineRunFindFilters = [
7
+ {
8
+ key: 'branch',
9
+ flag: '--branch',
10
+ argument: '<name>',
11
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_BRANCH,
12
+ pick: (run) => [run.branch?.name],
13
+ },
14
+ {
15
+ key: 'tag',
16
+ flag: '--tag',
17
+ argument: '<name>',
18
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_TAG,
19
+ pick: (run) => [run.tag?.name],
20
+ },
21
+ {
22
+ key: 'pr',
23
+ flag: '--pr',
24
+ argument: '<number>',
25
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_PR,
26
+ pick: (run) => [run.pull_request?.name],
27
+ },
28
+ {
29
+ key: 'revision',
30
+ flag: '--revision',
31
+ argument: '<revision>',
32
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_REVISION,
33
+ pick: (run) => [run.to_revision?.revision],
34
+ },
35
+ {
36
+ key: 'fromRevision',
37
+ flag: '--from-revision',
38
+ argument: '<revision>',
39
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_FROM_REVISION,
40
+ pick: (run) => [run.from_revision?.revision],
41
+ },
42
+ {
43
+ key: 'environment',
44
+ flag: '--environment',
45
+ argument: '<identifier>',
46
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_ENVIRONMENT,
47
+ pick: (run) => [run.environment?.identifier],
48
+ },
49
+ {
50
+ key: 'artifact',
51
+ flag: '--artifact',
52
+ argument: '<identifier[:version]>',
53
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_ARTIFACT,
54
+ pick: (run) => [
55
+ run.artifact?.identifier,
56
+ run.artifact?.identifier && run.artifact_version?.version
57
+ ? `${run.artifact.identifier}:${run.artifact_version.version}`
58
+ : undefined,
59
+ ],
60
+ },
61
+ {
62
+ key: 'status',
63
+ flag: '--status',
64
+ argument: '<status>',
65
+ description: texts_1.OPTION_PIPELINE_RUN_FIND_STATUS,
66
+ pick: (run) => [run.status],
67
+ },
68
+ ];
@@ -10,13 +10,16 @@ const execution_1 = require("./execution");
10
10
  const commandPipelineRunRetry = (0, utils_1.newCommand)('retry', texts_1.DESC_COMMAND_PIPELINE_RUN_RETRY, {
11
11
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_RUN],
12
12
  examples: texts_1.EXAMPLE_PIPELINE_RUN_RETRY,
13
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
13
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS +
14
+ texts_1.HELP_PIPELINE_RUN_FAILED_LOGS +
15
+ texts_1.HELP_PIPELINE_RUN_RETRY,
14
16
  });
15
17
  commandPipelineRunRetry.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
16
18
  commandPipelineRunRetry.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
17
19
  commandPipelineRunRetry.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
18
20
  commandPipelineRunRetry.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
19
21
  commandPipelineRunRetry.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
22
+ commandPipelineRunRetry.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
20
23
  commandPipelineRunRetry.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
21
24
  commandPipelineRunRetry.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
22
25
  commandPipelineRunRetry.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
@@ -28,6 +31,6 @@ commandPipelineRunRetry.action(async (identifier, runId, options) => {
28
31
  const pipelineId = await (0, execution_1.resolvePipelineId)(client, workspace, project, identifier);
29
32
  await client.pipelineRunRetry(workspace, project, pipelineId, rid);
30
33
  const OutputPipeline = require('../../../output/pipeline').default;
31
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
34
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
32
35
  });
33
36
  exports.default = commandPipelineRunRetry;
@@ -14,7 +14,7 @@ const client_1 = require("../../../api/client");
14
14
  const commandPipelineRunStart = (0, utils_1.newCommand)('start', texts_1.DESC_COMMAND_PIPELINE_RUN_START, {
15
15
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_RUN],
16
16
  examples: texts_1.EXAMPLE_PIPELINE_RUN_START,
17
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
17
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
18
18
  });
19
19
  commandPipelineRunStart.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
20
20
  commandPipelineRunStart.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
@@ -40,6 +40,7 @@ commandPipelineRunStart.option('--action <actions...>', texts_1.OPTION_PIPELINE_
40
40
  commandPipelineRunStart.option('-n,--no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
41
41
  commandPipelineRunStart.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
42
42
  commandPipelineRunStart.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
43
+ commandPipelineRunStart.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
43
44
  commandPipelineRunStart.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
44
45
  commandPipelineRunStart.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
45
46
  commandPipelineRunStart.usage('<identifier> [options]');
@@ -190,6 +191,6 @@ commandPipelineRunStart.action(async (identifier, options) => {
190
191
  body.payload_files = await uploadPayloadFiles(client, workspace, project, pipelineId, options.payload);
191
192
  const result = await client.pipelineRun(workspace, project, pipelineId, body);
192
193
  const OutputPipeline = require('../../../output/pipeline').default;
193
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, result.id, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
194
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, result.id, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
194
195
  });
195
196
  exports.default = commandPipelineRunStart;
@@ -10,13 +10,14 @@ const execution_1 = require("./execution");
10
10
  const commandPipelineRunStatus = (0, utils_1.newCommand)('status', texts_1.DESC_COMMAND_PIPELINE_RUN_STATUS, {
11
11
  requiredScopes: [utils_1.REST_API_SCOPE.PIPELINE_READ],
12
12
  examples: texts_1.EXAMPLE_PIPELINE_RUN_STATUS,
13
- helpText: texts_1.HELP_PIPELINE_RUN_STATUS,
13
+ helpText: texts_1.HELP_PIPELINE_RUN_STATUS + texts_1.HELP_PIPELINE_RUN_FAILED_LOGS,
14
14
  });
15
15
  commandPipelineRunStatus.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
16
16
  commandPipelineRunStatus.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
17
17
  commandPipelineRunStatus.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
18
18
  commandPipelineRunStatus.option('--no-follow', texts_1.OPTION_PIPELINE_RUN_NO_FOLLOW);
19
19
  commandPipelineRunStatus.option('--exit-code', texts_1.OPTION_EXEC_EXIT_CODE);
20
+ commandPipelineRunStatus.option('--failed-logs', texts_1.OPTION_PIPELINE_RUN_FAILED_LOGS);
20
21
  commandPipelineRunStatus.option('--format <text|jsonl>', texts_1.OPTION_EXEC_FORMAT_JSONL);
21
22
  commandPipelineRunStatus.argument('<identifier>', texts_1.OPTION_PIPELINE_IDENTIFIER);
22
23
  commandPipelineRunStatus.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
@@ -27,6 +28,6 @@ commandPipelineRunStatus.action(async (identifier, runId, options) => {
27
28
  const rid = input_1.default.pipelineRunId(runId);
28
29
  const pipelineId = await (0, execution_1.resolvePipelineId)(client, workspace, project, identifier);
29
30
  const OutputPipeline = require('../../../output/pipeline').default;
30
- await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode);
31
+ await OutputPipeline.runStatus(client, workspace, project, identifier, pipelineId, rid, !options.wait, !options.follow, options.format === 'jsonl', !!options.exitCode, !!options.failedLogs);
31
32
  });
32
33
  exports.default = commandPipelineRunStatus;
@@ -11,6 +11,7 @@ const logs_1 = __importDefault(require("./run/logs"));
11
11
  const cancel_1 = __importDefault(require("./run/cancel"));
12
12
  const retry_1 = __importDefault(require("./run/retry"));
13
13
  const list_1 = __importDefault(require("./run/list"));
14
+ const find_1 = __importDefault(require("./run/find"));
14
15
  const approve_1 = __importDefault(require("./run/approve"));
15
16
  const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_PIPELINE_RUN, {
16
17
  examples: [
@@ -21,6 +22,7 @@ const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_P
21
22
  ...texts_1.EXAMPLE_PIPELINE_RUN_RETRY,
22
23
  ...texts_1.EXAMPLE_PIPELINE_RUN_APPLY,
23
24
  ...texts_1.EXAMPLE_PIPELINE_RUN_LIST,
25
+ ...texts_1.EXAMPLE_PIPELINE_RUN_FIND,
24
26
  ],
25
27
  });
26
28
  commandPipelineRun.addCommand(start_1.default);
@@ -30,4 +32,5 @@ commandPipelineRun.addCommand(cancel_1.default);
30
32
  commandPipelineRun.addCommand(retry_1.default);
31
33
  commandPipelineRun.addCommand(approve_1.default);
32
34
  commandPipelineRun.addCommand(list_1.default);
35
+ commandPipelineRun.addCommand(find_1.default);
33
36
  exports.default = commandPipelineRun;
@@ -7,20 +7,31 @@ const output_1 = __importDefault(require("../../output"));
7
7
  const texts_1 = require("../../texts");
8
8
  const utils_1 = require("../../utils");
9
9
  const input_1 = __importDefault(require("../../input"));
10
- const commandProjectList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_PROJECT_LIST);
10
+ const commandProjectList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_PROJECT_LIST, {
11
+ helpText: texts_1.HELP_PROJECT_LIST_PAGINATION,
12
+ });
11
13
  commandProjectList.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
12
14
  commandProjectList.alias('ls');
15
+ commandProjectList.option('--page <number>', texts_1.OPTION_REST_API_PAGE);
16
+ commandProjectList.option('--per-page <number>', texts_1.OPTION_REST_API_PER_PAGE);
13
17
  commandProjectList.option('--format <text|json>', texts_1.OPTION_FORMAT);
14
18
  commandProjectList.action(async (options) => {
19
+ const paginated = options.page !== undefined || options.perPage !== undefined;
20
+ const page = paginated ? input_1.default.restApiPage(options.page) : 1;
21
+ const perPage = paginated ? input_1.default.restApiPerPage(options.perPage) : 10;
15
22
  const workspace = input_1.default.restApiWorkspace(options.workspace);
16
23
  const client = input_1.default.restApiTokenClient();
17
- const response = await client.getAllProjects(workspace);
24
+ const response = paginated
25
+ ? await client.getProjects(workspace, page, perPage)
26
+ : await client.getAllProjects(workspace);
18
27
  const projects = response.projects || [];
19
28
  if (options.format === 'json') {
20
29
  output_1.default.json(projects);
21
30
  }
22
31
  else {
23
32
  if (projects.length === 0) {
33
+ if (paginated)
34
+ output_1.default.exitNormal(texts_1.TXT_PROJECT_PAGE_EMPTY);
24
35
  output_1.default.exitError(texts_1.ERR_PROJECT_NO_PROJECTS);
25
36
  }
26
37
  const data = [['NAME', 'DISPLAY NAME', 'STATUS', 'URL']];
@@ -16,8 +16,7 @@ commandSandboxDestroy.action(async (identifier, options) => {
16
16
  const workspace = input_1.default.restApiWorkspace(options.workspace);
17
17
  const client = input_1.default.restApiTokenClient();
18
18
  const sandboxId = await input_1.default.sandboxId(client, workspace, options, identifier);
19
- const confirmed = options.force ||
20
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_DESTROY_CONFIRM)(identifier)));
19
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_DESTROY_CONFIRM)(identifier));
21
20
  if (!confirmed)
22
21
  output_1.default.exitNormal();
23
22
  await client.deleteSandbox(workspace, sandboxId);
@@ -24,8 +24,7 @@ commandSandboxEndpointDelete.action(async (identifier, endpointName, options) =>
24
24
  output_1.default.exitError(texts_1.ERR_SANDBOX_ENDPOINT_NOT_FOUND);
25
25
  }
26
26
  const updatedEndpoints = endpoints.filter((ep) => ep.name !== endpointName);
27
- const confirmed = options.force ||
28
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_ENDPOINT_DELETE_CONFIRM)(identifier, endpointName)));
27
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_ENDPOINT_DELETE_CONFIRM)(identifier, endpointName));
29
28
  if (!confirmed)
30
29
  output_1.default.exitNormal();
31
30
  await client.updateSandbox(workspace, sandboxId, {
@@ -16,8 +16,7 @@ commandSandboxExecKill.action(async (identifier, commandId, options) => {
16
16
  const workspace = input_1.default.restApiWorkspace(options.workspace);
17
17
  const client = input_1.default.restApiTokenClient();
18
18
  const sandboxId = await input_1.default.sandboxId(client, workspace, options, identifier);
19
- const confirmed = options.force ||
20
- (await output_1.default.confirm((0, texts_1.OPTION_SANDBOX_COMMAND_KILL_CONFIRM)(identifier, commandId)));
19
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.OPTION_SANDBOX_COMMAND_KILL_CONFIRM)(identifier, commandId));
21
20
  if (!confirmed)
22
21
  output_1.default.exitNormal();
23
22
  await client.terminateSandboxCommand(workspace, sandboxId, commandId);
@@ -23,8 +23,7 @@ commandSandboxSnapshotDelete.action(async (identifier, snapshotName, options) =>
23
23
  if (!foundSnapshot) {
24
24
  output_1.default.exitError(texts_1.ERR_SANDBOX_SNAPSHOT_NOT_FOUND);
25
25
  }
26
- const confirmed = options.force ||
27
- (await output_1.default.confirm((0, texts_1.TXT_SANDBOX_SNAPSHOT_DELETE_CONFIRM)(identifier, snapshotName)));
26
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_SANDBOX_SNAPSHOT_DELETE_CONFIRM)(identifier, snapshotName));
28
27
  if (!confirmed)
29
28
  output_1.default.exitNormal();
30
29
  await client.deleteSandboxSnapshot(workspace, sandboxId, foundSnapshot.id);
@@ -23,7 +23,7 @@ commandTargetDelete.action(async (identifier, options) => {
23
23
  const client = input_1.default.restApiTokenClient();
24
24
  const target_id = await (0, scope_1.resolveTargetId)(client, workspace, identifier, options,
25
25
  /* strictLine */ true);
26
- const confirmed = options.force || (await output_1.default.confirm((0, texts_1.TXT_TARGET_DELETE_CONFIRM)(identifier)));
26
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_TARGET_DELETE_CONFIRM)(identifier));
27
27
  if (!confirmed)
28
28
  output_1.default.exitNormal();
29
29
  await client.deleteTarget(workspace, target_id);
@@ -16,12 +16,11 @@ commandTargetExecKill.action(async (execId, options) => {
16
16
  const client = input_1.default.restApiTokenClient();
17
17
  // Resolve the exec before the prompt so a bad id fails the same way
18
18
  // (Resource not found, exit 1) with and without --force - otherwise the
19
- // auto-declined prompt exits 0 without ever checking the id. With --force
19
+ // confirmation error would hide the invalid id. With --force
20
20
  // the DELETE itself surfaces the 404, so the extra request is skipped.
21
21
  if (!options.force)
22
22
  await client.getTargetExec(workspace, execId);
23
- const confirmed = options.force ||
24
- (await output_1.default.confirm((0, texts_1.TXT_TARGET_EXEC_KILL_CONFIRM)(execId)));
23
+ const confirmed = await output_1.default.confirmDestructive(options.force, (0, texts_1.TXT_TARGET_EXEC_KILL_CONFIRM)(execId));
25
24
  if (!confirmed)
26
25
  output_1.default.exitNormal();
27
26
  await client.cancelTargetExec(workspace, execId);