@pipeline-builder/pipeline-manager 0.0.1

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 (222) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +145 -0
  3. package/cdk.json +91 -0
  4. package/config.yml +94 -0
  5. package/dist/agent/ai.d.ts +48 -0
  6. package/dist/agent/ai.d.ts.map +1 -0
  7. package/dist/agent/ai.js +149 -0
  8. package/dist/agent/bootstrap.d.ts +39 -0
  9. package/dist/agent/bootstrap.d.ts.map +1 -0
  10. package/dist/agent/bootstrap.js +66 -0
  11. package/dist/agent/env-file.d.ts +17 -0
  12. package/dist/agent/env-file.d.ts.map +1 -0
  13. package/dist/agent/env-file.js +47 -0
  14. package/dist/agent/executor.d.ts +30 -0
  15. package/dist/agent/executor.d.ts.map +1 -0
  16. package/dist/agent/executor.js +60 -0
  17. package/dist/agent/health.d.ts +43 -0
  18. package/dist/agent/health.d.ts.map +1 -0
  19. package/dist/agent/health.js +109 -0
  20. package/dist/agent/ports.d.ts +26 -0
  21. package/dist/agent/ports.d.ts.map +1 -0
  22. package/dist/agent/ports.js +132 -0
  23. package/dist/agent/post-steps.d.ts +61 -0
  24. package/dist/agent/post-steps.d.ts.map +1 -0
  25. package/dist/agent/post-steps.js +131 -0
  26. package/dist/agent/prereqs.d.ts +26 -0
  27. package/dist/agent/prereqs.d.ts.map +1 -0
  28. package/dist/agent/prereqs.js +134 -0
  29. package/dist/agent/targets.d.ts +128 -0
  30. package/dist/agent/targets.d.ts.map +1 -0
  31. package/dist/agent/targets.js +265 -0
  32. package/dist/agent/tools.d.ts +13 -0
  33. package/dist/agent/tools.d.ts.map +1 -0
  34. package/dist/agent/tools.js +75 -0
  35. package/dist/agent/troubleshoot.d.ts +30 -0
  36. package/dist/agent/troubleshoot.d.ts.map +1 -0
  37. package/dist/agent/troubleshoot.js +87 -0
  38. package/dist/boilerplate.d.ts +3 -0
  39. package/dist/boilerplate.d.ts.map +1 -0
  40. package/dist/boilerplate.js +54 -0
  41. package/dist/cdk.json +91 -0
  42. package/dist/cli.d.ts +62 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +463 -0
  45. package/dist/commands/audit-stacks.d.ts +24 -0
  46. package/dist/commands/audit-stacks.d.ts.map +1 -0
  47. package/dist/commands/audit-stacks.js +182 -0
  48. package/dist/commands/audit-tokens.d.ts +21 -0
  49. package/dist/commands/audit-tokens.d.ts.map +1 -0
  50. package/dist/commands/audit-tokens.js +153 -0
  51. package/dist/commands/bootstrap.d.ts +11 -0
  52. package/dist/commands/bootstrap.d.ts.map +1 -0
  53. package/dist/commands/bootstrap.js +159 -0
  54. package/dist/commands/create-pat.d.ts +27 -0
  55. package/dist/commands/create-pat.d.ts.map +1 -0
  56. package/dist/commands/create-pat.js +194 -0
  57. package/dist/commands/create-pipeline.d.ts +12 -0
  58. package/dist/commands/create-pipeline.d.ts.map +1 -0
  59. package/dist/commands/create-pipeline.js +315 -0
  60. package/dist/commands/deploy.d.ts +15 -0
  61. package/dist/commands/deploy.d.ts.map +1 -0
  62. package/dist/commands/deploy.js +157 -0
  63. package/dist/commands/entity-get.d.ts +51 -0
  64. package/dist/commands/entity-get.d.ts.map +1 -0
  65. package/dist/commands/entity-get.js +69 -0
  66. package/dist/commands/entity-list.d.ts +39 -0
  67. package/dist/commands/entity-list.d.ts.map +1 -0
  68. package/dist/commands/entity-list.js +88 -0
  69. package/dist/commands/get-pipeline.d.ts +13 -0
  70. package/dist/commands/get-pipeline.d.ts.map +1 -0
  71. package/dist/commands/get-pipeline.js +49 -0
  72. package/dist/commands/get-plugin.d.ts +13 -0
  73. package/dist/commands/get-plugin.d.ts.map +1 -0
  74. package/dist/commands/get-plugin.js +51 -0
  75. package/dist/commands/instantiate-template.d.ts +20 -0
  76. package/dist/commands/instantiate-template.d.ts.map +1 -0
  77. package/dist/commands/instantiate-template.js +274 -0
  78. package/dist/commands/list-pipelines.d.ts +20 -0
  79. package/dist/commands/list-pipelines.d.ts.map +1 -0
  80. package/dist/commands/list-pipelines.js +99 -0
  81. package/dist/commands/list-plugins.d.ts +20 -0
  82. package/dist/commands/list-plugins.d.ts.map +1 -0
  83. package/dist/commands/list-plugins.js +92 -0
  84. package/dist/commands/login.d.ts +21 -0
  85. package/dist/commands/login.d.ts.map +1 -0
  86. package/dist/commands/login.js +174 -0
  87. package/dist/commands/new-plugin.d.ts +12 -0
  88. package/dist/commands/new-plugin.d.ts.map +1 -0
  89. package/dist/commands/new-plugin.js +129 -0
  90. package/dist/commands/org-export.d.ts +25 -0
  91. package/dist/commands/org-export.d.ts.map +1 -0
  92. package/dist/commands/org-export.js +100 -0
  93. package/dist/commands/provision.d.ts +122 -0
  94. package/dist/commands/provision.d.ts.map +1 -0
  95. package/dist/commands/provision.js +867 -0
  96. package/dist/commands/redrive-events.d.ts +24 -0
  97. package/dist/commands/redrive-events.d.ts.map +1 -0
  98. package/dist/commands/redrive-events.js +127 -0
  99. package/dist/commands/register.d.ts +38 -0
  100. package/dist/commands/register.d.ts.map +1 -0
  101. package/dist/commands/register.js +160 -0
  102. package/dist/commands/setup-events.d.ts +15 -0
  103. package/dist/commands/setup-events.d.ts.map +1 -0
  104. package/dist/commands/setup-events.js +168 -0
  105. package/dist/commands/status.d.ts +11 -0
  106. package/dist/commands/status.d.ts.map +1 -0
  107. package/dist/commands/status.js +81 -0
  108. package/dist/commands/store-token.d.ts +26 -0
  109. package/dist/commands/store-token.d.ts.map +1 -0
  110. package/dist/commands/store-token.js +305 -0
  111. package/dist/commands/synth.d.ts +21 -0
  112. package/dist/commands/synth.d.ts.map +1 -0
  113. package/dist/commands/synth.js +158 -0
  114. package/dist/commands/upload-plugin.d.ts +21 -0
  115. package/dist/commands/upload-plugin.d.ts.map +1 -0
  116. package/dist/commands/upload-plugin.js +275 -0
  117. package/dist/commands/validate-plugin.d.ts +12 -0
  118. package/dist/commands/validate-plugin.d.ts.map +1 -0
  119. package/dist/commands/validate-plugin.js +175 -0
  120. package/dist/commands/validate-templates.d.ts +11 -0
  121. package/dist/commands/validate-templates.d.ts.map +1 -0
  122. package/dist/commands/validate-templates.js +116 -0
  123. package/dist/commands/version.d.ts +12 -0
  124. package/dist/commands/version.d.ts.map +1 -0
  125. package/dist/commands/version.js +216 -0
  126. package/dist/config/cli.constants.d.ts +116 -0
  127. package/dist/config/cli.constants.d.ts.map +1 -0
  128. package/dist/config/cli.constants.js +194 -0
  129. package/dist/config.yml +94 -0
  130. package/dist/lambda/token-renew-handler.d.ts +2 -0
  131. package/dist/lambda/token-renew-handler.d.ts.map +1 -0
  132. package/dist/lambda/token-renew-handler.js +125 -0
  133. package/dist/templates/events-stack.json +174 -0
  134. package/dist/templates/token-renew-stack.json +122 -0
  135. package/dist/types/config.d.ts +53 -0
  136. package/dist/types/config.d.ts.map +1 -0
  137. package/dist/types/config.js +4 -0
  138. package/dist/types/error.d.ts +61 -0
  139. package/dist/types/error.d.ts.map +1 -0
  140. package/dist/types/error.js +35 -0
  141. package/dist/types/index.d.ts +9 -0
  142. package/dist/types/index.d.ts.map +1 -0
  143. package/dist/types/index.js +11 -0
  144. package/dist/types/pipeline-template.d.ts +48 -0
  145. package/dist/types/pipeline-template.d.ts.map +1 -0
  146. package/dist/types/pipeline-template.js +4 -0
  147. package/dist/types/pipeline.d.ts +121 -0
  148. package/dist/types/pipeline.d.ts.map +1 -0
  149. package/dist/types/pipeline.js +4 -0
  150. package/dist/types/plugin.d.ts +135 -0
  151. package/dist/types/plugin.d.ts.map +1 -0
  152. package/dist/types/plugin.js +4 -0
  153. package/dist/utils/api-client.d.ts +26 -0
  154. package/dist/utils/api-client.d.ts.map +1 -0
  155. package/dist/utils/api-client.js +151 -0
  156. package/dist/utils/audit-log.d.ts +8 -0
  157. package/dist/utils/audit-log.d.ts.map +1 -0
  158. package/dist/utils/audit-log.js +57 -0
  159. package/dist/utils/auth-guard.d.ts +20 -0
  160. package/dist/utils/auth-guard.d.ts.map +1 -0
  161. package/dist/utils/auth-guard.js +22 -0
  162. package/dist/utils/auth-utils.d.ts +68 -0
  163. package/dist/utils/auth-utils.d.ts.map +1 -0
  164. package/dist/utils/auth-utils.js +77 -0
  165. package/dist/utils/aws-env.d.ts +21 -0
  166. package/dist/utils/aws-env.d.ts.map +1 -0
  167. package/dist/utils/aws-env.js +34 -0
  168. package/dist/utils/aws-secrets.d.ts +48 -0
  169. package/dist/utils/aws-secrets.d.ts.map +1 -0
  170. package/dist/utils/aws-secrets.js +115 -0
  171. package/dist/utils/banner.d.ts +19 -0
  172. package/dist/utils/banner.d.ts.map +1 -0
  173. package/dist/utils/banner.js +52 -0
  174. package/dist/utils/cdk-utils.d.ts +74 -0
  175. package/dist/utils/cdk-utils.d.ts.map +1 -0
  176. package/dist/utils/cdk-utils.js +152 -0
  177. package/dist/utils/command-utils.d.ts +75 -0
  178. package/dist/utils/command-utils.d.ts.map +1 -0
  179. package/dist/utils/command-utils.js +155 -0
  180. package/dist/utils/config-loader.d.ts +33 -0
  181. package/dist/utils/config-loader.d.ts.map +1 -0
  182. package/dist/utils/config-loader.js +154 -0
  183. package/dist/utils/cron.d.ts +28 -0
  184. package/dist/utils/cron.d.ts.map +1 -0
  185. package/dist/utils/cron.js +119 -0
  186. package/dist/utils/deploy-runner.d.ts +38 -0
  187. package/dist/utils/deploy-runner.d.ts.map +1 -0
  188. package/dist/utils/deploy-runner.js +112 -0
  189. package/dist/utils/error-handler.d.ts +29 -0
  190. package/dist/utils/error-handler.d.ts.map +1 -0
  191. package/dist/utils/error-handler.js +302 -0
  192. package/dist/utils/list-command-utils.d.ts +23 -0
  193. package/dist/utils/list-command-utils.d.ts.map +1 -0
  194. package/dist/utils/list-command-utils.js +57 -0
  195. package/dist/utils/output-utils.d.ts +40 -0
  196. package/dist/utils/output-utils.d.ts.map +1 -0
  197. package/dist/utils/output-utils.js +250 -0
  198. package/dist/utils/pipeline-config.d.ts +33 -0
  199. package/dist/utils/pipeline-config.d.ts.map +1 -0
  200. package/dist/utils/pipeline-config.js +55 -0
  201. package/dist/utils/platform-secret.d.ts +27 -0
  202. package/dist/utils/platform-secret.d.ts.map +1 -0
  203. package/dist/utils/platform-secret.js +92 -0
  204. package/dist/utils/plugin-resolver.d.ts +17 -0
  205. package/dist/utils/plugin-resolver.d.ts.map +1 -0
  206. package/dist/utils/plugin-resolver.js +101 -0
  207. package/dist/utils/preflight.d.ts +26 -0
  208. package/dist/utils/preflight.d.ts.map +1 -0
  209. package/dist/utils/preflight.js +59 -0
  210. package/dist/utils/rate-limiter.d.ts +15 -0
  211. package/dist/utils/rate-limiter.d.ts.map +1 -0
  212. package/dist/utils/rate-limiter.js +164 -0
  213. package/dist/utils/registry.d.ts +86 -0
  214. package/dist/utils/registry.d.ts.map +1 -0
  215. package/dist/utils/registry.js +140 -0
  216. package/dist/utils/response-utils.d.ts +21 -0
  217. package/dist/utils/response-utils.d.ts.map +1 -0
  218. package/dist/utils/response-utils.js +70 -0
  219. package/dist/utils/tls.d.ts +52 -0
  220. package/dist/utils/tls.d.ts.map +1 -0
  221. package/dist/utils/tls.js +88 -0
  222. package/package.json +181 -0
@@ -0,0 +1,275 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { Command } from 'commander';
6
+ import FormData from 'form-data';
7
+ import ora from 'ora';
8
+ import pico from 'picocolors';
9
+ import { FILE_SIZE_LIMITS, formatFileSize } from '../config/cli.constants.js';
10
+ import {} from '../types/index.js';
11
+ import { printCommandHeader, printSslWarning, createAuthenticatedClient, withSslOptions } from '../utils/command-utils.js';
12
+ import { ERROR_CODES, handleError, ValidationError } from '../utils/error-handler.js';
13
+ import { fileExists, printError, printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
14
+ import { extractSingleResponse } from '../utils/response-utils.js';
15
+ const { bold, green } = pico;
16
+ /**
17
+ * Registers the `upload-plugin` command with the CLI program.
18
+ *
19
+ * Validates a local plugin ZIP file (size, extension, readability),
20
+ * builds a multipart form, and uploads it to the platform API.
21
+ * Plugin name and version can be auto-detected from the package
22
+ * or overridden via CLI flags.
23
+ *
24
+ * @param program - The root Commander program instance to attach the command to.
25
+ *
26
+ * @example
27
+ * ```bash
28
+ * cli plugin upload --file plugin.zip --organization acme
29
+ * cli plugin upload --file plugin.zip --organization acme --public
30
+ * cli plugin upload --file plugin.zip --organization acme --name my-plugin --version 1.0.0
31
+ * cli plugin upload --file plugin.zip --organization acme --no-verify-ssl
32
+ * ```
33
+ */
34
+ export function uploadPlugin(program) {
35
+ withSslOptions(program
36
+ .command('upload')
37
+ .description('Upload and deploy a plugin package')
38
+ .requiredOption('-f, --file <file>', 'Path to plugin ZIP file')
39
+ .requiredOption('-o, --organization <organization>', 'Organization name')
40
+ .option('-n, --name <name>', 'Plugin name (optional, extracted from package if not provided)')
41
+ .option('-v, --version <version>', 'Plugin version (optional, extracted from package if not provided)')
42
+ .option('--public', 'Make plugin publicly accessible', false)
43
+ .option('--active', 'Set plugin as active', true)
44
+ .option('--no-active', 'Upload the plugin as inactive'))
45
+ .option('--dry-run', 'Validate file without uploading', false)
46
+ .action(async (options) => {
47
+ const executionId = printCommandHeader('Upload Plugin');
48
+ try {
49
+ // Display parameters
50
+ printInfo('Upload parameters', {
51
+ file: options.file,
52
+ organization: options.organization,
53
+ name: options.name || '(auto-detect)',
54
+ version: options.version || '(auto-detect)',
55
+ public: options.public ? 'Yes' : 'No',
56
+ active: options.active ? 'Yes' : 'No',
57
+ dryRun: options.dryRun,
58
+ verifySsl: options.verifySsl,
59
+ });
60
+ // Security warning for SSL verification disabled
61
+ printSslWarning(options.verifySsl);
62
+ // Validate organization
63
+ if (!options.organization || typeof options.organization !== 'string' || options.organization.trim().length === 0) {
64
+ printError('Invalid organization name', { provided: options.organization });
65
+ throw new ValidationError('Organization must be a non-empty string', 'organization', options.organization);
66
+ }
67
+ // Validate file path
68
+ if (!options.file || typeof options.file !== 'string' || options.file.trim().length === 0) {
69
+ printError('Invalid file path', { provided: options.file });
70
+ throw new ValidationError('File path must be a non-empty string', 'file', options.file);
71
+ }
72
+ const filePath = path.resolve(options.file);
73
+ // Validate file exists
74
+ printInfo('Validating plugin file', { path: filePath });
75
+ if (!fileExists(filePath)) {
76
+ printError('Plugin file not found', { path: filePath });
77
+ throw new ValidationError(`Plugin file not found: ${filePath}`, 'file', filePath);
78
+ }
79
+ // Validate file extension
80
+ const fileExt = path.extname(filePath).toLowerCase();
81
+ if (fileExt !== '.zip') {
82
+ printWarning('File extension is not .zip', {
83
+ provided: fileExt,
84
+ expected: '.zip',
85
+ });
86
+ throw new ValidationError('Plugin file must be a ZIP archive', 'file', filePath);
87
+ }
88
+ // Get file stats
89
+ const stats = fs.statSync(filePath);
90
+ const sizeBytes = stats.size;
91
+ const sizeFormatted = formatFileSize(sizeBytes);
92
+ printSuccess('Plugin file found', {
93
+ path: filePath,
94
+ size: sizeFormatted,
95
+ modified: new Date(stats.mtime).toLocaleString(),
96
+ });
97
+ // Check file size
98
+ if (sizeBytes > FILE_SIZE_LIMITS.PLUGIN) {
99
+ printError('Plugin file too large', {
100
+ size: sizeFormatted,
101
+ maximum: formatFileSize(FILE_SIZE_LIMITS.PLUGIN),
102
+ exceededBy: formatFileSize(sizeBytes - FILE_SIZE_LIMITS.PLUGIN),
103
+ });
104
+ throw new ValidationError(`Plugin file exceeds maximum size of ${formatFileSize(FILE_SIZE_LIMITS.PLUGIN)} (actual: ${sizeFormatted})`, 'file.size', sizeBytes);
105
+ }
106
+ // Check if file is readable
107
+ try {
108
+ fs.accessSync(filePath, fs.constants.R_OK);
109
+ }
110
+ catch (error) {
111
+ printError('Cannot read plugin file', {
112
+ path: filePath,
113
+ error: error instanceof Error ? error.message : String(error),
114
+ });
115
+ throw new ValidationError('Plugin file is not readable', 'file', filePath);
116
+ }
117
+ printSuccess('Plugin file validated');
118
+ // Validate version format if provided. Allows -prerelease and +build
119
+ // metadata (valid semver) to match validate-plugin and the DB constraint.
120
+ if (options.version) {
121
+ const versionRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
122
+ if (!versionRegex.test(options.version)) {
123
+ printWarning('Version format may be invalid', {
124
+ provided: options.version,
125
+ expected: 'semantic version (e.g., 1.0.0, 1.2.3-beta.1)',
126
+ });
127
+ }
128
+ }
129
+ // Validate name format if provided
130
+ if (options.name) {
131
+ const nameRegex = /^[a-z0-9-]+$/;
132
+ if (!nameRegex.test(options.name)) {
133
+ printWarning('Plugin name format may be invalid', {
134
+ provided: options.name,
135
+ expected: 'lowercase alphanumeric with dashes (e.g., my-plugin-name)',
136
+ });
137
+ }
138
+ }
139
+ // Dry run mode
140
+ if (options.dryRun) {
141
+ console.log('');
142
+ printSection('Dry Run - Validation Complete');
143
+ printSuccess('File validation passed - no upload performed');
144
+ printKeyValue({
145
+ File: filePath,
146
+ Size: sizeFormatted,
147
+ Organization: options.organization,
148
+ Name: options.name || '(will be auto-detected)',
149
+ Version: options.version || '(will be auto-detected)',
150
+ Public: options.public ? 'Yes' : 'No',
151
+ Active: options.active ? 'Yes' : 'No',
152
+ });
153
+ return;
154
+ }
155
+ // Create authenticated API client
156
+ const client = createAuthenticatedClient(options);
157
+ const config = client.getConfig();
158
+ // Create form data
159
+ console.log('');
160
+ printSection('Uploading Plugin');
161
+ printInfo('Preparing upload', {
162
+ file: path.basename(filePath),
163
+ size: sizeFormatted,
164
+ });
165
+ const formData = new FormData();
166
+ formData.append('plugin', fs.createReadStream(filePath), {
167
+ filename: path.basename(filePath),
168
+ contentType: 'application/zip',
169
+ });
170
+ formData.append('organization', options.organization);
171
+ if (options.name)
172
+ formData.append('name', options.name);
173
+ if (options.version)
174
+ formData.append('version', options.version);
175
+ formData.append('isPublic', options.public ? 'true' : 'false');
176
+ formData.append('isActive', options.active ? 'true' : 'false');
177
+ // Make API request
178
+ const endpoint = config.api.pluginUploadUrl;
179
+ printInfo('Uploading to API', {
180
+ endpoint: `${config.api.baseUrl}${endpoint}`,
181
+ });
182
+ console.log('');
183
+ const spinner = ora('Uploading plugin...').start();
184
+ let rawResponse;
185
+ let duration;
186
+ try {
187
+ const startTime = Date.now();
188
+ rawResponse = await client.postForm(endpoint, formData);
189
+ duration = Date.now() - startTime;
190
+ spinner.succeed('Plugin uploaded');
191
+ }
192
+ catch (error) {
193
+ spinner.fail('Upload failed');
194
+ throw error;
195
+ }
196
+ const response = extractSingleResponse(rawResponse, 'plugin', 'name');
197
+ if (!response) {
198
+ printError('No valid plugin data in response', {
199
+ responseKeys: rawResponse ? Object.keys(rawResponse) : '(null)',
200
+ });
201
+ throw new Error('Upload failed - no valid plugin data received');
202
+ }
203
+ console.log('');
204
+ printSection('Plugin Uploaded Successfully');
205
+ // Display plugin information
206
+ printKeyValue({
207
+ 'Plugin ID': green(bold(response.id)),
208
+ 'Name': response.name,
209
+ 'Version': response.version,
210
+ 'Organization': response.organization,
211
+ 'Description': response.description || '(not set)',
212
+ });
213
+ console.log('');
214
+ printKeyValue({
215
+ 'File URL': response.fileUrl || '(not available)',
216
+ 'File Size': response.fileSize ? `${(response.fileSize / 1024).toFixed(2)} KB` : '(not available)',
217
+ 'Checksum': response.checksum ? `${response.checksum.substring(0, 16)}...` : '(not available)',
218
+ });
219
+ console.log('');
220
+ printKeyValue({
221
+ 'Public': response.isPublic ? 'Yes' : 'No',
222
+ 'Active': response.isActive ? 'Yes' : 'No',
223
+ 'Created At': response.createdAt || '(not available)',
224
+ 'Uploaded By': response.uploadedBy || '(not available)',
225
+ });
226
+ console.log('');
227
+ printKeyValue({
228
+ 'Execution ID': executionId,
229
+ 'Upload Duration': `${(duration / 1000).toFixed(2)}s`,
230
+ 'Status': green('✓ Success'),
231
+ });
232
+ // Print additional information if available
233
+ if (response.metadata) {
234
+ console.log('');
235
+ printInfo('Plugin metadata available', {
236
+ keys: Object.keys(response.metadata).length,
237
+ });
238
+ }
239
+ // Print deployment logs URL if available
240
+ const resp = response;
241
+ const requestId = resp['X-Request-Id'] || resp.requestId;
242
+ if (requestId) {
243
+ console.log('');
244
+ printInfo('Deployment logs available', {
245
+ requestId,
246
+ url: `${config.api.baseUrl}/logs/${requestId}`,
247
+ });
248
+ }
249
+ // Next steps
250
+ console.log('');
251
+ printInfo('Next steps', {
252
+ view: `Use "get-plugin --id ${response.id}" to view plugin details`,
253
+ list: 'Use "list-plugins" to see all plugins',
254
+ });
255
+ }
256
+ catch (error) {
257
+ handleError(error, ERROR_CODES.API_REQUEST, {
258
+ debug: program.opts().debug,
259
+ exit: true,
260
+ context: {
261
+ command: 'upload-plugin',
262
+ executionId,
263
+ file: options.file,
264
+ organization: options.organization,
265
+ name: options.name,
266
+ version: options.version,
267
+ public: options.public,
268
+ active: options.active,
269
+ verifySsl: options.verifySsl,
270
+ },
271
+ });
272
+ }
273
+ });
274
+ }
275
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLXBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy91cGxvYWQtcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLFFBQVEsTUFBTSxXQUFXLENBQUM7QUFDakMsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQ3RCLE9BQU8sSUFBSSxNQUFNLFlBQVksQ0FBQztBQUM5QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUUsT0FBTyxFQUFvQyxNQUFNLG1CQUFtQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUseUJBQXlCLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0gsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RJLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRW5FLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRTdCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsT0FBZ0I7SUFDM0MsY0FBYyxDQUFDLE9BQU87U0FDbkIsT0FBTyxDQUFDLFFBQVEsQ0FBQztTQUNqQixX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LEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUU7b0JBQ1AsT0FBTyxFQUFFLGVBQWU7b0JBQ3hCLFdBQVc7b0JBQ1gsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7b0JBQ2xDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO29CQUN4QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07b0JBQ3RCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtvQkFDdEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO2lCQUM3QjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IEZvcm1EYXRhIGZyb20gJ2Zvcm0tZGF0YSc7XG5pbXBvcnQgb3JhIGZyb20gJ29yYSc7XG5pbXBvcnQgcGljbyBmcm9tICdwaWNvY29sb3JzJztcbmltcG9ydCB7IEZJTEVfU0laRV9MSU1JVFMsIGZvcm1hdEZpbGVTaXplIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgdHlwZSBQbHVnaW4sIHR5cGUgUGx1Z2luUmVzcG9uc2UgfSBmcm9tICcuLi90eXBlcy9pbmRleC5qcyc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIsIHByaW50U3NsV2FybmluZywgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudCwgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBmaWxlRXhpc3RzLCBwcmludEVycm9yLCBwcmludEluZm8sIHByaW50S2V5VmFsdWUsIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzLCBwcmludFdhcm5pbmcgfSBmcm9tICcuLi91dGlscy9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHsgZXh0cmFjdFNpbmdsZVJlc3BvbnNlIH0gZnJvbSAnLi4vdXRpbHMvcmVzcG9uc2UtdXRpbHMuanMnO1xuXG5jb25zdCB7IGJvbGQsIGdyZWVuIH0gPSBwaWNvO1xuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgYHVwbG9hZC1wbHVnaW5gIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogVmFsaWRhdGVzIGEgbG9jYWwgcGx1Z2luIFpJUCBmaWxlIChzaXplLCBleHRlbnNpb24sIHJlYWRhYmlsaXR5KSxcbiAqIGJ1aWxkcyBhIG11bHRpcGFydCBmb3JtLCBhbmQgdXBsb2FkcyBpdCB0byB0aGUgcGxhdGZvcm0gQVBJLlxuICogUGx1Z2luIG5hbWUgYW5kIHZlcnNpb24gY2FuIGJlIGF1dG8tZGV0ZWN0ZWQgZnJvbSB0aGUgcGFja2FnZVxuICogb3Igb3ZlcnJpZGRlbiB2aWEgQ0xJIGZsYWdzLlxuICpcbiAqIEBwYXJhbSBwcm9ncmFtIC0gVGhlIHJvb3QgQ29tbWFuZGVyIHByb2dyYW0gaW5zdGFuY2UgdG8gYXR0YWNoIHRoZSBjb21tYW5kIHRvLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBjbGkgcGx1Z2luIHVwbG9hZCAtLWZpbGUgcGx1Z2luLnppcCAtLW9yZ2FuaXphdGlvbiBhY21lXG4gKiBjbGkgcGx1Z2luIHVwbG9hZCAtLWZpbGUgcGx1Z2luLnppcCAtLW9yZ2FuaXphdGlvbiBhY21lIC0tcHVibGljXG4gKiBjbGkgcGx1Z2luIHVwbG9hZCAtLWZpbGUgcGx1Z2luLnppcCAtLW9yZ2FuaXphdGlvbiBhY21lIC0tbmFtZSBteS1wbHVnaW4gLS12ZXJzaW9uIDEuMC4wXG4gKiBjbGkgcGx1Z2luIHVwbG9hZCAtLWZpbGUgcGx1Z2luLnppcCAtLW9yZ2FuaXphdGlvbiBhY21lIC0tbm8tdmVyaWZ5LXNzbFxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRQbHVnaW4ocHJvZ3JhbTogQ29tbWFuZCk6IHZvaWQge1xuICB3aXRoU3NsT3B0aW9ucyhwcm9ncmFtXG4gICAgLmNvbW1hbmQoJ3VwbG9hZCcpXG4gICAgLmRlc2NyaXB0aW9uKCdVcGxvYWQgYW5kIGRlcGxveSBhIHBsdWdpbiBwYWNrYWdlJylcbiAgICAucmVxdWlyZWRPcHRpb24oJy1mLCAtLWZpbGUgPGZpbGU+JywgJ1BhdGggdG8gcGx1Z2luIFpJUCBmaWxlJylcbiAgICAucmVxdWlyZWRPcHRpb24oJy1vLCAtLW9yZ2FuaXphdGlvbiA8b3JnYW5pemF0aW9uPicsICdPcmdhbml6YXRpb24gbmFtZScpXG4gICAgLm9wdGlvbignLW4sIC0tbmFtZSA8bmFtZT4nLCAnUGx1Z2luIG5hbWUgKG9wdGlvbmFsLCBleHRyYWN0ZWQgZnJvbSBwYWNrYWdlIGlmIG5vdCBwcm92aWRlZCknKVxuICAgIC5vcHRpb24oJy12LCAtLXZlcnNpb24gPHZlcnNpb24+JywgJ1BsdWdpbiB2ZXJzaW9uIChvcHRpb25hbCwgZXh0cmFjdGVkIGZyb20gcGFja2FnZSBpZiBub3QgcHJvdmlkZWQpJylcbiAgICAub3B0aW9uKCctLXB1YmxpYycsICdNYWtlIHBsdWdpbiBwdWJsaWNseSBhY2Nlc3NpYmxlJywgZmFsc2UpXG4gICAgLm9wdGlvbignLS1hY3RpdmUnLCAnU2V0IHBsdWdpbiBhcyBhY3RpdmUnLCB0cnVlKVxuICAgIC5vcHRpb24oJy0tbm8tYWN0aXZlJywgJ1VwbG9hZCB0aGUgcGx1Z2luIGFzIGluYWN0aXZlJykpXG4gICAgLm9wdGlvbignLS1kcnktcnVuJywgJ1ZhbGlkYXRlIGZpbGUgd2l0aG91dCB1cGxvYWRpbmcnLCBmYWxzZSlcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignVXBsb2FkIFBsdWdpbicpO1xuXG4gICAgICB0cnkge1xuXG4gICAgICAgIC8vIERpc3BsYXkgcGFyYW1ldGVyc1xuICAgICAgICBwcmludEluZm8oJ1VwbG9hZCBwYXJhbWV0ZXJzJywge1xuICAgICAgICAgIGZpbGU6IG9wdGlvbnMuZmlsZSxcbiAgICAgICAgICBvcmdhbml6YXRpb246IG9wdGlvbnMub3JnYW5pemF0aW9uLFxuICAgICAgICAgIG5hbWU6IG9wdGlvbnMubmFtZSB8fCAnKGF1dG8tZGV0ZWN0KScsXG4gICAgICAgICAgdmVyc2lvbjogb3B0aW9ucy52ZXJzaW9uIHx8ICcoYXV0by1kZXRlY3QpJyxcbiAgICAgICAgICBwdWJsaWM6IG9wdGlvbnMucHVibGljID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgIGFjdGl2ZTogb3B0aW9ucy5hY3RpdmUgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgZHJ5UnVuOiBvcHRpb25zLmRyeVJ1bixcbiAgICAgICAgICB2ZXJpZnlTc2w6IG9wdGlvbnMudmVyaWZ5U3NsLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTZWN1cml0eSB3YXJuaW5nIGZvciBTU0wgdmVyaWZpY2F0aW9uIGRpc2FibGVkXG4gICAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgb3JnYW5pemF0aW9uXG4gICAgICAgIGlmICghb3B0aW9ucy5vcmdhbml6YXRpb24gfHwgdHlwZW9mIG9wdGlvbnMub3JnYW5pemF0aW9uICE9PSAnc3RyaW5nJyB8fCBvcHRpb25zLm9yZ2FuaXphdGlvbi50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcHJpbnRFcnJvcignSW52YWxpZCBvcmdhbml6YXRpb24gbmFtZScsIHsgcHJvdmlkZWQ6IG9wdGlvbnMub3JnYW5pemF0aW9uIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ09yZ2FuaXphdGlvbiBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZycsICdvcmdhbml6YXRpb24nLCBvcHRpb25zLm9yZ2FuaXphdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWYWxpZGF0ZSBmaWxlIHBhdGhcbiAgICAgICAgaWYgKCFvcHRpb25zLmZpbGUgfHwgdHlwZW9mIG9wdGlvbnMuZmlsZSAhPT0gJ3N0cmluZycgfHwgb3B0aW9ucy5maWxlLnRyaW0oKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBwcmludEVycm9yKCdJbnZhbGlkIGZpbGUgcGF0aCcsIHsgcHJvdmlkZWQ6IG9wdGlvbnMuZmlsZSB9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdGaWxlIHBhdGggbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcnLCAnZmlsZScsIG9wdGlvbnMuZmlsZSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGgucmVzb2x2ZShvcHRpb25zLmZpbGUpO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIGZpbGUgZXhpc3RzXG4gICAgICAgIHByaW50SW5mbygnVmFsaWRhdGluZyBwbHVnaW4gZmlsZScsIHsgcGF0aDogZmlsZVBhdGggfSk7XG5cbiAgICAgICAgaWYgKCFmaWxlRXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHByaW50RXJyb3IoJ1BsdWdpbiBmaWxlIG5vdCBmb3VuZCcsIHsgcGF0aDogZmlsZVBhdGggfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihgUGx1Z2luIGZpbGUgbm90IGZvdW5kOiAke2ZpbGVQYXRofWAsICdmaWxlJywgZmlsZVBhdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgZmlsZSBleHRlbnNpb25cbiAgICAgICAgY29uc3QgZmlsZUV4dCA9IHBhdGguZXh0bmFtZShmaWxlUGF0aCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKGZpbGVFeHQgIT09ICcuemlwJykge1xuICAgICAgICAgIHByaW50V2FybmluZygnRmlsZSBleHRlbnNpb24gaXMgbm90IC56aXAnLCB7XG4gICAgICAgICAgICBwcm92aWRlZDogZmlsZUV4dCxcbiAgICAgICAgICAgIGV4cGVjdGVkOiAnLnppcCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUGx1Z2luIGZpbGUgbXVzdCBiZSBhIFpJUCBhcmNoaXZlJywgJ2ZpbGUnLCBmaWxlUGF0aCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZXQgZmlsZSBzdGF0c1xuICAgICAgICBjb25zdCBzdGF0cyA9IGZzLnN0YXRTeW5jKGZpbGVQYXRoKTtcbiAgICAgICAgY29uc3Qgc2l6ZUJ5dGVzID0gc3RhdHMuc2l6ZTtcbiAgICAgICAgY29uc3Qgc2l6ZUZvcm1hdHRlZCA9IGZvcm1hdEZpbGVTaXplKHNpemVCeXRlcyk7XG5cbiAgICAgICAgcHJpbnRTdWNjZXNzKCdQbHVnaW4gZmlsZSBmb3VuZCcsIHtcbiAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICBzaXplOiBzaXplRm9ybWF0dGVkLFxuICAgICAgICAgIG1vZGlmaWVkOiBuZXcgRGF0ZShzdGF0cy5tdGltZSkudG9Mb2NhbGVTdHJpbmcoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQ2hlY2sgZmlsZSBzaXplXG4gICAgICAgIGlmIChzaXplQnl0ZXMgPiBGSUxFX1NJWkVfTElNSVRTLlBMVUdJTikge1xuICAgICAgICAgIHByaW50RXJyb3IoJ1BsdWdpbiBmaWxlIHRvbyBsYXJnZScsIHtcbiAgICAgICAgICAgIHNpemU6IHNpemVGb3JtYXR0ZWQsXG4gICAgICAgICAgICBtYXhpbXVtOiBmb3JtYXRGaWxlU2l6ZShGSUxFX1NJWkVfTElNSVRTLlBMVUdJTiksXG4gICAgICAgICAgICBleGNlZWRlZEJ5OiBmb3JtYXRGaWxlU2l6ZShzaXplQnl0ZXMgLSBGSUxFX1NJWkVfTElNSVRTLlBMVUdJTiksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgICAgIGBQbHVnaW4gZmlsZSBleGNlZWRzIG1heGltdW0gc2l6ZSBvZiAke2Zvcm1hdEZpbGVTaXplKEZJTEVfU0laRV9MSU1JVFMuUExVR0lOKX0gKGFjdHVhbDogJHtzaXplRm9ybWF0dGVkfSlgLFxuICAgICAgICAgICAgJ2ZpbGUuc2l6ZScsXG4gICAgICAgICAgICBzaXplQnl0ZXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIGZpbGUgaXMgcmVhZGFibGVcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmcy5hY2Nlc3NTeW5jKGZpbGVQYXRoLCBmcy5jb25zdGFudHMuUl9PSyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgcHJpbnRFcnJvcignQ2Fubm90IHJlYWQgcGx1Z2luIGZpbGUnLCB7XG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUGx1Z2luIGZpbGUgaXMgbm90IHJlYWRhYmxlJywgJ2ZpbGUnLCBmaWxlUGF0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBwcmludFN1Y2Nlc3MoJ1BsdWdpbiBmaWxlIHZhbGlkYXRlZCcpO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIHZlcnNpb24gZm9ybWF0IGlmIHByb3ZpZGVkLiBBbGxvd3MgLXByZXJlbGVhc2UgYW5kICtidWlsZFxuICAgICAgICAvLyBtZXRhZGF0YSAodmFsaWQgc2VtdmVyKSB0byBtYXRjaCB2YWxpZGF0ZS1wbHVnaW4gYW5kIHRoZSBEQiBjb25zdHJhaW50LlxuICAgICAgICBpZiAob3B0aW9ucy52ZXJzaW9uKSB7XG4gICAgICAgICAgY29uc3QgdmVyc2lvblJlZ2V4ID0gL15cXGQrXFwuXFxkK1xcLlxcZCsoLVthLXpBLVowLTkuLV0rKT8oXFwrW2EtekEtWjAtOS4tXSspPyQvO1xuICAgICAgICAgIGlmICghdmVyc2lvblJlZ2V4LnRlc3Qob3B0aW9ucy52ZXJzaW9uKSkge1xuICAgICAgICAgICAgcHJpbnRXYXJuaW5nKCdWZXJzaW9uIGZvcm1hdCBtYXkgYmUgaW52YWxpZCcsIHtcbiAgICAgICAgICAgICAgcHJvdmlkZWQ6IG9wdGlvbnMudmVyc2lvbixcbiAgICAgICAgICAgICAgZXhwZWN0ZWQ6ICdzZW1hbnRpYyB2ZXJzaW9uIChlLmcuLCAxLjAuMCwgMS4yLjMtYmV0YS4xKScsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWYWxpZGF0ZSBuYW1lIGZvcm1hdCBpZiBwcm92aWRlZFxuICAgICAgICBpZiAob3B0aW9ucy5uYW1lKSB7XG4gICAgICAgICAgY29uc3QgbmFtZVJlZ2V4ID0gL15bYS16MC05LV0rJC87XG4gICAgICAgICAgaWYgKCFuYW1lUmVnZXgudGVzdChvcHRpb25zLm5hbWUpKSB7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoJ1BsdWdpbiBuYW1lIGZvcm1hdCBtYXkgYmUgaW52YWxpZCcsIHtcbiAgICAgICAgICAgICAgcHJvdmlkZWQ6IG9wdGlvbnMubmFtZSxcbiAgICAgICAgICAgICAgZXhwZWN0ZWQ6ICdsb3dlcmNhc2UgYWxwaGFudW1lcmljIHdpdGggZGFzaGVzIChlLmcuLCBteS1wbHVnaW4tbmFtZSknLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRHJ5IHJ1biBtb2RlXG4gICAgICAgIGlmIChvcHRpb25zLmRyeVJ1bikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICBwcmludFNlY3Rpb24oJ0RyeSBSdW4gLSBWYWxpZGF0aW9uIENvbXBsZXRlJyk7XG4gICAgICAgICAgcHJpbnRTdWNjZXNzKCdGaWxlIHZhbGlkYXRpb24gcGFzc2VkIC0gbm8gdXBsb2FkIHBlcmZvcm1lZCcpO1xuXG4gICAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgICBGaWxlOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIFNpemU6IHNpemVGb3JtYXR0ZWQsXG4gICAgICAgICAgICBPcmdhbml6YXRpb246IG9wdGlvbnMub3JnYW5pemF0aW9uLFxuICAgICAgICAgICAgTmFtZTogb3B0aW9ucy5uYW1lIHx8ICcod2lsbCBiZSBhdXRvLWRldGVjdGVkKScsXG4gICAgICAgICAgICBWZXJzaW9uOiBvcHRpb25zLnZlcnNpb24gfHwgJyh3aWxsIGJlIGF1dG8tZGV0ZWN0ZWQpJyxcbiAgICAgICAgICAgIFB1YmxpYzogb3B0aW9ucy5wdWJsaWMgPyAnWWVzJyA6ICdObycsXG4gICAgICAgICAgICBBY3RpdmU6IG9wdGlvbnMuYWN0aXZlID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGF1dGhlbnRpY2F0ZWQgQVBJIGNsaWVudFxuICAgICAgICBjb25zdCBjbGllbnQgPSBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50KG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBjb25maWcgPSBjbGllbnQuZ2V0Q29uZmlnKCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGZvcm0gZGF0YVxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U2VjdGlvbignVXBsb2FkaW5nIFBsdWdpbicpO1xuICAgICAgICBwcmludEluZm8oJ1ByZXBhcmluZyB1cGxvYWQnLCB7XG4gICAgICAgICAgZmlsZTogcGF0aC5iYXNlbmFtZShmaWxlUGF0aCksXG4gICAgICAgICAgc2l6ZTogc2l6ZUZvcm1hdHRlZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgZm9ybURhdGEuYXBwZW5kKCdwbHVnaW4nLCBmcy5jcmVhdGVSZWFkU3RyZWFtKGZpbGVQYXRoKSwge1xuICAgICAgICAgIGZpbGVuYW1lOiBwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKSxcbiAgICAgICAgICBjb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL3ppcCcsXG4gICAgICAgIH0pO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ29yZ2FuaXphdGlvbicsIG9wdGlvbnMub3JnYW5pemF0aW9uKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5uYW1lKSBmb3JtRGF0YS5hcHBlbmQoJ25hbWUnLCBvcHRpb25zLm5hbWUpO1xuICAgICAgICBpZiAob3B0aW9ucy52ZXJzaW9uKSBmb3JtRGF0YS5hcHBlbmQoJ3ZlcnNpb24nLCBvcHRpb25zLnZlcnNpb24pO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ2lzUHVibGljJywgb3B0aW9ucy5wdWJsaWMgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgICAgICAgZm9ybURhdGEuYXBwZW5kKCdpc0FjdGl2ZScsIG9wdGlvbnMuYWN0aXZlID8gJ3RydWUnIDogJ2ZhbHNlJyk7XG5cbiAgICAgICAgLy8gTWFrZSBBUEkgcmVxdWVzdFxuICAgICAgICBjb25zdCBlbmRwb2ludCA9IGNvbmZpZy5hcGkucGx1Z2luVXBsb2FkVXJsO1xuICAgICAgICBwcmludEluZm8oJ1VwbG9hZGluZyB0byBBUEknLCB7XG4gICAgICAgICAgZW5kcG9pbnQ6IGAke2NvbmZpZy5hcGkuYmFzZVVybH0ke2VuZHBvaW50fWAsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcblxuICAgICAgICBjb25zdCBzcGlubmVyID0gb3JhKCdVcGxvYWRpbmcgcGx1Z2luLi4uJykuc3RhcnQoKTtcbiAgICAgICAgbGV0IHJhd1Jlc3BvbnNlOiBQbHVnaW5SZXNwb25zZTtcbiAgICAgICAgbGV0IGR1cmF0aW9uOiBudW1iZXI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICByYXdSZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wb3N0Rm9ybTxQbHVnaW5SZXNwb25zZT4oZW5kcG9pbnQsIGZvcm1EYXRhKTtcbiAgICAgICAgICBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgICAgc3Bpbm5lci5zdWNjZWVkKCdQbHVnaW4gdXBsb2FkZWQnKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBzcGlubmVyLmZhaWwoJ1VwbG9hZCBmYWlsZWQnKTtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gZXh0cmFjdFNpbmdsZVJlc3BvbnNlPFBsdWdpbj4ocmF3UmVzcG9uc2UsICdwbHVnaW4nLCAnbmFtZScpO1xuXG4gICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICBwcmludEVycm9yKCdObyB2YWxpZCBwbHVnaW4gZGF0YSBpbiByZXNwb25zZScsIHtcbiAgICAgICAgICAgIHJlc3BvbnNlS2V5czogcmF3UmVzcG9uc2UgPyBPYmplY3Qua2V5cyhyYXdSZXNwb25zZSkgOiAnKG51bGwpJyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VwbG9hZCBmYWlsZWQgLSBubyB2YWxpZCBwbHVnaW4gZGF0YSByZWNlaXZlZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICBwcmludFNlY3Rpb24oJ1BsdWdpbiBVcGxvYWRlZCBTdWNjZXNzZnVsbHknKTtcblxuICAgICAgICAvLyBEaXNwbGF5IHBsdWdpbiBpbmZvcm1hdGlvblxuICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAnUGx1Z2luIElEJzogZ3JlZW4oYm9sZChyZXNwb25zZS5pZCkpLFxuICAgICAgICAgICdOYW1lJzogcmVzcG9uc2UubmFtZSxcbiAgICAgICAgICAnVmVyc2lvbic6IHJlc3BvbnNlLnZlcnNpb24sXG4gICAgICAgICAgJ09yZ2FuaXphdGlvbic6IHJlc3BvbnNlLm9yZ2FuaXphdGlvbixcbiAgICAgICAgICAnRGVzY3JpcHRpb24nOiByZXNwb25zZS5kZXNjcmlwdGlvbiB8fCAnKG5vdCBzZXQpJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAnRmlsZSBVUkwnOiByZXNwb25zZS5maWxlVXJsIHx8ICcobm90IGF2YWlsYWJsZSknLFxuICAgICAgICAgICdGaWxlIFNpemUnOiByZXNwb25zZS5maWxlU2l6ZSA/IGAkeyhyZXNwb25zZS5maWxlU2l6ZSAvIDEwMjQpLnRvRml4ZWQoMil9IEtCYCA6ICcobm90IGF2YWlsYWJsZSknLFxuICAgICAgICAgICdDaGVja3N1bSc6IHJlc3BvbnNlLmNoZWNrc3VtID8gYCR7cmVzcG9uc2UuY2hlY2tzdW0uc3Vic3RyaW5nKDAsIDE2KX0uLi5gIDogJyhub3QgYXZhaWxhYmxlKScsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgJ1B1YmxpYyc6IHJlc3BvbnNlLmlzUHVibGljID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgICdBY3RpdmUnOiByZXNwb25zZS5pc0FjdGl2ZSA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICAnQ3JlYXRlZCBBdCc6IHJlc3BvbnNlLmNyZWF0ZWRBdCB8fCAnKG5vdCBhdmFpbGFibGUpJyxcbiAgICAgICAgICAnVXBsb2FkZWQgQnknOiByZXNwb25zZS51cGxvYWRlZEJ5IHx8ICcobm90IGF2YWlsYWJsZSknLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdFeGVjdXRpb24gSUQnOiBleGVjdXRpb25JZCxcbiAgICAgICAgICAnVXBsb2FkIER1cmF0aW9uJzogYCR7KGR1cmF0aW9uIC8gMTAwMCkudG9GaXhlZCgyKX1zYCxcbiAgICAgICAgICAnU3RhdHVzJzogZ3JlZW4oJ+KckyBTdWNjZXNzJyksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFByaW50IGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gaWYgYXZhaWxhYmxlXG4gICAgICAgIGlmIChyZXNwb25zZS5tZXRhZGF0YSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICBwcmludEluZm8oJ1BsdWdpbiBtZXRhZGF0YSBhdmFpbGFibGUnLCB7XG4gICAgICAgICAgICBrZXlzOiBPYmplY3Qua2V5cyhyZXNwb25zZS5tZXRhZGF0YSkubGVuZ3RoLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJpbnQgZGVwbG95bWVudCBsb2dzIFVSTCBpZiBhdmFpbGFibGVcbiAgICAgICAgY29uc3QgcmVzcCA9IHJlc3BvbnNlIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgIGNvbnN0IHJlcXVlc3RJZCA9IHJlc3BbJ1gtUmVxdWVzdC1JZCddIHx8IHJlc3AucmVxdWVzdElkO1xuICAgICAgICBpZiAocmVxdWVzdElkKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50SW5mbygnRGVwbG95bWVudCBsb2dzIGF2YWlsYWJsZScsIHtcbiAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgIHVybDogYCR7Y29uZmlnLmFwaS5iYXNlVXJsfS9sb2dzLyR7cmVxdWVzdElkfWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOZXh0IHN0ZXBzXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRJbmZvKCdOZXh0IHN0ZXBzJywge1xuICAgICAgICAgIHZpZXc6IGBVc2UgXCJnZXQtcGx1Z2luIC0taWQgJHtyZXNwb25zZS5pZH1cIiB0byB2aWV3IHBsdWdpbiBkZXRhaWxzYCxcbiAgICAgICAgICBsaXN0OiAnVXNlIFwibGlzdC1wbHVnaW5zXCIgdG8gc2VlIGFsbCBwbHVnaW5zJyxcbiAgICAgICAgfSk7XG5cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICd1cGxvYWQtcGx1Z2luJyxcbiAgICAgICAgICAgIGV4ZWN1dGlvbklkLFxuICAgICAgICAgICAgZmlsZTogb3B0aW9ucy5maWxlLFxuICAgICAgICAgICAgb3JnYW5pemF0aW9uOiBvcHRpb25zLm9yZ2FuaXphdGlvbixcbiAgICAgICAgICAgIG5hbWU6IG9wdGlvbnMubmFtZSxcbiAgICAgICAgICAgIHZlcnNpb246IG9wdGlvbnMudmVyc2lvbixcbiAgICAgICAgICAgIHB1YmxpYzogb3B0aW9ucy5wdWJsaWMsXG4gICAgICAgICAgICBhY3RpdmU6IG9wdGlvbnMuYWN0aXZlLFxuICAgICAgICAgICAgdmVyaWZ5U3NsOiBvcHRpb25zLnZlcmlmeVNzbCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the `validate-plugin` command — run the same structural + `{{ }}`
4
+ * template checks the server's upload path enforces, against a LOCAL plugin
5
+ * directory, so authors catch problems before packaging/uploading. Exits
6
+ * non-zero on any problem (CI-friendly), mirroring `validate-templates`.
7
+ *
8
+ * Usage:
9
+ * pipeline-manager plugin validate --dir ./my-linter
10
+ */
11
+ export declare function validatePlugin(program: Command): void;
12
+ //# sourceMappingURL=validate-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-plugin.d.ts","sourceRoot":"","sources":["../../src/commands/validate-plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+IrD"}
@@ -0,0 +1,175 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { Command } from 'commander';
6
+ import YAML from 'yaml';
7
+ import { printCommandHeader } from '../utils/command-utils.js';
8
+ import { ERROR_CODES, handleError, ValidationError } from '../utils/error-handler.js';
9
+ import { printError, printSuccess, printWarning, fileExists } from '../utils/output-utils.js';
10
+ const PLUGIN_TYPES = ['CodeBuildStep', 'ShellStep', 'ManualApprovalStep'];
11
+ const COMPUTE_TYPES = ['SMALL', 'MEDIUM', 'LARGE', 'X2_LARGE'];
12
+ const FAILURE_BEHAVIORS = ['fail', 'warn', 'ignore'];
13
+ const BUILD_TYPES = ['build_image', 'prebuilt', 'metadata_only'];
14
+ /**
15
+ * Register the `validate-plugin` command — run the same structural + `{{ }}`
16
+ * template checks the server's upload path enforces, against a LOCAL plugin
17
+ * directory, so authors catch problems before packaging/uploading. Exits
18
+ * non-zero on any problem (CI-friendly), mirroring `validate-templates`.
19
+ *
20
+ * Usage:
21
+ * pipeline-manager plugin validate --dir ./my-linter
22
+ */
23
+ export function validatePlugin(program) {
24
+ program
25
+ .command('validate')
26
+ .description('Validate a local plugin directory (config.yaml + plugin-spec.yaml) before upload')
27
+ .requiredOption('--dir <path>', 'Path to the plugin directory')
28
+ .action(async (options) => {
29
+ const executionId = printCommandHeader('Validate Plugin');
30
+ try {
31
+ const dir = path.resolve(options.dir ?? '');
32
+ if (!fileExists(dir) || !fs.statSync(dir).isDirectory()) {
33
+ throw new ValidationError(`Not a directory: ${dir}`);
34
+ }
35
+ const problems = [];
36
+ // config.yaml (optional build manifest).
37
+ const configPath = ['config.yaml', 'config.yml'].map(f => path.join(dir, f)).find(fileExists);
38
+ let buildType = 'build_image';
39
+ let specFile = 'plugin-spec.yaml';
40
+ let dockerfileName = 'Dockerfile';
41
+ if (configPath) {
42
+ const config = (YAML.parse(fs.readFileSync(configPath, 'utf-8')) ?? {});
43
+ if (config.buildType !== undefined) {
44
+ if (typeof config.buildType !== 'string' || !BUILD_TYPES.includes(config.buildType)) {
45
+ problems.push(`config.yaml: buildType must be one of ${BUILD_TYPES.join(', ')}`);
46
+ }
47
+ else {
48
+ buildType = config.buildType;
49
+ }
50
+ }
51
+ if (typeof config.pluginSpec === 'string')
52
+ specFile = config.pluginSpec;
53
+ if (typeof config.dockerfile === 'string')
54
+ dockerfileName = config.dockerfile;
55
+ if ((buildType === 'prebuilt' || buildType === 'metadata_only') && config.dockerfile) {
56
+ problems.push(`config.yaml: dockerfile is not allowed when buildType is ${buildType}`);
57
+ }
58
+ }
59
+ // plugin-spec.yaml (required).
60
+ const specPath = path.join(dir, specFile);
61
+ if (!fileExists(specPath))
62
+ throw new ValidationError(`Missing plugin spec: ${specPath}`);
63
+ const spec = (YAML.parse(fs.readFileSync(specPath, 'utf-8')) ?? {});
64
+ // Required fields.
65
+ if (typeof spec.name !== 'string' || !spec.name)
66
+ problems.push('plugin-spec.yaml: name is required');
67
+ else if (!/^[a-z0-9-]+$/.test(spec.name))
68
+ problems.push('plugin-spec.yaml: name must match /^[a-z0-9-]+$/');
69
+ if (typeof spec.version !== 'string' || !spec.version)
70
+ problems.push('plugin-spec.yaml: version is required');
71
+ // Match the server/DB semver check (allows -prerelease and +build metadata).
72
+ else if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(spec.version))
73
+ problems.push('plugin-spec.yaml: version must be semver (x.y.z)');
74
+ const pluginType = (typeof spec.pluginType === 'string' ? spec.pluginType : 'CodeBuildStep');
75
+ if (!PLUGIN_TYPES.includes(pluginType))
76
+ problems.push(`plugin-spec.yaml: pluginType must be one of ${PLUGIN_TYPES.join(', ')}`);
77
+ if (spec.computeType !== undefined && !COMPUTE_TYPES.includes(String(spec.computeType))) {
78
+ problems.push(`plugin-spec.yaml: computeType must be one of ${COMPUTE_TYPES.join(', ')}`);
79
+ }
80
+ if (spec.failureBehavior !== undefined && !FAILURE_BEHAVIORS.includes(String(spec.failureBehavior))) {
81
+ problems.push(`plugin-spec.yaml: failureBehavior must be one of ${FAILURE_BEHAVIORS.join(', ')}`);
82
+ }
83
+ const isApproval = pluginType === 'ManualApprovalStep';
84
+ if (!isApproval && (!Array.isArray(spec.commands) || spec.commands.length === 0)) {
85
+ problems.push('plugin-spec.yaml: commands[] is required (except for ManualApprovalStep)');
86
+ }
87
+ // Build-type prerequisites.
88
+ if (buildType === 'build_image' && !isApproval && !fileExists(path.join(dir, dockerfileName))) {
89
+ problems.push(`Dockerfile not found for buildType build_image: ${path.join(dir, dockerfileName)}`);
90
+ }
91
+ if (buildType === 'prebuilt' && !fileExists(path.join(dir, 'image.tar'))) {
92
+ problems.push('image.tar not found for buildType prebuilt');
93
+ }
94
+ // `{{ }}` template validation — same scope roots + templatable fields the
95
+ // server enforces at upload (pipeline-core primitives; no server dep).
96
+ const core = await import('@pipeline-builder/pipeline-core');
97
+ const isTpl = (f) => f === 'description' ||
98
+ f.startsWith('commands') ||
99
+ f.startsWith('installCommands') ||
100
+ f.startsWith('env.') || f.startsWith('env[') ||
101
+ f.startsWith('buildArgs.') || f.startsWith('buildArgs[');
102
+ const isKnown = core.allowedScopeRoots(['pipeline', 'plugin', 'env']);
103
+ const { errors } = core.validateTemplates(spec, isTpl, isKnown);
104
+ for (const e of errors)
105
+ problems.push(`template [${e.field ?? '?'}]: ${e.message}`);
106
+ // Plugin CONTRACT check — mirrors the server's upload validation
107
+ // (api/plugin/src/helpers/plugin-spec.ts) so a spec rejected at upload also
108
+ // fails here (no false-green). Two independent rules per `{{ pipeline.vars.X }}`
109
+ // / `{{ pipeline.metadata.X }}` reference:
110
+ // (a) declaration: unless the token has a `| default:`, X must be declared
111
+ // in requiredVars / requiredMetadata;
112
+ // (b) coercion type: if the token has a `| number|bool|json` filter, the
113
+ // declared type in varsTypes/metadataTypes (default 'string') must match.
114
+ const requiredVars = new Set(Array.isArray(spec.requiredVars) ? spec.requiredVars.map(String) : []);
115
+ const requiredMetadata = new Set(Array.isArray(spec.requiredMetadata) ? spec.requiredMetadata.map(String) : []);
116
+ const varsTypes = spec.varsTypes ?? {};
117
+ const metadataTypes = spec.metadataTypes ?? {};
118
+ const coerceToType = { number: 'number', bool: 'bool', json: 'json' };
119
+ const templatableStrings = [
120
+ ...(typeof spec.description === 'string' ? [spec.description] : []),
121
+ ...(Array.isArray(spec.commands) ? spec.commands.filter((c) => typeof c === 'string') : []),
122
+ ...(Array.isArray(spec.installCommands) ? spec.installCommands.filter((c) => typeof c === 'string') : []),
123
+ ...Object.values(spec.env ?? {}).filter((v) => typeof v === 'string'),
124
+ ...Object.values(spec.buildArgs ?? {}).filter((v) => typeof v === 'string'),
125
+ ];
126
+ for (const source of templatableStrings) {
127
+ let tokens;
128
+ try {
129
+ tokens = core.tokenize(source);
130
+ }
131
+ catch {
132
+ continue;
133
+ }
134
+ for (const t of tokens) {
135
+ if (t.kind !== 'expr')
136
+ continue;
137
+ const [root, sub, key] = t.path;
138
+ if (root !== 'pipeline' || (sub !== 'vars' && sub !== 'metadata') || !key)
139
+ continue;
140
+ const isVars = sub === 'vars';
141
+ // (a) declaration — waived by a `| default:`.
142
+ if (t.defaultValue === undefined) {
143
+ const declared = isVars ? requiredVars.has(key) : requiredMetadata.has(key);
144
+ if (!declared)
145
+ problems.push(`contract: template references {{ pipeline.${sub}.${key} }} but '${key}' is not declared in ${isVars ? 'requiredVars' : 'requiredMetadata'}`);
146
+ }
147
+ // (b) coercion type — independent of default.
148
+ if (t.coerce) {
149
+ const declaredType = (isVars ? varsTypes : metadataTypes)[key] ?? 'string';
150
+ const expectedType = coerceToType[t.coerce];
151
+ if (expectedType && declaredType !== expectedType) {
152
+ problems.push(`contract: {{ pipeline.${sub}.${key} | ${t.coerce} }} but declared type is '${declaredType}' (add '${key}: ${expectedType}' to ${isVars ? 'varsTypes' : 'metadataTypes'})`);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ if (problems.length === 0) {
158
+ printSuccess(`Plugin '${String(spec.name)}' is valid`, { executionId, buildType, pluginType });
159
+ return;
160
+ }
161
+ printWarning(`Found ${problems.length} problem(s):`);
162
+ for (const p of problems)
163
+ printError(` • ${p}`);
164
+ process.exit(1);
165
+ }
166
+ catch (err) {
167
+ handleError(err, err instanceof ValidationError ? ERROR_CODES.VALIDATION : ERROR_CODES.GENERAL, {
168
+ debug: program.opts().debug,
169
+ exit: true,
170
+ context: { command: 'validate-plugin', executionId },
171
+ });
172
+ }
173
+ });
174
+ }
175
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtcGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3ZhbGlkYXRlLXBsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBTTlGLE1BQU0sWUFBWSxHQUFHLENBQUMsZUFBZSxFQUFFLFdBQVcsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0FBQzFFLE1BQU0sYUFBYSxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDL0QsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDckQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBRWpFOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxPQUFnQjtJQUM3QyxPQUFPO1NBQ0osT0FBTyxDQUFDLFVBQVUsQ0FBQztTQUNuQixXQUFXLENBQUMsa0ZBQWtGLENBQUM7U0FDL0YsY0FBYyxDQUFDLGNBQWMsRUFBRSw4QkFBOEIsQ0FBQztTQUM5RCxNQUFNLENBQUMsS0FB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Z0JBQzlGLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSztnQkFDM0IsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRTthQUNyRCxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IFlBTUwgZnJvbSAneWFtbCc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBwcmludEVycm9yLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZywgZmlsZUV4aXN0cyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbmludGVyZmFjZSBWYWxpZGF0ZVBsdWdpbk9wdGlvbnMge1xuICBkaXI/OiBzdHJpbmc7XG59XG5cbmNvbnN0IFBMVUdJTl9UWVBFUyA9IFsnQ29kZUJ1aWxkU3RlcCcsICdTaGVsbFN0ZXAnLCAnTWFudWFsQXBwcm92YWxTdGVwJ107XG5jb25zdCBDT01QVVRFX1RZUEVTID0gWydTTUFMTCcsICdNRURJVU0nLCAnTEFSR0UnLCAnWDJfTEFSR0UnXTtcbmNvbnN0IEZBSUxVUkVfQkVIQVZJT1JTID0gWydmYWlsJywgJ3dhcm4nLCAnaWdub3JlJ107XG5jb25zdCBCVUlMRF9UWVBFUyA9IFsnYnVpbGRfaW1hZ2UnLCAncHJlYnVpbHQnLCAnbWV0YWRhdGFfb25seSddO1xuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBgdmFsaWRhdGUtcGx1Z2luYCBjb21tYW5kIOKAlCBydW4gdGhlIHNhbWUgc3RydWN0dXJhbCArIGB7eyB9fWBcbiAqIHRlbXBsYXRlIGNoZWNrcyB0aGUgc2VydmVyJ3MgdXBsb2FkIHBhdGggZW5mb3JjZXMsIGFnYWluc3QgYSBMT0NBTCBwbHVnaW5cbiAqIGRpcmVjdG9yeSwgc28gYXV0aG9ycyBjYXRjaCBwcm9ibGVtcyBiZWZvcmUgcGFja2FnaW5nL3VwbG9hZGluZy4gRXhpdHNcbiAqIG5vbi16ZXJvIG9uIGFueSBwcm9ibGVtIChDSS1mcmllbmRseSksIG1pcnJvcmluZyBgdmFsaWRhdGUtdGVtcGxhdGVzYC5cbiAqXG4gKiBVc2FnZTpcbiAqICAgcGlwZWxpbmUtbWFuYWdlciBwbHVnaW4gdmFsaWRhdGUgLS1kaXIgLi9teS1saW50ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUGx1Z2luKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKCd2YWxpZGF0ZScpXG4gICAgLmRlc2NyaXB0aW9uKCdWYWxpZGF0ZSBhIGxvY2FsIHBsdWdpbiBkaXJlY3RvcnkgKGNvbmZpZy55YW1sICsgcGx1Z2luLXNwZWMueWFtbCkgYmVmb3JlIHVwbG9hZCcpXG4gICAgLnJlcXVpcmVkT3B0aW9uKCctLWRpciA8cGF0aD4nLCAnUGF0aCB0byB0aGUgcGx1Z2luIGRpcmVjdG9yeScpXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9uczogVmFsaWRhdGVQbHVnaW5PcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignVmFsaWRhdGUgUGx1Z2luJyk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkaXIgPSBwYXRoLnJlc29sdmUob3B0aW9ucy5kaXIgPz8gJycpO1xuICAgICAgICBpZiAoIWZpbGVFeGlzdHMoZGlyKSB8fCAhZnMuc3RhdFN5bmMoZGlyKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihgTm90IGEgZGlyZWN0b3J5OiAke2Rpcn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByb2JsZW1zOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIC8vIGNvbmZpZy55YW1sIChvcHRpb25hbCBidWlsZCBtYW5pZmVzdCkuXG4gICAgICAgIGNvbnN0IGNvbmZpZ1BhdGggPSBbJ2NvbmZpZy55YW1sJywgJ2NvbmZpZy55bWwnXS5tYXAoZiA9PiBwYXRoLmpvaW4oZGlyLCBmKSkuZmluZChmaWxlRXhpc3RzKTtcbiAgICAgICAgbGV0IGJ1aWxkVHlwZSA9ICdidWlsZF9pbWFnZSc7XG4gICAgICAgIGxldCBzcGVjRmlsZSA9ICdwbHVnaW4tc3BlYy55YW1sJztcbiAgICAgICAgbGV0IGRvY2tlcmZpbGVOYW1lID0gJ0RvY2tlcmZpbGUnO1xuICAgICAgICBpZiAoY29uZmlnUGF0aCkge1xuICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IChZQU1MLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmLTgnKSkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICAgIGlmIChjb25maWcuYnVpbGRUeXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnLmJ1aWxkVHlwZSAhPT0gJ3N0cmluZycgfHwgIUJVSUxEX1RZUEVTLmluY2x1ZGVzKGNvbmZpZy5idWlsZFR5cGUpKSB7XG4gICAgICAgICAgICAgIHByb2JsZW1zLnB1c2goYGNvbmZpZy55YW1sOiBidWlsZFR5cGUgbXVzdCBiZSBvbmUgb2YgJHtCVUlMRF9UWVBFUy5qb2luKCcsICcpfWApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYnVpbGRUeXBlID0gY29uZmlnLmJ1aWxkVHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcucGx1Z2luU3BlYyA9PT0gJ3N0cmluZycpIHNwZWNGaWxlID0gY29uZmlnLnBsdWdpblNwZWM7XG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcuZG9ja2VyZmlsZSA9PT0gJ3N0cmluZycpIGRvY2tlcmZpbGVOYW1lID0gY29uZmlnLmRvY2tlcmZpbGU7XG4gICAgICAgICAgaWYgKChidWlsZFR5cGUgPT09ICdwcmVidWlsdCcgfHwgYnVpbGRUeXBlID09PSAnbWV0YWRhdGFfb25seScpICYmIGNvbmZpZy5kb2NrZXJmaWxlKSB7XG4gICAgICAgICAgICBwcm9ibGVtcy5wdXNoKGBjb25maWcueWFtbDogZG9ja2VyZmlsZSBpcyBub3QgYWxsb3dlZCB3aGVuIGJ1aWxkVHlwZSBpcyAke2J1aWxkVHlwZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwbHVnaW4tc3BlYy55YW1sIChyZXF1aXJlZCkuXG4gICAgICAgIGNvbnN0IHNwZWNQYXRoID0gcGF0aC5qb2luKGRpciwgc3BlY0ZpbGUpO1xuICAgICAgICBpZiAoIWZpbGVFeGlzdHMoc3BlY1BhdGgpKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGBNaXNzaW5nIHBsdWdpbiBzcGVjOiAke3NwZWNQYXRofWApO1xuICAgICAgICBjb25zdCBzcGVjID0gKFlBTUwucGFyc2UoZnMucmVhZEZpbGVTeW5jKHNwZWNQYXRoLCAndXRmLTgnKSkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgICAgIC8vIFJlcXVpcmVkIGZpZWxkcy5cbiAgICAgICAgaWYgKHR5cGVvZiBzcGVjLm5hbWUgIT09ICdzdHJpbmcnIHx8ICFzcGVjLm5hbWUpIHByb2JsZW1zLnB1c2goJ3BsdWdpbi1zcGVjLnlhbWw6IG5hbWUgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgZWxzZSBpZiAoIS9eW2EtejAtOS1dKyQvLnRlc3Qoc3BlYy5uYW1lKSkgcHJvYmxlbXMucHVzaCgncGx1Z2luLXNwZWMueWFtbDogbmFtZSBtdXN0IG1hdGNoIC9eW2EtejAtOS1dKyQvJyk7XG4gICAgICAgIGlmICh0eXBlb2Ygc3BlYy52ZXJzaW9uICE9PSAnc3RyaW5nJyB8fCAhc3BlYy52ZXJzaW9uKSBwcm9ibGVtcy5wdXNoKCdwbHVnaW4tc3BlYy55YW1sOiB2ZXJzaW9uIGlzIHJlcXVpcmVkJyk7XG4gICAgICAgIC8vIE1hdGNoIHRoZSBzZXJ2ZXIvREIgc2VtdmVyIGNoZWNrIChhbGxvd3MgLXByZXJlbGVhc2UgYW5kICtidWlsZCBtZXRhZGF0YSkuXG4gICAgICAgIGVsc2UgaWYgKCEvXlxcZCtcXC5cXGQrXFwuXFxkKygtW2EtekEtWjAtOS4tXSspPyhcXCtbYS16QS1aMC05Li1dKyk/JC8udGVzdChzcGVjLnZlcnNpb24pKSBwcm9ibGVtcy5wdXNoKCdwbHVnaW4tc3BlYy55YW1sOiB2ZXJzaW9uIG11c3QgYmUgc2VtdmVyICh4LnkueiknKTtcblxuICAgICAgICBjb25zdCBwbHVnaW5UeXBlID0gKHR5cGVvZiBzcGVjLnBsdWdpblR5cGUgPT09ICdzdHJpbmcnID8gc3BlYy5wbHVnaW5UeXBlIDogJ0NvZGVCdWlsZFN0ZXAnKTtcbiAgICAgICAgaWYgKCFQTFVHSU5fVFlQRVMuaW5jbHVkZXMocGx1Z2luVHlwZSkpIHByb2JsZW1zLnB1c2goYHBsdWdpbi1zcGVjLnlhbWw6IHBsdWdpblR5cGUgbXVzdCBiZSBvbmUgb2YgJHtQTFVHSU5fVFlQRVMuam9pbignLCAnKX1gKTtcbiAgICAgICAgaWYgKHNwZWMuY29tcHV0ZVR5cGUgIT09IHVuZGVmaW5lZCAmJiAhQ09NUFVURV9UWVBFUy5pbmNsdWRlcyhTdHJpbmcoc3BlYy5jb21wdXRlVHlwZSkpKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaChgcGx1Z2luLXNwZWMueWFtbDogY29tcHV0ZVR5cGUgbXVzdCBiZSBvbmUgb2YgJHtDT01QVVRFX1RZUEVTLmpvaW4oJywgJyl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNwZWMuZmFpbHVyZUJlaGF2aW9yICE9PSB1bmRlZmluZWQgJiYgIUZBSUxVUkVfQkVIQVZJT1JTLmluY2x1ZGVzKFN0cmluZyhzcGVjLmZhaWx1cmVCZWhhdmlvcikpKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaChgcGx1Z2luLXNwZWMueWFtbDogZmFpbHVyZUJlaGF2aW9yIG11c3QgYmUgb25lIG9mICR7RkFJTFVSRV9CRUhBVklPUlMuam9pbignLCAnKX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlzQXBwcm92YWwgPSBwbHVnaW5UeXBlID09PSAnTWFudWFsQXBwcm92YWxTdGVwJztcbiAgICAgICAgaWYgKCFpc0FwcHJvdmFsICYmICghQXJyYXkuaXNBcnJheShzcGVjLmNvbW1hbmRzKSB8fCBzcGVjLmNvbW1hbmRzLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgICBwcm9ibGVtcy5wdXNoKCdwbHVnaW4tc3BlYy55YW1sOiBjb21tYW5kc1tdIGlzIHJlcXVpcmVkIChleGNlcHQgZm9yIE1hbnVhbEFwcHJvdmFsU3RlcCknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJ1aWxkLXR5cGUgcHJlcmVxdWlzaXRlcy5cbiAgICAgICAgaWYgKGJ1aWxkVHlwZSA9PT0gJ2J1aWxkX2ltYWdlJyAmJiAhaXNBcHByb3ZhbCAmJiAhZmlsZUV4aXN0cyhwYXRoLmpvaW4oZGlyLCBkb2NrZXJmaWxlTmFtZSkpKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaChgRG9ja2VyZmlsZSBub3QgZm91bmQgZm9yIGJ1aWxkVHlwZSBidWlsZF9pbWFnZTogJHtwYXRoLmpvaW4oZGlyLCBkb2NrZXJmaWxlTmFtZSl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1aWxkVHlwZSA9PT0gJ3ByZWJ1aWx0JyAmJiAhZmlsZUV4aXN0cyhwYXRoLmpvaW4oZGlyLCAnaW1hZ2UudGFyJykpKSB7XG4gICAgICAgICAgcHJvYmxlbXMucHVzaCgnaW1hZ2UudGFyIG5vdCBmb3VuZCBmb3IgYnVpbGRUeXBlIHByZWJ1aWx0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBge3sgfX1gIHRlbXBsYXRlIHZhbGlkYXRpb24g4oCUIHNhbWUgc2NvcGUgcm9vdHMgKyB0ZW1wbGF0YWJsZSBmaWVsZHMgdGhlXG4gICAgICAgIC8vIHNlcnZlciBlbmZvcmNlcyBhdCB1cGxvYWQgKHBpcGVsaW5lLWNvcmUgcHJpbWl0aXZlczsgbm8gc2VydmVyIGRlcCkuXG4gICAgICAgIGNvbnN0IGNvcmUgPSBhd2FpdCBpbXBvcnQoJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnKTtcbiAgICAgICAgY29uc3QgaXNUcGwgPSAoZjogc3RyaW5nKSA9PlxuICAgICAgICAgIGYgPT09ICdkZXNjcmlwdGlvbicgfHxcbiAgICAgICAgICBmLnN0YXJ0c1dpdGgoJ2NvbW1hbmRzJykgfHxcbiAgICAgICAgICBmLnN0YXJ0c1dpdGgoJ2luc3RhbGxDb21tYW5kcycpIHx8XG4gICAgICAgICAgZi5zdGFydHNXaXRoKCdlbnYuJykgfHwgZi5zdGFydHNXaXRoKCdlbnZbJykgfHxcbiAgICAgICAgICBmLnN0YXJ0c1dpdGgoJ2J1aWxkQXJncy4nKSB8fCBmLnN0YXJ0c1dpdGgoJ2J1aWxkQXJnc1snKTtcbiAgICAgICAgY29uc3QgaXNLbm93biA9IGNvcmUuYWxsb3dlZFNjb3BlUm9vdHMoWydwaXBlbGluZScsICdwbHVnaW4nLCAnZW52J10pO1xuICAgICAgICBjb25zdCB7IGVycm9ycyB9ID0gY29yZS52YWxpZGF0ZVRlbXBsYXRlcyhzcGVjLCBpc1RwbCwgaXNLbm93bik7XG4gICAgICAgIGZvciAoY29uc3QgZSBvZiBlcnJvcnMpIHByb2JsZW1zLnB1c2goYHRlbXBsYXRlIFske2UuZmllbGQgPz8gJz8nfV06ICR7ZS5tZXNzYWdlfWApO1xuXG4gICAgICAgIC8vIFBsdWdpbiBDT05UUkFDVCBjaGVjayDigJQgbWlycm9ycyB0aGUgc2VydmVyJ3MgdXBsb2FkIHZhbGlkYXRpb25cbiAgICAgICAgLy8gKGFwaS9wbHVnaW4vc3JjL2hlbHBlcnMvcGx1Z2luLXNwZWMudHMpIHNvIGEgc3BlYyByZWplY3RlZCBhdCB1cGxvYWQgYWxzb1xuICAgICAgICAvLyBmYWlscyBoZXJlIChubyBmYWxzZS1ncmVlbikuIFR3byBpbmRlcGVuZGVudCBydWxlcyBwZXIgYHt7IHBpcGVsaW5lLnZhcnMuWCB9fWBcbiAgICAgICAgLy8gLyBge3sgcGlwZWxpbmUubWV0YWRhdGEuWCB9fWAgcmVmZXJlbmNlOlxuICAgICAgICAvLyAgIChhKSBkZWNsYXJhdGlvbjogdW5sZXNzIHRoZSB0b2tlbiBoYXMgYSBgfCBkZWZhdWx0OmAsIFggbXVzdCBiZSBkZWNsYXJlZFxuICAgICAgICAvLyAgICAgICBpbiByZXF1aXJlZFZhcnMgLyByZXF1aXJlZE1ldGFkYXRhO1xuICAgICAgICAvLyAgIChiKSBjb2VyY2lvbiB0eXBlOiBpZiB0aGUgdG9rZW4gaGFzIGEgYHwgbnVtYmVyfGJvb2x8anNvbmAgZmlsdGVyLCB0aGVcbiAgICAgICAgLy8gICAgICAgZGVjbGFyZWQgdHlwZSBpbiB2YXJzVHlwZXMvbWV0YWRhdGFUeXBlcyAoZGVmYXVsdCAnc3RyaW5nJykgbXVzdCBtYXRjaC5cbiAgICAgICAgY29uc3QgcmVxdWlyZWRWYXJzID0gbmV3IFNldChBcnJheS5pc0FycmF5KHNwZWMucmVxdWlyZWRWYXJzKSA/IChzcGVjLnJlcXVpcmVkVmFycyBhcyB1bmtub3duW10pLm1hcChTdHJpbmcpIDogW10pO1xuICAgICAgICBjb25zdCByZXF1aXJlZE1ldGFkYXRhID0gbmV3IFNldChBcnJheS5pc0FycmF5KHNwZWMucmVxdWlyZWRNZXRhZGF0YSkgPyAoc3BlYy5yZXF1aXJlZE1ldGFkYXRhIGFzIHVua25vd25bXSkubWFwKFN0cmluZykgOiBbXSk7XG4gICAgICAgIGNvbnN0IHZhcnNUeXBlcyA9IChzcGVjLnZhcnNUeXBlcyBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA/PyB7fTtcbiAgICAgICAgY29uc3QgbWV0YWRhdGFUeXBlcyA9IChzcGVjLm1ldGFkYXRhVHlwZXMgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPz8ge307XG4gICAgICAgIGNvbnN0IGNvZXJjZVRvVHlwZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgbnVtYmVyOiAnbnVtYmVyJywgYm9vbDogJ2Jvb2wnLCBqc29uOiAnanNvbicgfTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGFibGVTdHJpbmdzOiBzdHJpbmdbXSA9IFtcbiAgICAgICAgICAuLi4odHlwZW9mIHNwZWMuZGVzY3JpcHRpb24gPT09ICdzdHJpbmcnID8gW3NwZWMuZGVzY3JpcHRpb25dIDogW10pLFxuICAgICAgICAgIC4uLihBcnJheS5pc0FycmF5KHNwZWMuY29tbWFuZHMpID8gc3BlYy5jb21tYW5kcy5maWx0ZXIoKGMpOiBjIGlzIHN0cmluZyA9PiB0eXBlb2YgYyA9PT0gJ3N0cmluZycpIDogW10pLFxuICAgICAgICAgIC4uLihBcnJheS5pc0FycmF5KHNwZWMuaW5zdGFsbENvbW1hbmRzKSA/IHNwZWMuaW5zdGFsbENvbW1hbmRzLmZpbHRlcigoYyk6IGMgaXMgc3RyaW5nID0+IHR5cGVvZiBjID09PSAnc3RyaW5nJykgOiBbXSksXG4gICAgICAgICAgLi4uT2JqZWN0LnZhbHVlcygoc3BlYy5lbnYgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID8/IHt9KS5maWx0ZXIoKHYpOiB2IGlzIHN0cmluZyA9PiB0eXBlb2YgdiA9PT0gJ3N0cmluZycpLFxuICAgICAgICAgIC4uLk9iamVjdC52YWx1ZXMoKHNwZWMuYnVpbGRBcmdzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA/PyB7fSkuZmlsdGVyKCh2KTogdiBpcyBzdHJpbmcgPT4gdHlwZW9mIHYgPT09ICdzdHJpbmcnKSxcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChjb25zdCBzb3VyY2Ugb2YgdGVtcGxhdGFibGVTdHJpbmdzKSB7XG4gICAgICAgICAgbGV0IHRva2VucztcbiAgICAgICAgICB0cnkgeyB0b2tlbnMgPSBjb3JlLnRva2VuaXplKHNvdXJjZSk7IH0gY2F0Y2ggeyBjb250aW51ZTsgfVxuICAgICAgICAgIGZvciAoY29uc3QgdCBvZiB0b2tlbnMpIHtcbiAgICAgICAgICAgIGlmICh0LmtpbmQgIT09ICdleHByJykgY29udGludWU7XG4gICAgICAgICAgICBjb25zdCBbcm9vdCwgc3ViLCBrZXldID0gdC5wYXRoO1xuICAgICAgICAgICAgaWYgKHJvb3QgIT09ICdwaXBlbGluZScgfHwgKHN1YiAhPT0gJ3ZhcnMnICYmIHN1YiAhPT0gJ21ldGFkYXRhJykgfHwgIWtleSkgY29udGludWU7XG4gICAgICAgICAgICBjb25zdCBpc1ZhcnMgPSBzdWIgPT09ICd2YXJzJztcbiAgICAgICAgICAgIC8vIChhKSBkZWNsYXJhdGlvbiDigJQgd2FpdmVkIGJ5IGEgYHwgZGVmYXVsdDpgLlxuICAgICAgICAgICAgaWYgKHQuZGVmYXVsdFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVjbGFyZWQgPSBpc1ZhcnMgPyByZXF1aXJlZFZhcnMuaGFzKGtleSkgOiByZXF1aXJlZE1ldGFkYXRhLmhhcyhrZXkpO1xuICAgICAgICAgICAgICBpZiAoIWRlY2xhcmVkKSBwcm9ibGVtcy5wdXNoKGBjb250cmFjdDogdGVtcGxhdGUgcmVmZXJlbmNlcyB7eyBwaXBlbGluZS4ke3N1Yn0uJHtrZXl9IH19IGJ1dCAnJHtrZXl9JyBpcyBub3QgZGVjbGFyZWQgaW4gJHtpc1ZhcnMgPyAncmVxdWlyZWRWYXJzJyA6ICdyZXF1aXJlZE1ldGFkYXRhJ31gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIChiKSBjb2VyY2lvbiB0eXBlIOKAlCBpbmRlcGVuZGVudCBvZiBkZWZhdWx0LlxuICAgICAgICAgICAgaWYgKHQuY29lcmNlKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlY2xhcmVkVHlwZSA9IChpc1ZhcnMgPyB2YXJzVHlwZXMgOiBtZXRhZGF0YVR5cGVzKVtrZXldID8/ICdzdHJpbmcnO1xuICAgICAgICAgICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSBjb2VyY2VUb1R5cGVbdC5jb2VyY2VdO1xuICAgICAgICAgICAgICBpZiAoZXhwZWN0ZWRUeXBlICYmIGRlY2xhcmVkVHlwZSAhPT0gZXhwZWN0ZWRUeXBlKSB7XG4gICAgICAgICAgICAgICAgcHJvYmxlbXMucHVzaChgY29udHJhY3Q6IHt7IHBpcGVsaW5lLiR7c3VifS4ke2tleX0gfCAke3QuY29lcmNlfSB9fSBidXQgZGVjbGFyZWQgdHlwZSBpcyAnJHtkZWNsYXJlZFR5cGV9JyAoYWRkICcke2tleX06ICR7ZXhwZWN0ZWRUeXBlfScgdG8gJHtpc1ZhcnMgPyAndmFyc1R5cGVzJyA6ICdtZXRhZGF0YVR5cGVzJ30pYCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJvYmxlbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcHJpbnRTdWNjZXNzKGBQbHVnaW4gJyR7U3RyaW5nKHNwZWMubmFtZSl9JyBpcyB2YWxpZGAsIHsgZXhlY3V0aW9uSWQsIGJ1aWxkVHlwZSwgcGx1Z2luVHlwZSB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBwcmludFdhcm5pbmcoYEZvdW5kICR7cHJvYmxlbXMubGVuZ3RofSBwcm9ibGVtKHMpOmApO1xuICAgICAgICBmb3IgKGNvbnN0IHAgb2YgcHJvYmxlbXMpIHByaW50RXJyb3IoYCAg4oCiICR7cH1gKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVyciwgZXJyIGluc3RhbmNlb2YgVmFsaWRhdGlvbkVycm9yID8gRVJST1JfQ09ERVMuVkFMSURBVElPTiA6IEVSUk9SX0NPREVTLkdFTkVSQUwsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgICAgICBjb250ZXh0OiB7IGNvbW1hbmQ6ICd2YWxpZGF0ZS1wbHVnaW4nLCBleGVjdXRpb25JZCB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the `validate-templates` command.
4
+ *
5
+ * Usage:
6
+ * pipeline-manager template validate --pipeline <uuid>
7
+ * pipeline-manager template validate --plugin <name:version>
8
+ * pipeline-manager template validate --file ./plugin-spec.yaml
9
+ */
10
+ export declare function validateTemplatesCommand(program: Command): void;
11
+ //# sourceMappingURL=validate-templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-templates.d.ts","sourceRoot":"","sources":["../../src/commands/validate-templates.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkF/D"}