@copado/agentia-cli 1.0.0 → 1.2.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 (226) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +2252 -1529
  3. package/dist/commands/ai/agent/ask.js +4 -4
  4. package/dist/commands/ai/agent/chat.js +4 -4
  5. package/dist/commands/cicd/cloud/commit.js +7 -2
  6. package/dist/commands/cicd/credential/auth/status.js +38 -0
  7. package/dist/commands/cicd/credential/auth/web/login.js +54 -0
  8. package/dist/commands/cicd/credential/list.js +13 -17
  9. package/dist/commands/cicd/credential/open.js +30 -0
  10. package/dist/commands/cicd/credential/update.js +9 -12
  11. package/dist/commands/cicd/environment/auth/status.js +34 -13
  12. package/dist/commands/cicd/environment/auth/web/login.js +20 -4
  13. package/dist/commands/cicd/environment/open.js +6 -22
  14. package/dist/commands/cicd/extension/create.js +53 -0
  15. package/dist/commands/cicd/extension/install.js +127 -0
  16. package/dist/commands/cicd/extension/package.js +35 -0
  17. package/dist/commands/cicd/extension/publish.js +61 -0
  18. package/dist/commands/cicd/extension/uninstall.js +99 -0
  19. package/dist/commands/cicd/extension/validate.js +47 -0
  20. package/dist/commands/cicd/extension-configuration/get.js +24 -0
  21. package/dist/commands/cicd/extension-configuration/list.js +49 -0
  22. package/dist/commands/cicd/extension-configuration/open.js +38 -0
  23. package/dist/commands/cicd/metadata/content/get.js +1 -1
  24. package/dist/commands/cicd/metadata/dependency/list.js +2 -2
  25. package/dist/commands/cicd/metadata/explore.js +81 -0
  26. package/dist/commands/cicd/metadata/list.js +3 -3
  27. package/dist/commands/cicd/metadata/refresh/deleted.js +1 -1
  28. package/dist/commands/cicd/metadata/refresh/run.js +2 -2
  29. package/dist/commands/cicd/metadata/refresh/status.js +2 -2
  30. package/dist/commands/cicd/pipeline/automation/activate.js +39 -0
  31. package/dist/commands/cicd/pipeline/automation/create.js +33 -0
  32. package/dist/commands/cicd/pipeline/automation/deactivate.js +39 -0
  33. package/dist/commands/cicd/pipeline/automation/delete.js +45 -0
  34. package/dist/commands/cicd/pipeline/automation/get.js +32 -0
  35. package/dist/commands/cicd/pipeline/automation/list.js +38 -0
  36. package/dist/commands/cicd/pipeline/automation/open.js +38 -0
  37. package/dist/commands/cicd/pipeline/automation/update.js +38 -0
  38. package/dist/commands/cicd/pipeline/quality-gate/activate.js +39 -0
  39. package/dist/commands/cicd/pipeline/quality-gate/create.js +34 -0
  40. package/dist/commands/cicd/pipeline/quality-gate/deactivate.js +39 -0
  41. package/dist/commands/cicd/pipeline/quality-gate/delete.js +45 -0
  42. package/dist/commands/cicd/pipeline/quality-gate/get.js +32 -0
  43. package/dist/commands/cicd/pipeline/quality-gate/list.js +34 -0
  44. package/dist/commands/cicd/pipeline/quality-gate/open.js +38 -0
  45. package/dist/commands/cicd/pipeline/quality-gate/update.js +38 -0
  46. package/dist/commands/cicd/work/create.js +1 -0
  47. package/dist/commands/cicd/work/environment-sync.js +8 -7
  48. package/dist/commands/cicd/work/get.js +18 -2
  49. package/dist/commands/cicd/work/set.js +6 -4
  50. package/dist/commands/cicd/work/submit.js +3 -2
  51. package/dist/commands/cicd/work/update.js +1 -0
  52. package/dist/commands/plugins/install.js +2 -5
  53. package/dist/commands/setup/skills/create.js +29 -3
  54. package/dist/commands/setup/skills/list.js +55 -0
  55. package/dist/commands/setup/skills/update.js +37 -4
  56. package/dist/commands/setup.js +3 -3
  57. package/dist/commands/testing/data-table/create.js +1 -2
  58. package/dist/commands/testing/data-table/delete.js +1 -2
  59. package/dist/commands/testing/data-table/export.js +2 -6
  60. package/dist/commands/testing/data-table/get.js +2 -4
  61. package/dist/commands/testing/data-table/list.js +1 -2
  62. package/dist/commands/testing/data-table/update.js +3 -4
  63. package/dist/commands/testing/job/create.js +26 -22
  64. package/dist/commands/testing/job/delete.js +2 -2
  65. package/dist/commands/testing/job/files/download.js +73 -0
  66. package/dist/commands/testing/job/files/list.js +43 -0
  67. package/dist/commands/testing/job/{upload.js → files/upload.js} +13 -9
  68. package/dist/commands/testing/job/get.js +2 -2
  69. package/dist/commands/testing/job/list.js +1 -1
  70. package/dist/commands/testing/job/refs.js +4 -4
  71. package/dist/commands/testing/job/run.js +134 -1
  72. package/dist/commands/testing/{build → job/runs}/abort.js +10 -8
  73. package/dist/commands/testing/job/runs/get.js +42 -0
  74. package/dist/commands/testing/{build → job/runs}/list.js +19 -10
  75. package/dist/commands/testing/{logs.js → job/runs/logs.js} +9 -6
  76. package/dist/commands/testing/{build → job/runs}/search.js +9 -7
  77. package/dist/commands/testing/job/schedule/get.js +5 -11
  78. package/dist/commands/testing/job/schedule/remove.js +3 -3
  79. package/dist/commands/testing/job/schedule/set.js +3 -3
  80. package/dist/commands/testing/job/update.js +22 -65
  81. package/dist/commands/testing/live/continue.js +5 -10
  82. package/dist/commands/testing/live/execute.js +3 -3
  83. package/dist/commands/testing/live/history.js +7 -2
  84. package/dist/commands/testing/live/inspect.js +5 -4
  85. package/dist/commands/testing/live/interrupt.js +5 -10
  86. package/dist/commands/testing/live/recorder.js +23 -115
  87. package/dist/commands/testing/live/reports.js +3 -3
  88. package/dist/commands/testing/live/screenshot.js +3 -3
  89. package/dist/commands/testing/live/set-options.js +11 -4
  90. package/dist/commands/testing/live/start.js +9 -4
  91. package/dist/commands/testing/live/status.js +2 -5
  92. package/dist/commands/testing/live/stop.js +3 -5
  93. package/dist/commands/testing/live/view.js +2 -2
  94. package/dist/commands/testing/project/create.js +1 -17
  95. package/dist/commands/testing/project/get.js +0 -1
  96. package/dist/commands/testing/project/list.js +2 -2
  97. package/dist/commands/testing/project/permission/set.js +3 -7
  98. package/dist/commands/testing/project/permission/update.js +2 -2
  99. package/dist/commands/testing/robot/create.js +22 -25
  100. package/dist/commands/testing/robot/get.js +1 -1
  101. package/dist/commands/testing/robot/list.js +3 -3
  102. package/dist/commands/testing/robot/update.js +3 -3
  103. package/dist/commands/testing/user-parameter/create.js +3 -9
  104. package/dist/commands/testing/user-parameter/update.js +1 -7
  105. package/dist/commands/testing/variable/create.js +4 -9
  106. package/dist/commands/testing/variable/list.js +3 -3
  107. package/dist/commands/testing/variable/update.js +5 -12
  108. package/dist/help.js +17 -0
  109. package/dist/lib/ai-types.js +2 -1
  110. package/dist/lib/claude-mcp-config.js +15 -0
  111. package/dist/lib/credential-sync.js +1 -2
  112. package/dist/lib/defaults-store.js +4 -1
  113. package/dist/lib/environment-auth-status.js +2 -1
  114. package/dist/lib/environment-auth.js +2 -1
  115. package/dist/lib/environment-credential-flags.js +3 -1
  116. package/dist/lib/environment-credential-operations.js +8 -2
  117. package/dist/lib/environment-types.js +3 -1
  118. package/dist/lib/extension/assets.js +4 -0
  119. package/dist/lib/extension/create.js +3 -0
  120. package/dist/lib/extension/git.js +17 -0
  121. package/dist/lib/extension/index.js +27 -0
  122. package/dist/lib/extension/install.js +4 -0
  123. package/dist/lib/extension/manifest.js +21 -0
  124. package/dist/lib/extension/package.js +3 -0
  125. package/dist/lib/extension/paths.js +5 -0
  126. package/dist/lib/extension/publish.js +3 -0
  127. package/dist/lib/extension/sf-deploy.js +8 -0
  128. package/dist/lib/extension/source.js +7 -0
  129. package/dist/lib/extension/uninstall.js +3 -0
  130. package/dist/lib/extension-configuration-ops.js +4 -0
  131. package/dist/lib/extension-configuration-sanitize.js +7 -0
  132. package/dist/lib/extension-configuration-types.js +8 -0
  133. package/dist/lib/function-types.js +3 -1
  134. package/dist/lib/http-proxy.js +13 -0
  135. package/dist/lib/mcp/ai-tools.js +3 -3
  136. package/dist/lib/mcp/command-id.js +2 -0
  137. package/dist/lib/mcp/pipeline-automation-quality-tools.js +452 -0
  138. package/dist/lib/mcp/server.js +70 -1
  139. package/dist/lib/mcp/testing-live-tools.js +24 -13
  140. package/dist/lib/mcp/testing-tools.js +239 -550
  141. package/dist/lib/mcp/tool-annotations.js +27 -18
  142. package/dist/lib/mcp/tools.js +117 -32
  143. package/dist/lib/mcp/work-tools.js +37 -10
  144. package/dist/lib/metadata-explore.js +8 -0
  145. package/dist/lib/network-error.js +8 -0
  146. package/dist/lib/pipeline-automation-flags.js +12 -0
  147. package/dist/lib/pipeline-automation-ops.js +9 -0
  148. package/dist/lib/pipeline-automation-types.js +18 -0
  149. package/dist/lib/pipeline-lifecycle-id.js +3 -0
  150. package/dist/lib/pipeline-quality-gate-flags.js +12 -0
  151. package/dist/lib/pipeline-quality-gate-ops.js +9 -0
  152. package/dist/lib/pipeline-quality-gate-types.js +17 -0
  153. package/dist/lib/plugin-host/ai.js +2 -1
  154. package/dist/lib/plugin-skills.js +22 -0
  155. package/dist/lib/plugin-trust/gate.js +1 -2
  156. package/dist/lib/project-root.js +3 -1
  157. package/dist/lib/project-setup.js +5 -4
  158. package/dist/lib/runtime.js +1 -1
  159. package/dist/lib/salesforce-tooling-check.js +6 -0
  160. package/dist/lib/setup-skills.js +4 -1
  161. package/dist/lib/setup-templates.js +1 -4
  162. package/dist/lib/skill-packs.js +7 -0
  163. package/dist/lib/template-types.js +3 -1
  164. package/dist/lib/testing-archive.js +9 -0
  165. package/dist/lib/testing-data-table.js +39 -0
  166. package/dist/lib/testing-execution.js +22 -0
  167. package/dist/lib/testing-flags.js +6 -2
  168. package/dist/lib/testing-gateway.js +4 -1
  169. package/dist/lib/testing-live-command.js +3 -1
  170. package/dist/lib/testing-live-operations.js +7 -1
  171. package/dist/lib/testing-live-recorder.js +3 -1
  172. package/dist/lib/testing-live-state.js +8 -1
  173. package/dist/lib/testing-operations.js +6 -21
  174. package/dist/lib/testing-sanitization.js +2 -1
  175. package/dist/lib/testing-secret-input.js +2 -1
  176. package/dist/lib/testing-types.js +24 -3
  177. package/dist/lib/work-committed-metadata.js +4 -0
  178. package/dist/lib/work-environment-sync.js +3 -1
  179. package/dist/lib/work-flags.js +6 -1
  180. package/dist/lib/work-get.js +2 -1
  181. package/dist/lib/work-local-development-flow.js +4 -0
  182. package/dist/lib/work-submit-wait.js +3 -1
  183. package/oclif.manifest.json +9771 -9650
  184. package/package.json +35 -2
  185. package/templates/rules/cursor/agentia.mdc +29 -0
  186. package/templates/skills/agentia/SKILL.md +29 -0
  187. package/templates/skills/agentia-ai/SKILL.md +3 -4
  188. package/templates/skills/agentia-ai/references/ai-agents.md +2 -2
  189. package/templates/skills/agentia-cicd/SKILL.md +9 -4
  190. package/templates/skills/agentia-cicd/references/environments-and-credentials.md +19 -13
  191. package/templates/skills/agentia-cicd/references/extensions.md +52 -0
  192. package/templates/skills/agentia-cicd/references/pipelines.md +36 -2
  193. package/templates/skills/agentia-cicd/references/work.md +25 -8
  194. package/templates/skills/agentia-metadata/SKILL.md +140 -0
  195. package/templates/skills/agentia-metadata/references/metadata-explore.md +142 -0
  196. package/templates/skills/agentia-testing/SKILL.md +3 -3
  197. package/templates/skills/agentia-testing/references/tests.md +14 -14
  198. package/dist/commands/testing/build/get.js +0 -38
  199. package/dist/commands/testing/build/latest.js +0 -40
  200. package/dist/commands/testing/build/logs.js +0 -47
  201. package/dist/commands/testing/build/run.js +0 -26
  202. package/dist/commands/testing/create.js +0 -2
  203. package/dist/commands/testing/job/download.js +0 -54
  204. package/dist/commands/testing/job/files.js +0 -34
  205. package/dist/commands/testing/run.js +0 -26
  206. package/dist/commands/testing/status.js +0 -45
  207. package/dist/commands/testing/test/create.js +0 -2
  208. package/dist/commands/testing/test/logs.js +0 -2
  209. package/dist/commands/testing/test/run.js +0 -26
  210. package/dist/commands/testing/test/status.js +0 -2
  211. package/dist/commands/testing/test/update.js +0 -2
  212. package/dist/commands/testing/update.js +0 -65
  213. package/dist/lib/testing-data-command.js +0 -8
  214. package/dist/lib/testing-data-core.js +0 -20
  215. package/dist/lib/testing-data-export.js +0 -6
  216. package/dist/lib/testing-data-import.js +0 -6
  217. package/dist/lib/testing-data-io.js +0 -12
  218. package/dist/lib/testing-data-operations.js +0 -10
  219. package/dist/lib/testing-data-types.js +0 -4
  220. package/dist/lib/testing-live-endpoints.js +0 -6
  221. package/dist/lib/testing-live-history.js +0 -7
  222. package/dist/lib/testing-run-command.js +0 -3
  223. package/dist/lib/testing-schedule.js +0 -5
  224. package/dist/lib/testing-session.js +0 -5
  225. package/dist/lib/testing-watch.js +0 -4
  226. package/templates/AGENTS.md +0 -24
@@ -1,11 +1,12 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
- import { testingFileInputFlags, testingGitStorageFlags, testingProjectFlag, } from '../../../lib/testing-flags.js';
3
+ import { testingFileInputFlags, testingGitStorageFlags, testingProjectFlag } from '../../../lib/testing-flags.js';
4
4
  import { createTestingJob, DEFAULT_TESTING_AUTHOR } from '../../../lib/testing-operations.js';
5
5
  import { resolveTestingSecretInput } from '../../../lib/testing-secret-input.js';
6
6
  import { formatTestingRecord, TESTING_JOB_PARALLEL_MODES, TESTING_JOB_SUITE_TYPES, } from '../../../lib/testing-types.js';
7
7
  export default class TestingJobCreate extends AgentiaCommand {
8
- static description = 'Create a Copado Robotic Testing job/test from uploaded files or Git storage';
8
+ static deprecateAliases = true;
9
+ static description = 'Create a Copado Robotic Testing job from uploaded files or Git storage';
9
10
  static examples = [
10
11
  '<%= config.bin %> <%= command.id %> --project <project-id> --robot <robot-id> --name "Smoke" --file tests.robot',
11
12
  '<%= config.bin %> <%= command.id %> --project <project-id> --robot <robot-id> --name "Smoke" --dir tests --json',
@@ -15,20 +16,29 @@ export default class TestingJobCreate extends AgentiaCommand {
15
16
  ...testingProjectFlag,
16
17
  ...testingFileInputFlags,
17
18
  ...testingGitStorageFlags,
18
- 'author-email': Flags.string({ default: DEFAULT_TESTING_AUTHOR.email, description: 'Author email for initial file history.' }),
19
- 'author-name': Flags.string({ default: DEFAULT_TESTING_AUTHOR.name, description: 'Author name for initial file history.' }),
19
+ 'author-email': Flags.string({
20
+ default: DEFAULT_TESTING_AUTHOR.email,
21
+ description: 'Author email for initial file history.',
22
+ }),
23
+ 'author-name': Flags.string({
24
+ default: DEFAULT_TESTING_AUTHOR.name,
25
+ description: 'Author name for initial file history.',
26
+ }),
20
27
  'base-path': Flags.string({ description: 'Require local files to stay within this directory.' }),
21
28
  'case-duration-change-detection': Flags.boolean({
22
29
  allowNo: true,
23
30
  description: 'Enable or disable duration analytics.',
24
31
  }),
25
32
  description: Flags.string({
26
- description: 'Job/test description.',
33
+ description: 'Job description.',
34
+ }),
35
+ 'dry-run': Flags.boolean({
36
+ default: false,
37
+ description: 'Return a sanitized creation plan without network mutation.',
27
38
  }),
28
- 'dry-run': Flags.boolean({ default: false, description: 'Return a sanitized creation plan without network mutation.' }),
29
39
  message: Flags.string({ description: 'Commit message for initial file upload.' }),
30
40
  name: Flags.string({
31
- description: 'Job/test name.',
41
+ description: 'Job name.',
32
42
  required: true,
33
43
  }),
34
44
  'parallel-mode': Flags.option({
@@ -44,26 +54,24 @@ export default class TestingJobCreate extends AgentiaCommand {
44
54
  'screen-depth': Flags.integer({ description: 'Screen color depth.', min: 1 }),
45
55
  'screen-height': Flags.integer({ description: 'Screen height.', min: 1 }),
46
56
  'screen-width': Flags.integer({ description: 'Screen width.', min: 1 }),
47
- 'show-video-params': Flags.boolean({ allowNo: true, description: 'Show or hide video parameters.' }),
57
+ 'show-video-params': Flags.boolean({
58
+ allowNo: true,
59
+ description: 'Enable or disable video streaming and recording capabilities when running the test job.',
60
+ }),
48
61
  'suite-type': Flags.option({ description: 'CRT suite/job type.', options: [...TESTING_JOB_SUITE_TYPES] })(),
49
62
  timeout: Flags.string({ description: 'Build timeout, for example 10m.' }),
50
63
  validation: Flags.boolean({ default: false, description: 'Ask CRT to validate the created job.' }),
51
64
  };
65
+ static hiddenAliases = ['testing:create', 'testing:test:create'];
52
66
  async run() {
53
67
  const { flags } = await this.parse(TestingJobCreate);
54
- const screenValues = [flags['screen-width'], flags['screen-height'], flags['screen-depth']];
55
- if (screenValues.some((value) => value !== undefined) && screenValues.includes(undefined)) {
56
- this.error('Provide --screen-width, --screen-height, and --screen-depth together.', { exit: 2 });
57
- }
58
68
  const gitPassword = await resolveTestingSecretInput({
59
69
  value: flags['git-password'],
60
70
  valueFile: flags['git-password-file'],
61
71
  valueStdin: flags['git-password-stdin'],
62
72
  }, { label: 'CRT Git password', required: false });
63
73
  const result = await this.withSpinner('Creating testing job', () => createTestingJob({
64
- analytics: flags['case-duration-change-detection'] === undefined
65
- ? undefined
66
- : { caseDurationChangeDetection: flags['case-duration-change-detection'] },
74
+ caseDurationChangeDetection: flags['case-duration-change-detection'],
67
75
  description: flags.description,
68
76
  dryRun: flags['dry-run'],
69
77
  fileInput: {
@@ -83,13 +91,9 @@ export default class TestingJobCreate extends AgentiaCommand {
83
91
  parallelExecution: flags['parallel-mode'],
84
92
  projectId: flags.project,
85
93
  robotId: flags.robot,
86
- screen: flags['screen-width'] === undefined
87
- ? undefined
88
- : {
89
- depth: flags['screen-depth'],
90
- height: flags['screen-height'],
91
- width: flags['screen-width'],
92
- },
94
+ screenDepth: flags['screen-depth'],
95
+ screenHeight: flags['screen-height'],
96
+ screenWidth: flags['screen-width'],
93
97
  showVideoParams: flags['show-video-params'],
94
98
  suiteType: flags['suite-type'],
95
99
  timeout: flags.timeout,
@@ -6,11 +6,11 @@ import { deleteTestingJob } from '../../../lib/testing-operations.js';
6
6
  export default class TestingJobDelete extends AgentiaCommand {
7
7
  static args = {
8
8
  id: Args.integer({
9
- description: 'CRT job/test ID.',
9
+ description: 'CRT job ID.',
10
10
  required: true,
11
11
  }),
12
12
  };
13
- static description = 'Delete a Copado Robotic Testing job/test';
13
+ static description = 'Delete a Copado Robotic Testing job';
14
14
  static examples = [
15
15
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --yes',
16
16
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --yes --json',
@@ -0,0 +1,73 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingBranchFlag, testingProjectFlag } from '../../../../lib/testing-flags.js';
4
+ import { downloadTestingJobFiles } from '../../../../lib/testing-operations.js';
5
+ import { formatTestingTable } from '../../../../lib/testing-types.js';
6
+ export default class TestingJobFilesDownload extends AgentiaCommand {
7
+ static args = {
8
+ id: Args.integer({
9
+ description: 'CRT job ID.',
10
+ required: true,
11
+ }),
12
+ };
13
+ static deprecateAliases = true;
14
+ static description = 'Download files from a Copado Robotic Testing job';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --file tests.robot',
17
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --file tests.robot --output-dir ./crt-files --json',
18
+ ];
19
+ static flags = {
20
+ ...testingProjectFlag,
21
+ ...testingBranchFlag,
22
+ file: Flags.string({
23
+ char: 'f',
24
+ description: 'Remote CRT file path to download. Can be provided multiple times.',
25
+ multiple: true,
26
+ required: true,
27
+ }),
28
+ 'output-dir': Flags.string({
29
+ char: 'o',
30
+ description: 'Directory to write downloaded files.',
31
+ }),
32
+ };
33
+ static hiddenAliases = ['testing:job:download'];
34
+ async run() {
35
+ const { args, flags } = await this.parse(TestingJobFilesDownload);
36
+ const result = await this.withSpinner('Downloading testing job files', () => downloadTestingJobFiles({
37
+ branch: flags.branch,
38
+ files: flags.file,
39
+ jobId: args.id,
40
+ outputDir: flags['output-dir'],
41
+ projectId: flags.project,
42
+ }));
43
+ this.display(() => {
44
+ if (flags['output-dir'] !== undefined) {
45
+ if (result.files.length > 0) {
46
+ this.log(`Downloaded files to ${flags['output-dir']}`);
47
+ this.log(formatTestingTable(result.files));
48
+ }
49
+ else {
50
+ this.log('Downloaded file response did not include a file listing.');
51
+ }
52
+ return;
53
+ }
54
+ if (result.files.length === 0) {
55
+ this.log('Downloaded file response did not include a file listing.');
56
+ return;
57
+ }
58
+ for (const [index, file] of result.files.entries()) {
59
+ if (result.files.length > 1 && file.path !== undefined) {
60
+ this.log(file.path);
61
+ }
62
+ const value = file.value ?? '';
63
+ const content = file.encoding === 'base64' ? Buffer.from(value, 'base64').toString('utf8') : value;
64
+ process.stdout.write(content);
65
+ if (!content.endsWith('\n') && index < result.files.length - 1) {
66
+ process.stdout.write('\n');
67
+ }
68
+ }
69
+ });
70
+ return result;
71
+ }
72
+ }
73
+ //# sourceMappingURL=download.js.map
@@ -0,0 +1,43 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingBranchFlag, testingProjectFlag } from '../../../../lib/testing-flags.js';
4
+ import { listTestingJobFiles } from '../../../../lib/testing-operations.js';
5
+ import { formatTestingTable } from '../../../../lib/testing-types.js';
6
+ export default class TestingJobFilesList extends AgentiaCommand {
7
+ static args = {
8
+ id: Args.integer({
9
+ description: 'CRT job ID.',
10
+ required: true,
11
+ }),
12
+ };
13
+ static deprecateAliases = true;
14
+ static description = 'List files for a Copado Robotic Testing job';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id>',
17
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --branch main --json',
18
+ ];
19
+ static flags = {
20
+ ...testingProjectFlag,
21
+ ...testingBranchFlag,
22
+ 'shared-credentials': Flags.boolean({ allowNo: true, description: 'Use shared stored Git credentials.' }),
23
+ };
24
+ static hiddenAliases = ['testing:job:files'];
25
+ async run() {
26
+ const { args, flags } = await this.parse(TestingJobFilesList);
27
+ const files = await this.withSpinner('Fetching testing job files', () => listTestingJobFiles({
28
+ branch: flags.branch,
29
+ jobId: args.id,
30
+ projectId: flags.project,
31
+ sharedCredentials: flags['shared-credentials'],
32
+ }));
33
+ this.display(() => {
34
+ if (files.length === 0) {
35
+ this.log('No testing job files found.');
36
+ return;
37
+ }
38
+ this.log(formatTestingTable(files));
39
+ });
40
+ return files;
41
+ }
42
+ }
43
+ //# sourceMappingURL=list.js.map
@@ -1,16 +1,17 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
- import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
- import { testingBranchFlag, testingProjectFlag, testingUploadOperationFlags, } from '../../../lib/testing-flags.js';
4
- import { buildFileOperationsFromSpecs, DEFAULT_TESTING_AUTHOR, uploadTestingJobFiles } from '../../../lib/testing-operations.js';
5
- import { formatTestingRecord } from '../../../lib/testing-types.js';
6
- export default class TestingJobUpload extends AgentiaCommand {
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingBranchFlag, testingProjectFlag, testingUploadOperationFlags } from '../../../../lib/testing-flags.js';
4
+ import { buildFileOperationsFromSpecs, DEFAULT_TESTING_AUTHOR, uploadTestingJobFiles, } from '../../../../lib/testing-operations.js';
5
+ import { formatTestingRecord } from '../../../../lib/testing-types.js';
6
+ export default class TestingJobFilesUpload extends AgentiaCommand {
7
7
  static args = {
8
8
  id: Args.integer({
9
- description: 'CRT job/test ID.',
9
+ description: 'CRT job ID.',
10
10
  required: true,
11
11
  }),
12
12
  };
13
- static description = 'Upload file operations to a Copado Robotic Testing job/test';
13
+ static deprecateAliases = true;
14
+ static description = 'Upload file operations to a Copado Robotic Testing job';
14
15
  static examples = [
15
16
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --add tests.robot',
16
17
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --replace local.robot:tests.robot --remove old.robot --json',
@@ -45,8 +46,9 @@ export default class TestingJobUpload extends AgentiaCommand {
45
46
  description: 'Validated remote path prefix for all operations.',
46
47
  }),
47
48
  };
49
+ static hiddenAliases = ['testing:job:upload', 'testing:update', 'testing:test:update'];
48
50
  async run() {
49
- const { args, flags } = await this.parse(TestingJobUpload);
51
+ const { args, flags } = await this.parse(TestingJobFilesUpload);
50
52
  const operations = buildFileOperationsFromSpecs({
51
53
  add: flags.add,
52
54
  basePath: flags['base-path'],
@@ -68,7 +70,9 @@ export default class TestingJobUpload extends AgentiaCommand {
68
70
  projectId: flags.project,
69
71
  }));
70
72
  this.display(() => {
71
- this.log(`File operations uploaded: ${operations.length}`);
73
+ this.log(result.dryRun
74
+ ? `File operations planned (dry run): ${operations.length}`
75
+ : `File operations uploaded: ${operations.length}`);
72
76
  this.log(formatTestingRecord(result.response));
73
77
  });
74
78
  return result;
@@ -6,11 +6,11 @@ import { formatTestingRecord } from '../../../lib/testing-types.js';
6
6
  export default class TestingJobGet extends AgentiaCommand {
7
7
  static args = {
8
8
  id: Args.string({
9
- description: 'CRT job/test ID.',
9
+ description: 'CRT job ID.',
10
10
  required: true,
11
11
  }),
12
12
  };
13
- static description = 'Get a Copado Robotic Testing job/test from the project job list';
13
+ static description = 'Get a Copado Robotic Testing job from the project job list';
14
14
  static examples = [
15
15
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id>',
16
16
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --json',
@@ -4,7 +4,7 @@ import { testingProjectFlag } from '../../../lib/testing-flags.js';
4
4
  import { listTestingJobs } from '../../../lib/testing-operations.js';
5
5
  import { formatTestingJobTable } from '../../../lib/testing-types.js';
6
6
  export default class TestingJobList extends AgentiaCommand {
7
- static description = 'List Copado Robotic Testing jobs/tests in a project';
7
+ static description = 'List Copado Robotic Testing jobs in a project';
8
8
  static examples = [
9
9
  '<%= config.bin %> <%= command.id %> --project <project-id>',
10
10
  '<%= config.bin %> <%= command.id %> --project <project-id> --name "Smoke" --json',
@@ -2,12 +2,12 @@ import { Args, Flags } from '@oclif/core';
2
2
  import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
3
  import { testingProjectFlag } from '../../../lib/testing-flags.js';
4
4
  import { getTestingJobRefs } from '../../../lib/testing-operations.js';
5
- import { formatTestingRecord } from '../../../lib/testing-types.js';
5
+ import { formatTestingRefsTable } from '../../../lib/testing-types.js';
6
6
  export default class TestingJobRefs extends AgentiaCommand {
7
7
  static args = {
8
- id: Args.integer({ description: 'CRT job/test ID.', required: true }),
8
+ id: Args.integer({ description: 'CRT job ID.', required: true }),
9
9
  };
10
- static description = 'List Git branches and tags for a Copado Robotic Testing job/test';
10
+ static description = 'List Git branches and tags for a Copado Robotic Testing job';
11
11
  static examples = [
12
12
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id>',
13
13
  '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --shared-credentials --json',
@@ -23,7 +23,7 @@ export default class TestingJobRefs extends AgentiaCommand {
23
23
  projectId: flags.project,
24
24
  sharedCredentials: flags['shared-credentials'],
25
25
  }));
26
- this.display(() => this.log(formatTestingRecord(result)));
26
+ this.display(() => this.log(formatTestingRefsTable(result)));
27
27
  return result;
28
28
  }
29
29
  }
@@ -1,2 +1,135 @@
1
- export { default } from '../build/run.js';
1
+ import { Args } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
+ import { resolveTestingCredentials } from '../../../lib/testing-config.js';
4
+ import { executeTestingBuildRun, testingBuildStatus, } from '../../../lib/testing-execution.js';
5
+ import { buildTestingRunOptions, testingProjectFlag, testingRunOptionFlags } from '../../../lib/testing-flags.js';
6
+ import { getTestingProject } from '../../../lib/testing-operations.js';
7
+ import { asTestingRecord, formatTestingRecord, normalizeTestingId, testingRunLogsUrl, testingRunResultsUrl, } from '../../../lib/testing-types.js';
8
+ export default class TestingJobRun extends AgentiaCommand {
9
+ static args = {
10
+ id: Args.integer({
11
+ description: 'CRT job ID to run.',
12
+ required: true,
13
+ }),
14
+ };
15
+ static deprecateAliases = true;
16
+ static description = 'Run a Copado Robotic Testing job';
17
+ static examples = [
18
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id>',
19
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --param BROWSER=chrome --record failed',
20
+ '<%= config.bin %> <%= command.id %> <job-id> --project <project-id> --no-wait --json',
21
+ ];
22
+ static flags = {
23
+ ...testingProjectFlag,
24
+ ...testingRunOptionFlags,
25
+ };
26
+ static hiddenAliases = ['testing:run', 'testing:build:run', 'testing:test:run'];
27
+ async run() {
28
+ const { args, flags } = await this.parse(TestingJobRun);
29
+ const ids = { jobId: args.id, projectId: flags.project };
30
+ const runOptions = buildTestingRunOptions(flags, ids);
31
+ const isDataDriven = (runOptions.dataTables?.length ?? 0) > 0;
32
+ const requiresArtifacts = flags['save-artifacts'] !== undefined || flags.xunit !== undefined;
33
+ const shouldWait = (flags.wait !== false && !isDataDriven) || requiresArtifacts;
34
+ const streamLogs = shouldWait && flags['stream-logs'] !== false && !this.jsonEnabled();
35
+ let urlContext;
36
+ let queuedDots = false;
37
+ const execOptions = {
38
+ ...runOptions,
39
+ onBuildStarted: streamLogs
40
+ ? async (buildId) => {
41
+ urlContext = await this.resolveRunUrlContext(ids.projectId);
42
+ this.log(`Run ID: ${buildId}`);
43
+ this.log(`Logs: ${testingRunLogsUrl({
44
+ buildId,
45
+ domain: urlContext.domain,
46
+ jobId: ids.jobId,
47
+ orgId: urlContext.orgId,
48
+ projectId: ids.projectId,
49
+ })}`);
50
+ }
51
+ : undefined,
52
+ onLogChunk: streamLogs ? (chunk) => process.stdout.write(chunk) : undefined,
53
+ onPoll: streamLogs
54
+ ? (build) => {
55
+ if (testingBuildStatus(build) === 'queued') {
56
+ process.stdout.write(queuedDots ? '.' : 'Run is queued...');
57
+ queuedDots = true;
58
+ return;
59
+ }
60
+ if (queuedDots) {
61
+ process.stdout.write('\n');
62
+ queuedDots = false;
63
+ }
64
+ }
65
+ : undefined,
66
+ saveArtifacts: flags['save-artifacts'],
67
+ streamLogs,
68
+ timeout: flags.timeout,
69
+ wait: flags.wait,
70
+ xunit: flags.xunit,
71
+ };
72
+ let result;
73
+ try {
74
+ result = streamLogs
75
+ ? await executeTestingBuildRun(execOptions)
76
+ : await this.withSpinner('Running testing run', () => executeTestingBuildRun(execOptions));
77
+ }
78
+ finally {
79
+ if (queuedDots)
80
+ process.stdout.write('\n');
81
+ }
82
+ if (result.wait === undefined) {
83
+ this.display(() => {
84
+ this.log('Testing run started');
85
+ this.log(formatTestingRecord({ build: result.build, jobId: result.jobId, projectId: result.projectId }));
86
+ });
87
+ return result;
88
+ }
89
+ this.display(() => {
90
+ const buildId = result.wait?.buildId ?? normalizeTestingId(result.build);
91
+ const context = urlContext ?? resolveTestingCredentials();
92
+ this.log('Testing run finished');
93
+ this.log(formatTestingRecord({
94
+ artifacts: result.artifacts,
95
+ buildId,
96
+ jobId: result.jobId,
97
+ projectId: result.projectId,
98
+ }));
99
+ if (buildId !== undefined) {
100
+ this.log(`Results: ${testingRunResultsUrl({
101
+ buildId,
102
+ domain: context.domain,
103
+ jobId: result.jobId,
104
+ orgId: context.orgId,
105
+ projectId: result.projectId,
106
+ })}`);
107
+ }
108
+ });
109
+ if (result.failedWait && flags['no-exit-code'] !== true) {
110
+ const status = result.finalBuild === undefined ? undefined : testingBuildStatus(result.finalBuild);
111
+ this.error(`Testing run finished with status ${status ?? 'failed'}.`, { exit: 1 });
112
+ }
113
+ return result;
114
+ }
115
+ async resolveRunUrlContext(projectId) {
116
+ const credentials = resolveTestingCredentials();
117
+ try {
118
+ const project = await getTestingProject({ projectId });
119
+ const projectOrgId = normalizeTestingId({
120
+ id: project.organizationId ?? project.organization_id ?? asTestingRecord(project.organization).id,
121
+ });
122
+ return {
123
+ domain: credentials.domain,
124
+ orgId: projectOrgId ?? credentials.orgId,
125
+ };
126
+ }
127
+ catch {
128
+ return {
129
+ domain: credentials.domain,
130
+ orgId: credentials.orgId,
131
+ };
132
+ }
133
+ }
134
+ }
2
135
  //# sourceMappingURL=run.js.map
@@ -1,17 +1,18 @@
1
1
  import { Args } from '@oclif/core';
2
- import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
- import { confirmTestingAction } from '../../../lib/testing-confirmation.js';
4
- import { testingJobFlag, testingProjectFlag, testingYesFlag, } from '../../../lib/testing-flags.js';
5
- import { abortTestingBuild } from '../../../lib/testing-operations.js';
6
- import { formatTestingRecord } from '../../../lib/testing-types.js';
7
- export default class TestingBuildAbort extends AgentiaCommand {
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { confirmTestingAction } from '../../../../lib/testing-confirmation.js';
4
+ import { testingJobFlag, testingProjectFlag, testingYesFlag } from '../../../../lib/testing-flags.js';
5
+ import { abortTestingBuild } from '../../../../lib/testing-operations.js';
6
+ import { formatTestingRecord } from '../../../../lib/testing-types.js';
7
+ export default class TestingJobRunsAbort extends AgentiaCommand {
8
8
  static args = {
9
9
  id: Args.integer({
10
10
  description: 'CRT build/run ID.',
11
11
  required: true,
12
12
  }),
13
13
  };
14
- static description = 'Abort a Copado Robotic Testing build/run';
14
+ static deprecateAliases = true;
15
+ static description = 'Abort a Copado Robotic Testing job run';
15
16
  static examples = [
16
17
  '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id> --yes',
17
18
  '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id> --yes --json',
@@ -21,8 +22,9 @@ export default class TestingBuildAbort extends AgentiaCommand {
21
22
  ...testingJobFlag,
22
23
  ...testingYesFlag,
23
24
  };
25
+ static hiddenAliases = ['testing:build:abort'];
24
26
  async run() {
25
- const { args, flags } = await this.parse(TestingBuildAbort);
27
+ const { args, flags } = await this.parse(TestingJobRunsAbort);
26
28
  const confirmed = await confirmTestingAction({
27
29
  action: 'Build abort',
28
30
  json: this.jsonEnabled(),
@@ -0,0 +1,42 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingJobFlag, testingProjectFlag } from '../../../../lib/testing-flags.js';
4
+ import { getTestingBuild } from '../../../../lib/testing-operations.js';
5
+ import { formatTestingBuildDetail, formatTestingBuildSummary } from '../../../../lib/testing-types.js';
6
+ export default class TestingJobRunsGet extends AgentiaCommand {
7
+ static args = {
8
+ id: Args.integer({
9
+ description: 'CRT build/run ID.',
10
+ required: true,
11
+ }),
12
+ };
13
+ static deprecateAliases = true;
14
+ static description = 'Get the result of a Copado Robotic Testing job run';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id>',
17
+ '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id> --full --json',
18
+ ];
19
+ static flags = {
20
+ ...testingProjectFlag,
21
+ ...testingJobFlag,
22
+ full: Flags.boolean({
23
+ default: false,
24
+ description: 'Fetch the full build result instead of the compact summary.',
25
+ }),
26
+ };
27
+ static hiddenAliases = ['testing:build:get'];
28
+ async run() {
29
+ const { args, flags } = await this.parse(TestingJobRunsGet);
30
+ const json = this.jsonEnabled();
31
+ // The compact single-build response omits xUnit totals, so the human summary reads the full record.
32
+ const build = await this.withSpinner('Fetching testing build', () => getTestingBuild({
33
+ buildId: args.id,
34
+ full: flags.full || !json,
35
+ jobId: flags.job,
36
+ projectId: flags.project,
37
+ }));
38
+ this.display(() => this.log(flags.full ? formatTestingBuildDetail(build) : formatTestingBuildSummary(build)));
39
+ return build;
40
+ }
41
+ }
42
+ //# sourceMappingURL=get.js.map
@@ -1,12 +1,14 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { AgentiaCommand } from '../../../lib/agentia-command.js';
3
- import { testingProjectFlag, } from '../../../lib/testing-flags.js';
4
- import { countTestingBuilds, listTestingBuilds } from '../../../lib/testing-operations.js';
5
- import { formatTestingBuildTable, TESTING_BUILD_STATUSES, } from '../../../lib/testing-types.js';
6
- export default class TestingBuildList extends AgentiaCommand {
7
- static description = 'List Copado Robotic Testing builds/runs';
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingProjectFlag } from '../../../../lib/testing-flags.js';
4
+ import { countTestingBuilds, listTestingBuilds } from '../../../../lib/testing-operations.js';
5
+ import { formatTestingBuildTable, TESTING_BUILD_STATUSES } from '../../../../lib/testing-types.js';
6
+ export default class TestingJobRunsList extends AgentiaCommand {
7
+ static deprecateAliases = true;
8
+ static description = 'List Copado Robotic Testing job runs';
8
9
  static examples = [
9
10
  '<%= config.bin %> <%= command.id %> --project <project-id>',
11
+ '<%= config.bin %> <%= command.id %> --project <project-id> --status failed --json',
10
12
  '<%= config.bin %> <%= command.id %> --project <project-id> --job <job-id> --status succeeded --json',
11
13
  '<%= config.bin %> <%= command.id %> --project <project-id> --job <job-id> --count',
12
14
  ];
@@ -17,7 +19,7 @@ export default class TestingBuildList extends AgentiaCommand {
17
19
  description: 'Return only the number of builds. Requires --job.',
18
20
  }),
19
21
  job: Flags.integer({
20
- description: 'Limit builds to one CRT job/test ID.',
22
+ description: 'Limit builds to one CRT job ID.',
21
23
  }),
22
24
  page: Flags.integer({
23
25
  description: 'CRT build page number.',
@@ -37,12 +39,19 @@ export default class TestingBuildList extends AgentiaCommand {
37
39
  options: [...TESTING_BUILD_STATUSES],
38
40
  })(),
39
41
  };
42
+ static hiddenAliases = [
43
+ 'testing:build:list',
44
+ 'testing:build:latest',
45
+ 'testing:status',
46
+ 'testing:test:status',
47
+ ];
40
48
  async run() {
41
- const { flags } = await this.parse(TestingBuildList);
49
+ const { flags } = await this.parse(TestingJobRunsList);
42
50
  if (flags.count) {
43
- if (flags.job === undefined)
51
+ const { job } = flags;
52
+ if (job === undefined)
44
53
  this.error('--count requires --job.', { exit: 2 });
45
- const count = await this.withSpinner('Counting testing builds', () => countTestingBuilds({ jobId: flags.job, projectId: flags.project }));
54
+ const count = await this.withSpinner('Counting testing builds', () => countTestingBuilds({ jobId: job, projectId: flags.project }));
46
55
  this.display(() => this.log(count.toString()));
47
56
  return { count };
48
57
  }
@@ -1,17 +1,19 @@
1
1
  import { Args } from '@oclif/core';
2
- import { AgentiaCommand } from '../../lib/agentia-command.js';
3
- import { testingJobFlag, testingLogOptionFlags, testingOutputFlags, testingProjectFlag, } from '../../lib/testing-flags.js';
4
- import { getTestingBuildLogs } from '../../lib/testing-operations.js';
5
- export default class TestingLogs extends AgentiaCommand {
2
+ import { AgentiaCommand } from '../../../../lib/agentia-command.js';
3
+ import { testingJobFlag, testingLogOptionFlags, testingOutputFlags, testingProjectFlag, } from '../../../../lib/testing-flags.js';
4
+ import { getTestingBuildLogs } from '../../../../lib/testing-operations.js';
5
+ export default class TestingJobRunsLogs extends AgentiaCommand {
6
6
  static args = {
7
7
  id: Args.integer({
8
8
  description: 'CRT build/run ID.',
9
9
  required: true,
10
10
  }),
11
11
  };
12
- static description = 'Get logs for a Copado Robotic Testing run';
12
+ static deprecateAliases = true;
13
+ static description = 'Get logs for a Copado Robotic Testing job run';
13
14
  static examples = [
14
15
  '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id>',
16
+ '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id> --tail-lines 200',
15
17
  '<%= config.bin %> <%= command.id %> <build-id> --project <project-id> --job <job-id> --output log.html --json',
16
18
  ];
17
19
  static flags = {
@@ -20,8 +22,9 @@ export default class TestingLogs extends AgentiaCommand {
20
22
  ...testingLogOptionFlags,
21
23
  ...testingOutputFlags,
22
24
  };
25
+ static hiddenAliases = ['testing:logs', 'testing:test:logs', 'testing:build:logs'];
23
26
  async run() {
24
- const { args, flags } = await this.parse(TestingLogs);
27
+ const { args, flags } = await this.parse(TestingJobRunsLogs);
25
28
  const result = await this.withSpinner('Fetching testing run logs', () => getTestingBuildLogs({
26
29
  buildId: args.id,
27
30
  container: flags.container,