@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,24 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `redrive-events` command with the CLI program.
4
+ *
5
+ * Manual fallback for the events Lambda's self-healing redrive (Phase 3): calls
6
+ * SQS `StartMessageMoveTask(DLQ → main queue)` for the `pipeline-builder-events`
7
+ * stack, moving messages that exhausted their receive count in the dead-letter
8
+ * queue back onto `pipeline-builder-events` so the ingestion Lambda re-processes
9
+ * them. Idempotent ingest (dedupe on `idempotencyKey`) prevents double-counting.
10
+ *
11
+ * The Lambda already does this automatically after a successful batch; this
12
+ * command is the operator escape hatch when the Lambda is down or the DLQ needs
13
+ * to be drained on demand. Like the Lambda, it refuses to start a second move
14
+ * task while one is already active (SQS allows only one in-flight task per
15
+ * source queue anyway).
16
+ *
17
+ * @example
18
+ * ```bash
19
+ * pipeline-manager infra redrive-events --region us-east-1
20
+ * pipeline-manager infra redrive-events --region us-east-1 --profile prod
21
+ * ```
22
+ */
23
+ export declare function redriveEvents(program: Command): void;
24
+ //# sourceMappingURL=redrive-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redrive-events.d.ts","sourceRoot":"","sources":["../../src/commands/redrive-events.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8GpD"}
@@ -0,0 +1,127 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { CloudFormationClient, DescribeStacksCommand } from '@aws-sdk/client-cloudformation';
4
+ import { SQSClient, GetQueueAttributesCommand, ListMessageMoveTasksCommand, StartMessageMoveTaskCommand, } from '@aws-sdk/client-sqs';
5
+ import { Command } from 'commander';
6
+ import { EVENTS_STACK_NAME } from '../config/cli.constants.js';
7
+ import { applyAwsProfile, resolveAwsRegion } from '../utils/aws-env.js';
8
+ import { printCommandHeader, withProfileOption, withRegionOption } from '../utils/command-utils.js';
9
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
10
+ import { printError, printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
11
+ // CFN stack that setup-events deploys — the queues live here.
12
+ const STACK_NAME = EVENTS_STACK_NAME;
13
+ /**
14
+ * Registers the `redrive-events` command with the CLI program.
15
+ *
16
+ * Manual fallback for the events Lambda's self-healing redrive (Phase 3): calls
17
+ * SQS `StartMessageMoveTask(DLQ → main queue)` for the `pipeline-builder-events`
18
+ * stack, moving messages that exhausted their receive count in the dead-letter
19
+ * queue back onto `pipeline-builder-events` so the ingestion Lambda re-processes
20
+ * them. Idempotent ingest (dedupe on `idempotencyKey`) prevents double-counting.
21
+ *
22
+ * The Lambda already does this automatically after a successful batch; this
23
+ * command is the operator escape hatch when the Lambda is down or the DLQ needs
24
+ * to be drained on demand. Like the Lambda, it refuses to start a second move
25
+ * task while one is already active (SQS allows only one in-flight task per
26
+ * source queue anyway).
27
+ *
28
+ * @example
29
+ * ```bash
30
+ * pipeline-manager infra redrive-events --region us-east-1
31
+ * pipeline-manager infra redrive-events --region us-east-1 --profile prod
32
+ * ```
33
+ */
34
+ export function redriveEvents(program) {
35
+ withProfileOption(withRegionOption(program
36
+ .command('redrive-events')
37
+ .description('Redrive dead-lettered CodePipeline events back onto the ingestion queue (manual fallback for the Lambda self-healing redrive)')))
38
+ .action(async (options) => {
39
+ const executionId = printCommandHeader('Redrive Events');
40
+ try {
41
+ const region = resolveAwsRegion(options.region);
42
+ // Honor --profile for the SDK clients below (mirrors setup-events) — without
43
+ // this the SDK hits the DEFAULT account while any accompanying CLI call
44
+ // honored --profile (silent split-brain).
45
+ applyAwsProfile(options.profile);
46
+ printInfo('Parameters', { stack: STACK_NAME, region });
47
+ // Step 1: resolve the queue URLs from the stack outputs (source of truth —
48
+ // no hardcoded queue names). setup-events must have run first.
49
+ printSection('Resolve Queues');
50
+ const cfnClient = new CloudFormationClient({ region });
51
+ const describeResult = await cfnClient.send(new DescribeStacksCommand({ StackName: STACK_NAME }));
52
+ const outputs = describeResult.Stacks?.[0]?.Outputs ?? [];
53
+ const outputMap = Object.fromEntries(outputs.map(o => [o.OutputKey ?? '', o.OutputValue ?? '']));
54
+ const eventQueueArn = outputMap.EventQueueArn;
55
+ const eventQueueUrl = outputMap.EventQueueUrl;
56
+ const dlqUrl = outputMap.DeadLetterQueueUrl;
57
+ if (!eventQueueArn || !dlqUrl) {
58
+ printError(`Stack ${STACK_NAME} is missing expected outputs`, {
59
+ hint: 'Run `pipeline-manager infra setup-events` first.',
60
+ });
61
+ throw new Error('Stack outputs EventQueueArn / DeadLetterQueueUrl not found');
62
+ }
63
+ const sqs = new SQSClient({ region });
64
+ // The stack exposes the DLQ URL but not its ARN — StartMessageMoveTask needs
65
+ // the source ARN, so resolve it from the queue's attributes.
66
+ const dlqAttrs = await sqs.send(new GetQueueAttributesCommand({
67
+ QueueUrl: dlqUrl,
68
+ AttributeNames: ['QueueArn', 'ApproximateNumberOfMessages'],
69
+ }));
70
+ const dlqArn = dlqAttrs.Attributes?.QueueArn;
71
+ const dlqDepth = Number(dlqAttrs.Attributes?.ApproximateNumberOfMessages ?? '0');
72
+ if (!dlqArn) {
73
+ throw new Error(`Could not resolve the DLQ ARN from ${dlqUrl}`);
74
+ }
75
+ printKeyValue({
76
+ 'Source (DLQ)': dlqArn,
77
+ 'Destination (queue)': eventQueueArn,
78
+ 'DLQ depth (approx)': String(dlqDepth),
79
+ });
80
+ // Nothing to move — bail early so the operator gets a clear signal instead
81
+ // of a no-op task.
82
+ if (dlqDepth === 0) {
83
+ printSuccess('Dead-letter queue is empty — nothing to redrive.');
84
+ return;
85
+ }
86
+ // Step 2: refuse to stack move tasks. SQS permits only one in-flight move
87
+ // task per source queue; surface any active one instead of erroring out.
88
+ printSection('Redrive');
89
+ const active = await sqs.send(new ListMessageMoveTasksCommand({ SourceArn: dlqArn }));
90
+ const running = (active.Results ?? []).find(t => t.Status === 'RUNNING');
91
+ if (running) {
92
+ printWarning('A message move task is already running for this DLQ — not starting another.', {
93
+ taskHandle: running.TaskHandle,
94
+ approxMovedSoFar: running.ApproximateNumberOfMessagesMoved,
95
+ });
96
+ return;
97
+ }
98
+ // Step 3: start the move (DLQ → main queue). DestinationArn is set explicitly
99
+ // even though SQS would default to the original source queue — the main
100
+ // ingestion queue is exactly that target.
101
+ const start = await sqs.send(new StartMessageMoveTaskCommand({
102
+ SourceArn: dlqArn,
103
+ DestinationArn: eventQueueArn,
104
+ }));
105
+ console.log('');
106
+ printSection('Redrive Started');
107
+ printKeyValue({
108
+ 'Task Handle': start.TaskHandle ?? '(none returned)',
109
+ 'Source (DLQ)': dlqArn,
110
+ 'Destination (queue)': eventQueueUrl || eventQueueArn,
111
+ 'Messages queued': String(dlqDepth),
112
+ 'Status': '✓ Started',
113
+ });
114
+ console.log('');
115
+ printSuccess('Redrive task started. Messages will re-flow through the ingestion Lambda.');
116
+ printInfo('Idempotent ingest dedupes on idempotencyKey, so re-driven events are not double-counted.');
117
+ }
118
+ catch (error) {
119
+ handleError(error, ERROR_CODES.API_REQUEST, {
120
+ debug: program.opts().debug,
121
+ exit: true,
122
+ context: { command: 'redrive-events', executionId, stack: STACK_NAME },
123
+ });
124
+ }
125
+ });
126
+ }
127
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkcml2ZS1ldmVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvcmVkcml2ZS1ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RixPQUFPLEVBQ0wsU0FBUyxFQUNULHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0IsMkJBQTJCLEdBQzVCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDeEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDcEcsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUUxSCw4REFBOEQ7QUFDOUQsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7QUFFckM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUFnQjtJQUM1QyxpQkFBaUIsQ0FDZixnQkFBZ0IsQ0FBQyxPQUFPO1NBQ3JCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztTQUN6QixXQUFXLENBQUMsK0hBQStILENBQUMsQ0FBQyxDQUNqSjtTQUNFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7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QywwRkFBMEYsQ0FBQyxDQUFDO1FBRXhHLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsV0FBVyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFO2dCQUMxQyxLQUFLLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUs7Z0JBQzNCLElBQUksRUFBRSxJQUFJO2dCQUNWLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRTthQUN2RSxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IENsb3VkRm9ybWF0aW9uQ2xpZW50LCBEZXNjcmliZVN0YWNrc0NvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0IHtcbiAgU1FTQ2xpZW50LFxuICBHZXRRdWV1ZUF0dHJpYnV0ZXNDb21tYW5kLFxuICBMaXN0TWVzc2FnZU1vdmVUYXNrc0NvbW1hbmQsXG4gIFN0YXJ0TWVzc2FnZU1vdmVUYXNrQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXNxcyc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IEVWRU5UU19TVEFDS19OQU1FIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXBwbHlBd3NQcm9maWxlLCByZXNvbHZlQXdzUmVnaW9uIH0gZnJvbSAnLi4vdXRpbHMvYXdzLWVudi5qcyc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyBFUlJPUl9DT0RFUywgaGFuZGxlRXJyb3IgfSBmcm9tICcuLi91dGlscy9lcnJvci1oYW5kbGVyLmpzJztcbmltcG9ydCB7IHByaW50RXJyb3IsIHByaW50SW5mbywgcHJpbnRLZXlWYWx1ZSwgcHJpbnRTZWN0aW9uLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbi8vIENGTiBzdGFjayB0aGF0IHNldHVwLWV2ZW50cyBkZXBsb3lzIOKAlCB0aGUgcXVldWVzIGxpdmUgaGVyZS5cbmNvbnN0IFNUQUNLX05BTUUgPSBFVkVOVFNfU1RBQ0tfTkFNRTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGByZWRyaXZlLWV2ZW50c2AgY29tbWFuZCB3aXRoIHRoZSBDTEkgcHJvZ3JhbS5cbiAqXG4gKiBNYW51YWwgZmFsbGJhY2sgZm9yIHRoZSBldmVudHMgTGFtYmRhJ3Mgc2VsZi1oZWFsaW5nIHJlZHJpdmUgKFBoYXNlIDMpOiBjYWxsc1xuICogU1FTIGBTdGFydE1lc3NhZ2VNb3ZlVGFzayhETFEg4oaSIG1haW4gcXVldWUpYCBmb3IgdGhlIGBwaXBlbGluZS1idWlsZGVyLWV2ZW50c2BcbiAqIHN0YWNrLCBtb3ZpbmcgbWVzc2FnZXMgdGhhdCBleGhhdXN0ZWQgdGhlaXIgcmVjZWl2ZSBjb3VudCBpbiB0aGUgZGVhZC1sZXR0ZXJcbiAqIHF1ZXVlIGJhY2sgb250byBgcGlwZWxpbmUtYnVpbGRlci1ldmVudHNgIHNvIHRoZSBpbmdlc3Rpb24gTGFtYmRhIHJlLXByb2Nlc3Nlc1xuICogdGhlbS4gSWRlbXBvdGVudCBpbmdlc3QgKGRlZHVwZSBvbiBgaWRlbXBvdGVuY3lLZXlgKSBwcmV2ZW50cyBkb3VibGUtY291bnRpbmcuXG4gKlxuICogVGhlIExhbWJkYSBhbHJlYWR5IGRvZXMgdGhpcyBhdXRvbWF0aWNhbGx5IGFmdGVyIGEgc3VjY2Vzc2Z1bCBiYXRjaDsgdGhpc1xuICogY29tbWFuZCBpcyB0aGUgb3BlcmF0b3IgZXNjYXBlIGhhdGNoIHdoZW4gdGhlIExhbWJkYSBpcyBkb3duIG9yIHRoZSBETFEgbmVlZHNcbiAqIHRvIGJlIGRyYWluZWQgb24gZGVtYW5kLiBMaWtlIHRoZSBMYW1iZGEsIGl0IHJlZnVzZXMgdG8gc3RhcnQgYSBzZWNvbmQgbW92ZVxuICogdGFzayB3aGlsZSBvbmUgaXMgYWxyZWFkeSBhY3RpdmUgKFNRUyBhbGxvd3Mgb25seSBvbmUgaW4tZmxpZ2h0IHRhc2sgcGVyXG4gKiBzb3VyY2UgcXVldWUgYW55d2F5KS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgYmFzaFxuICogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSByZWRyaXZlLWV2ZW50cyAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgcmVkcml2ZS1ldmVudHMgLS1yZWdpb24gdXMtZWFzdC0xIC0tcHJvZmlsZSBwcm9kXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZHJpdmVFdmVudHMocHJvZ3JhbTogQ29tbWFuZCk6IHZvaWQge1xuICB3aXRoUHJvZmlsZU9wdGlvbihcbiAgICB3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAgIC5jb21tYW5kKCdyZWRyaXZlLWV2ZW50cycpXG4gICAgICAuZGVzY3JpcHRpb24oJ1JlZHJpdmUgZGVhZC1sZXR0ZXJlZCBDb2RlUGlwZWxpbmUgZXZlbnRzIGJhY2sgb250byB0aGUgaW5nZXN0aW9uIHF1ZXVlIChtYW51YWwgZmFsbGJhY2sgZm9yIHRoZSBMYW1iZGEgc2VsZi1oZWFsaW5nIHJlZHJpdmUpJykpLFxuICApXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ1JlZHJpdmUgRXZlbnRzJyk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlZ2lvbiA9IHJlc29sdmVBd3NSZWdpb24ob3B0aW9ucy5yZWdpb24pO1xuICAgICAgICAvLyBIb25vciAtLXByb2ZpbGUgZm9yIHRoZSBTREsgY2xpZW50cyBiZWxvdyAobWlycm9ycyBzZXR1cC1ldmVudHMpIOKAlCB3aXRob3V0XG4gICAgICAgIC8vIHRoaXMgdGhlIFNESyBoaXRzIHRoZSBERUZBVUxUIGFjY291bnQgd2hpbGUgYW55IGFjY29tcGFueWluZyBDTEkgY2FsbFxuICAgICAgICAvLyBob25vcmVkIC0tcHJvZmlsZSAoc2lsZW50IHNwbGl0LWJyYWluKS5cbiAgICAgICAgYXBwbHlBd3NQcm9maWxlKG9wdGlvbnMucHJvZmlsZSk7XG5cbiAgICAgICAgcHJpbnRJbmZvKCdQYXJhbWV0ZXJzJywgeyBzdGFjazogU1RBQ0tfTkFNRSwgcmVnaW9uIH0pO1xuXG4gICAgICAgIC8vIFN0ZXAgMTogcmVzb2x2ZSB0aGUgcXVldWUgVVJMcyBmcm9tIHRoZSBzdGFjayBvdXRwdXRzIChzb3VyY2Ugb2YgdHJ1dGgg4oCUXG4gICAgICAgIC8vIG5vIGhhcmRjb2RlZCBxdWV1ZSBuYW1lcykuIHNldHVwLWV2ZW50cyBtdXN0IGhhdmUgcnVuIGZpcnN0LlxuICAgICAgICBwcmludFNlY3Rpb24oJ1Jlc29sdmUgUXVldWVzJyk7XG5cbiAgICAgICAgY29uc3QgY2ZuQ2xpZW50ID0gbmV3IENsb3VkRm9ybWF0aW9uQ2xpZW50KHsgcmVnaW9uIH0pO1xuICAgICAgICBjb25zdCBkZXNjcmliZVJlc3VsdCA9IGF3YWl0IGNmbkNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVN0YWNrc0NvbW1hbmQoeyBTdGFja05hbWU6IFNUQUNLX05BTUUgfSkpO1xuICAgICAgICBjb25zdCBvdXRwdXRzID0gZGVzY3JpYmVSZXN1bHQuU3RhY2tzPy5bMF0/Lk91dHB1dHMgPz8gW107XG4gICAgICAgIGNvbnN0IG91dHB1dE1hcCA9IE9iamVjdC5mcm9tRW50cmllcyhvdXRwdXRzLm1hcChvID0+IFtvLk91dHB1dEtleSA/PyAnJywgby5PdXRwdXRWYWx1ZSA/PyAnJ10pKTtcblxuICAgICAgICBjb25zdCBldmVudFF1ZXVlQXJuID0gb3V0cHV0TWFwLkV2ZW50UXVldWVBcm47XG4gICAgICAgIGNvbnN0IGV2ZW50UXVldWVVcmwgPSBvdXRwdXRNYXAuRXZlbnRRdWV1ZVVybDtcbiAgICAgICAgY29uc3QgZGxxVXJsID0gb3V0cHV0TWFwLkRlYWRMZXR0ZXJRdWV1ZVVybDtcblxuICAgICAgICBpZiAoIWV2ZW50UXVldWVBcm4gfHwgIWRscVVybCkge1xuICAgICAgICAgIHByaW50RXJyb3IoYFN0YWNrICR7U1RBQ0tfTkFNRX0gaXMgbWlzc2luZyBleHBlY3RlZCBvdXRwdXRzYCwge1xuICAgICAgICAgICAgaGludDogJ1J1biBgcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzZXR1cC1ldmVudHNgIGZpcnN0LicsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTdGFjayBvdXRwdXRzIEV2ZW50UXVldWVBcm4gLyBEZWFkTGV0dGVyUXVldWVVcmwgbm90IGZvdW5kJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzcXMgPSBuZXcgU1FTQ2xpZW50KHsgcmVnaW9uIH0pO1xuXG4gICAgICAgIC8vIFRoZSBzdGFjayBleHBvc2VzIHRoZSBETFEgVVJMIGJ1dCBub3QgaXRzIEFSTiDigJQgU3RhcnRNZXNzYWdlTW92ZVRhc2sgbmVlZHNcbiAgICAgICAgLy8gdGhlIHNvdXJjZSBBUk4sIHNvIHJlc29sdmUgaXQgZnJvbSB0aGUgcXVldWUncyBhdHRyaWJ1dGVzLlxuICAgICAgICBjb25zdCBkbHFBdHRycyA9IGF3YWl0IHNxcy5zZW5kKG5ldyBHZXRRdWV1ZUF0dHJpYnV0ZXNDb21tYW5kKHtcbiAgICAgICAgICBRdWV1ZVVybDogZGxxVXJsLFxuICAgICAgICAgIEF0dHJpYnV0ZU5hbWVzOiBbJ1F1ZXVlQXJuJywgJ0FwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlcyddLFxuICAgICAgICB9KSk7XG4gICAgICAgIGNvbnN0IGRscUFybiA9IGRscUF0dHJzLkF0dHJpYnV0ZXM/LlF1ZXVlQXJuO1xuICAgICAgICBjb25zdCBkbHFEZXB0aCA9IE51bWJlcihkbHFBdHRycy5BdHRyaWJ1dGVzPy5BcHByb3hpbWF0ZU51bWJlck9mTWVzc2FnZXMgPz8gJzAnKTtcblxuICAgICAgICBpZiAoIWRscUFybikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHJlc29sdmUgdGhlIERMUSBBUk4gZnJvbSAke2RscVVybH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdTb3VyY2UgKERMUSknOiBkbHFBcm4sXG4gICAgICAgICAgJ0Rlc3RpbmF0aW9uIChxdWV1ZSknOiBldmVudFF1ZXVlQXJuLFxuICAgICAgICAgICdETFEgZGVwdGggKGFwcHJveCknOiBTdHJpbmcoZGxxRGVwdGgpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBOb3RoaW5nIHRvIG1vdmUg4oCUIGJhaWwgZWFybHkgc28gdGhlIG9wZXJhdG9yIGdldHMgYSBjbGVhciBzaWduYWwgaW5zdGVhZFxuICAgICAgICAvLyBvZiBhIG5vLW9wIHRhc2suXG4gICAgICAgIGlmIChkbHFEZXB0aCA9PT0gMCkge1xuICAgICAgICAgIHByaW50U3VjY2VzcygnRGVhZC1sZXR0ZXIgcXVldWUgaXMgZW1wdHkg4oCUIG5vdGhpbmcgdG8gcmVkcml2ZS4nKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdGVwIDI6IHJlZnVzZSB0byBzdGFjayBtb3ZlIHRhc2tzLiBTUVMgcGVybWl0cyBvbmx5IG9uZSBpbi1mbGlnaHQgbW92ZVxuICAgICAgICAvLyB0YXNrIHBlciBzb3VyY2UgcXVldWU7IHN1cmZhY2UgYW55IGFjdGl2ZSBvbmUgaW5zdGVhZCBvZiBlcnJvcmluZyBvdXQuXG4gICAgICAgIHByaW50U2VjdGlvbignUmVkcml2ZScpO1xuXG4gICAgICAgIGNvbnN0IGFjdGl2ZSA9IGF3YWl0IHNxcy5zZW5kKG5ldyBMaXN0TWVzc2FnZU1vdmVUYXNrc0NvbW1hbmQoeyBTb3VyY2VBcm46IGRscUFybiB9KSk7XG4gICAgICAgIGNvbnN0IHJ1bm5pbmcgPSAoYWN0aXZlLlJlc3VsdHMgPz8gW10pLmZpbmQodCA9PiB0LlN0YXR1cyA9PT0gJ1JVTk5JTkcnKTtcbiAgICAgICAgaWYgKHJ1bm5pbmcpIHtcbiAgICAgICAgICBwcmludFdhcm5pbmcoJ0EgbWVzc2FnZSBtb3ZlIHRhc2sgaXMgYWxyZWFkeSBydW5uaW5nIGZvciB0aGlzIERMUSDigJQgbm90IHN0YXJ0aW5nIGFub3RoZXIuJywge1xuICAgICAgICAgICAgdGFza0hhbmRsZTogcnVubmluZy5UYXNrSGFuZGxlLFxuICAgICAgICAgICAgYXBwcm94TW92ZWRTb0ZhcjogcnVubmluZy5BcHByb3hpbWF0ZU51bWJlck9mTWVzc2FnZXNNb3ZlZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdGVwIDM6IHN0YXJ0IHRoZSBtb3ZlIChETFEg4oaSIG1haW4gcXVldWUpLiBEZXN0aW5hdGlvbkFybiBpcyBzZXQgZXhwbGljaXRseVxuICAgICAgICAvLyBldmVuIHRob3VnaCBTUVMgd291bGQgZGVmYXVsdCB0byB0aGUgb3JpZ2luYWwgc291cmNlIHF1ZXVlIOKAlCB0aGUgbWFpblxuICAgICAgICAvLyBpbmdlc3Rpb24gcXVldWUgaXMgZXhhY3RseSB0aGF0IHRhcmdldC5cbiAgICAgICAgY29uc3Qgc3RhcnQgPSBhd2FpdCBzcXMuc2VuZChuZXcgU3RhcnRNZXNzYWdlTW92ZVRhc2tDb21tYW5kKHtcbiAgICAgICAgICBTb3VyY2VBcm46IGRscUFybixcbiAgICAgICAgICBEZXN0aW5hdGlvbkFybjogZXZlbnRRdWV1ZUFybixcbiAgICAgICAgfSkpO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgcHJpbnRTZWN0aW9uKCdSZWRyaXZlIFN0YXJ0ZWQnKTtcbiAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgJ1Rhc2sgSGFuZGxlJzogc3RhcnQuVGFza0hhbmRsZSA/PyAnKG5vbmUgcmV0dXJuZWQpJyxcbiAgICAgICAgICAnU291cmNlIChETFEpJzogZGxxQXJuLFxuICAgICAgICAgICdEZXN0aW5hdGlvbiAocXVldWUpJzogZXZlbnRRdWV1ZVVybCB8fCBldmVudFF1ZXVlQXJuLFxuICAgICAgICAgICdNZXNzYWdlcyBxdWV1ZWQnOiBTdHJpbmcoZGxxRGVwdGgpLFxuICAgICAgICAgICdTdGF0dXMnOiAn4pyTIFN0YXJ0ZWQnLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U3VjY2VzcygnUmVkcml2ZSB0YXNrIHN0YXJ0ZWQuIE1lc3NhZ2VzIHdpbGwgcmUtZmxvdyB0aHJvdWdoIHRoZSBpbmdlc3Rpb24gTGFtYmRhLicpO1xuICAgICAgICBwcmludEluZm8oJ0lkZW1wb3RlbnQgaW5nZXN0IGRlZHVwZXMgb24gaWRlbXBvdGVuY3lLZXksIHNvIHJlLWRyaXZlbiBldmVudHMgYXJlIG5vdCBkb3VibGUtY291bnRlZC4nKTtcblxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkFQSV9SRVFVRVNULCB7XG4gICAgICAgICAgZGVidWc6IHByb2dyYW0ub3B0cygpLmRlYnVnLFxuICAgICAgICAgIGV4aXQ6IHRydWUsXG4gICAgICAgICAgY29udGV4dDogeyBjb21tYW5kOiAncmVkcml2ZS1ldmVudHMnLCBleGVjdXRpb25JZCwgc3RhY2s6IFNUQUNLX05BTUUgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG59XG4iXX0=
@@ -0,0 +1,38 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `register` command with the CLI program.
4
+ *
5
+ * Two purposes — both targeted at recovering from a deploy whose registration
6
+ * step didn't land:
7
+ *
8
+ * 1. Explicit re-register (`--id <pipelineId>`) — recomputes the ARN from
9
+ * STS + region and POSTs it to the platform. Useful when the platform
10
+ * was unreachable during `deploy`, when the registry row was deleted by
11
+ * mistake, or for any other reason a deployed stack has no registry row.
12
+ *
13
+ * 2. Drain pending intents (every invocation) — `deploy` writes a local
14
+ * file under `~/.pipeline-manager/pending-registrations/` whenever its
15
+ * registration POST fails. Each `register` invocation tries to drain
16
+ * every such file. On success the file is deleted; on failure it stays
17
+ * and surfaces as a warning.
18
+ *
19
+ * Flags:
20
+ * - `--id <pipelineId>` — re-register a specific pipeline by ID
21
+ * - `--region <region>` — AWS region (default: AWS_REGION env / us-east-1)
22
+ * - `--no-drain` — skip draining pending intents
23
+ *
24
+ * Exit codes:
25
+ * - 0: requested registration succeeded AND no pending intents remain
26
+ * - 1: at least one registration (explicit or pending) still failed
27
+ *
28
+ * @example
29
+ * ```bash
30
+ * # Retry a registration that failed during deploy
31
+ * pipeline-manager pipeline register --id pipe-123
32
+ *
33
+ * # Just drain pending intents from disk, no specific registration
34
+ * pipeline-manager pipeline register
35
+ * ```
36
+ */
37
+ export declare function register(program: Command): void;
38
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwG/C"}
@@ -0,0 +1,160 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import {} from '../types/index.js';
5
+ import { createAuthenticatedClient, printCommandHeader, printSslWarning, withRegionOption, withSslOptions } from '../utils/command-utils.js';
6
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
7
+ import { printError, printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
8
+ import { buildRegistryPayload, clearPendingIntent, readPendingIntents, writePendingIntent, } from '../utils/registry.js';
9
+ import { extractSingleResponse } from '../utils/response-utils.js';
10
+ /**
11
+ * Registers the `register` command with the CLI program.
12
+ *
13
+ * Two purposes — both targeted at recovering from a deploy whose registration
14
+ * step didn't land:
15
+ *
16
+ * 1. Explicit re-register (`--id <pipelineId>`) — recomputes the ARN from
17
+ * STS + region and POSTs it to the platform. Useful when the platform
18
+ * was unreachable during `deploy`, when the registry row was deleted by
19
+ * mistake, or for any other reason a deployed stack has no registry row.
20
+ *
21
+ * 2. Drain pending intents (every invocation) — `deploy` writes a local
22
+ * file under `~/.pipeline-manager/pending-registrations/` whenever its
23
+ * registration POST fails. Each `register` invocation tries to drain
24
+ * every such file. On success the file is deleted; on failure it stays
25
+ * and surfaces as a warning.
26
+ *
27
+ * Flags:
28
+ * - `--id <pipelineId>` — re-register a specific pipeline by ID
29
+ * - `--region <region>` — AWS region (default: AWS_REGION env / us-east-1)
30
+ * - `--no-drain` — skip draining pending intents
31
+ *
32
+ * Exit codes:
33
+ * - 0: requested registration succeeded AND no pending intents remain
34
+ * - 1: at least one registration (explicit or pending) still failed
35
+ *
36
+ * @example
37
+ * ```bash
38
+ * # Retry a registration that failed during deploy
39
+ * pipeline-manager pipeline register --id pipe-123
40
+ *
41
+ * # Just drain pending intents from disk, no specific registration
42
+ * pipeline-manager pipeline register
43
+ * ```
44
+ */
45
+ export function register(program) {
46
+ withSslOptions(withRegionOption(program
47
+ .command('register')
48
+ .description('Register a deployed pipeline ARN with the platform (retry path for failed registrations)')
49
+ .option('-i, --id <id>', 'Pipeline ID to register (re-derives ARN from STS)'))
50
+ .option('--no-drain', 'Skip draining pending intents from prior failed deploys'))
51
+ .action(async (options) => {
52
+ const executionId = printCommandHeader('Register Pipeline');
53
+ printSslWarning(options.verifySsl);
54
+ let anyFailed = false;
55
+ let registeredCount = 0;
56
+ try {
57
+ const client = createAuthenticatedClient(options);
58
+ const pipelineUrl = client.getConfig().api.pipelineUrl;
59
+ // ── Drain pending intents first ──
60
+ // We drain before the explicit registration so a queued failure for
61
+ // the same pipelineId is replaced (not double-applied) by the fresh
62
+ // payload below.
63
+ const drained = new Set();
64
+ if (options.drain !== false) {
65
+ const intents = await readPendingIntents();
66
+ if (intents.length > 0) {
67
+ printSection('Draining pending intents');
68
+ printInfo('Found pending registrations from prior failed deploys', {
69
+ count: String(intents.length),
70
+ });
71
+ for (const intent of intents) {
72
+ // Skip the explicit pipeline — we'll re-build a fresh payload below.
73
+ if (options.id && intent.pipelineId === options.id)
74
+ continue;
75
+ const ok = await postRegistration(client, pipelineUrl, intent, intent.pipelineId);
76
+ if (ok) {
77
+ await clearPendingIntent(intent.pipelineId);
78
+ drained.add(intent.pipelineId);
79
+ registeredCount++;
80
+ }
81
+ else {
82
+ anyFailed = true;
83
+ }
84
+ }
85
+ }
86
+ }
87
+ // ── Explicit registration ──
88
+ if (options.id) {
89
+ printSection('Re-registering pipeline');
90
+ const pipelineRes = await client.get(`${pipelineUrl}/${options.id}`);
91
+ const pipeline = extractSingleResponse(pipelineRes, 'pipeline', 'id');
92
+ if (!pipeline) {
93
+ printError('Pipeline not found in platform');
94
+ throw new Error(`No pipeline returned for id ${options.id}`);
95
+ }
96
+ if (!pipeline.orgId) {
97
+ printError('Pipeline has no orgId — cannot register');
98
+ throw new Error(`Pipeline ${pipeline.id} is missing orgId`);
99
+ }
100
+ const payload = await buildRegistryPayload({
101
+ id: pipeline.id,
102
+ orgId: pipeline.orgId,
103
+ pipelineName: pipeline.pipelineName,
104
+ project: pipeline.project,
105
+ organization: pipeline.organization,
106
+ }, options.region);
107
+ // Clear any stale intent for this pipelineId before retrying so we
108
+ // don't leave a duplicate file behind on success.
109
+ await clearPendingIntent(payload.pipelineId);
110
+ const ok = await postRegistration(client, pipelineUrl, payload, payload.pipelineId);
111
+ if (ok) {
112
+ registeredCount++;
113
+ printSuccess('Pipeline registered for event reporting', {
114
+ pipelineId: payload.pipelineId,
115
+ });
116
+ }
117
+ else {
118
+ anyFailed = true;
119
+ const path = await writePendingIntent(payload);
120
+ printWarning('Registration failed; intent saved for retry', { intent: path });
121
+ }
122
+ }
123
+ printSection('Summary');
124
+ printKeyValue({
125
+ 'Registered': String(registeredCount),
126
+ 'Drained from queue': String(drained.size),
127
+ 'Status': anyFailed ? 'Some registrations still pending' : 'All clear',
128
+ 'Execution ID': executionId,
129
+ });
130
+ process.exit(anyFailed ? 1 : 0);
131
+ }
132
+ catch (error) {
133
+ handleError(error, ERROR_CODES.API_REQUEST, {
134
+ debug: program.opts().debug,
135
+ exit: false,
136
+ context: { command: 'register', executionId, pipelineId: options.id },
137
+ });
138
+ process.exit(1);
139
+ }
140
+ });
141
+ }
142
+ /**
143
+ * POST a registration payload to the platform. On failure, the caller decides
144
+ * whether to write/preserve a pending intent — this helper just reports.
145
+ */
146
+ async function postRegistration(client, pipelineUrl, payload, pipelineId) {
147
+ try {
148
+ await client.post(`${pipelineUrl}/registry`, payload);
149
+ printInfo('Registered', { pipelineId });
150
+ return true;
151
+ }
152
+ catch (err) {
153
+ printWarning('Registration failed', {
154
+ pipelineId,
155
+ error: err instanceof Error ? err.message : String(err),
156
+ });
157
+ return false;
158
+ }
159
+ }
160
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvcmVnaXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBd0MsTUFBTSxtQkFBbUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdJLE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckUsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDMUgsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLGtCQUFrQixHQUVuQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRW5FOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0NHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxPQUFnQjtJQUN2QyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsT0FBTztTQUNwQyxPQUFPLENBQUMsVUFBVSxDQUFDO1NBQ25CLFdBQVcsQ0FBQywwRkFBMEYsQ0FBQztTQUN2RyxNQUFNLENBQUMsZUFBZSxFQUFFLG1EQUFtRCxDQUFDLENBQUM7U0FDN0UsTUFBTSxDQUFDLFlBQVksRUFBRSx5REFBeUQsQ0FBQyxDQUFDO1NBQ2hGLE1BQU0sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDeEIsTUFBTSxXQUFXLEdBQUcsa0JBQWtC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QUssRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFO2dCQUMxQyxLQUFLLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUs7Z0JBQzNCLElBQUksRUFBRSxLQUFLO2dCQUNYLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFO2FBQ3RFLENBQUMsQ0FBQztZQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxnQkFBZ0IsQ0FDN0IsTUFBb0QsRUFDcEQsV0FBbUIsRUFDbkIsT0FBd0IsRUFDeEIsVUFBa0I7SUFFbEIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsV0FBVyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDdEQsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDeEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLFlBQVksQ0FBQyxxQkFBcUIsRUFBRTtZQUNsQyxVQUFVO1lBQ1YsS0FBSyxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7U0FDeEQsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IHR5cGUgUGlwZWxpbmUsIHR5cGUgUGlwZWxpbmVSZXNwb25zZSB9IGZyb20gJy4uL3R5cGVzL2luZGV4LmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnQsIHByaW50Q29tbWFuZEhlYWRlciwgcHJpbnRTc2xXYXJuaW5nLCB3aXRoUmVnaW9uT3B0aW9uLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgRVJST1JfQ09ERVMsIGhhbmRsZUVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBwcmludEVycm9yLCBwcmludEluZm8sIHByaW50S2V5VmFsdWUsIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzLCBwcmludFdhcm5pbmcgfSBmcm9tICcuLi91dGlscy9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHtcbiAgYnVpbGRSZWdpc3RyeVBheWxvYWQsXG4gIGNsZWFyUGVuZGluZ0ludGVudCxcbiAgcmVhZFBlbmRpbmdJbnRlbnRzLFxuICB3cml0ZVBlbmRpbmdJbnRlbnQsXG4gIHR5cGUgUmVnaXN0cnlQYXlsb2FkLFxufSBmcm9tICcuLi91dGlscy9yZWdpc3RyeS5qcyc7XG5pbXBvcnQgeyBleHRyYWN0U2luZ2xlUmVzcG9uc2UgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS11dGlscy5qcyc7XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgcmVnaXN0ZXJgIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogVHdvIHB1cnBvc2VzIOKAlCBib3RoIHRhcmdldGVkIGF0IHJlY292ZXJpbmcgZnJvbSBhIGRlcGxveSB3aG9zZSByZWdpc3RyYXRpb25cbiAqIHN0ZXAgZGlkbid0IGxhbmQ6XG4gKlxuICogICAxLiBFeHBsaWNpdCByZS1yZWdpc3RlciAoYC0taWQgPHBpcGVsaW5lSWQ+YCkg4oCUIHJlY29tcHV0ZXMgdGhlIEFSTiBmcm9tXG4gKiAgICAgIFNUUyArIHJlZ2lvbiBhbmQgUE9TVHMgaXQgdG8gdGhlIHBsYXRmb3JtLiBVc2VmdWwgd2hlbiB0aGUgcGxhdGZvcm1cbiAqICAgICAgd2FzIHVucmVhY2hhYmxlIGR1cmluZyBgZGVwbG95YCwgd2hlbiB0aGUgcmVnaXN0cnkgcm93IHdhcyBkZWxldGVkIGJ5XG4gKiAgICAgIG1pc3Rha2UsIG9yIGZvciBhbnkgb3RoZXIgcmVhc29uIGEgZGVwbG95ZWQgc3RhY2sgaGFzIG5vIHJlZ2lzdHJ5IHJvdy5cbiAqXG4gKiAgIDIuIERyYWluIHBlbmRpbmcgaW50ZW50cyAoZXZlcnkgaW52b2NhdGlvbikg4oCUIGBkZXBsb3lgIHdyaXRlcyBhIGxvY2FsXG4gKiAgICAgIGZpbGUgdW5kZXIgYH4vLnBpcGVsaW5lLW1hbmFnZXIvcGVuZGluZy1yZWdpc3RyYXRpb25zL2Agd2hlbmV2ZXIgaXRzXG4gKiAgICAgIHJlZ2lzdHJhdGlvbiBQT1NUIGZhaWxzLiBFYWNoIGByZWdpc3RlcmAgaW52b2NhdGlvbiB0cmllcyB0byBkcmFpblxuICogICAgICBldmVyeSBzdWNoIGZpbGUuIE9uIHN1Y2Nlc3MgdGhlIGZpbGUgaXMgZGVsZXRlZDsgb24gZmFpbHVyZSBpdCBzdGF5c1xuICogICAgICBhbmQgc3VyZmFjZXMgYXMgYSB3YXJuaW5nLlxuICpcbiAqIEZsYWdzOlxuICogICAtIGAtLWlkIDxwaXBlbGluZUlkPmAg4oCUIHJlLXJlZ2lzdGVyIGEgc3BlY2lmaWMgcGlwZWxpbmUgYnkgSURcbiAqICAgLSBgLS1yZWdpb24gPHJlZ2lvbj5gIOKAlCBBV1MgcmVnaW9uIChkZWZhdWx0OiBBV1NfUkVHSU9OIGVudiAvIHVzLWVhc3QtMSlcbiAqICAgLSBgLS1uby1kcmFpbmAg4oCUIHNraXAgZHJhaW5pbmcgcGVuZGluZyBpbnRlbnRzXG4gKlxuICogRXhpdCBjb2RlczpcbiAqICAgLSAwOiByZXF1ZXN0ZWQgcmVnaXN0cmF0aW9uIHN1Y2NlZWRlZCBBTkQgbm8gcGVuZGluZyBpbnRlbnRzIHJlbWFpblxuICogICAtIDE6IGF0IGxlYXN0IG9uZSByZWdpc3RyYXRpb24gKGV4cGxpY2l0IG9yIHBlbmRpbmcpIHN0aWxsIGZhaWxlZFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiAjIFJldHJ5IGEgcmVnaXN0cmF0aW9uIHRoYXQgZmFpbGVkIGR1cmluZyBkZXBsb3lcbiAqIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgcmVnaXN0ZXIgLS1pZCBwaXBlLTEyM1xuICpcbiAqICMgSnVzdCBkcmFpbiBwZW5kaW5nIGludGVudHMgZnJvbSBkaXNrLCBubyBzcGVjaWZpYyByZWdpc3RyYXRpb25cbiAqIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgcmVnaXN0ZXJcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXIocHJvZ3JhbTogQ29tbWFuZCk6IHZvaWQge1xuICB3aXRoU3NsT3B0aW9ucyh3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAuY29tbWFuZCgncmVnaXN0ZXInKVxuICAgIC5kZXNjcmlwdGlvbignUmVnaXN0ZXIgYSBkZXBsb3llZCBwaXBlbGluZSBBUk4gd2l0aCB0aGUgcGxhdGZvcm0gKHJldHJ5IHBhdGggZm9yIGZhaWxlZCByZWdpc3RyYXRpb25zKScpXG4gICAgLm9wdGlvbignLWksIC0taWQgPGlkPicsICdQaXBlbGluZSBJRCB0byByZWdpc3RlciAocmUtZGVyaXZlcyBBUk4gZnJvbSBTVFMpJykpXG4gICAgLm9wdGlvbignLS1uby1kcmFpbicsICdTa2lwIGRyYWluaW5nIHBlbmRpbmcgaW50ZW50cyBmcm9tIHByaW9yIGZhaWxlZCBkZXBsb3lzJykpXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ1JlZ2lzdGVyIFBpcGVsaW5lJyk7XG4gICAgICBwcmludFNzbFdhcm5pbmcob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICBsZXQgYW55RmFpbGVkID0gZmFsc2U7XG4gICAgICBsZXQgcmVnaXN0ZXJlZENvdW50ID0gMDtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gY3JlYXRlQXV0aGVudGljYXRlZENsaWVudChvcHRpb25zKTtcbiAgICAgICAgY29uc3QgcGlwZWxpbmVVcmwgPSBjbGllbnQuZ2V0Q29uZmlnKCkuYXBpLnBpcGVsaW5lVXJsO1xuXG4gICAgICAgIC8vIOKUgOKUgCBEcmFpbiBwZW5kaW5nIGludGVudHMgZmlyc3Qg4pSA4pSAXG4gICAgICAgIC8vIFdlIGRyYWluIGJlZm9yZSB0aGUgZXhwbGljaXQgcmVnaXN0cmF0aW9uIHNvIGEgcXVldWVkIGZhaWx1cmUgZm9yXG4gICAgICAgIC8vIHRoZSBzYW1lIHBpcGVsaW5lSWQgaXMgcmVwbGFjZWQgKG5vdCBkb3VibGUtYXBwbGllZCkgYnkgdGhlIGZyZXNoXG4gICAgICAgIC8vIHBheWxvYWQgYmVsb3cuXG4gICAgICAgIGNvbnN0IGRyYWluZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgaWYgKG9wdGlvbnMuZHJhaW4gIT09IGZhbHNlKSB7XG4gICAgICAgICAgY29uc3QgaW50ZW50cyA9IGF3YWl0IHJlYWRQZW5kaW5nSW50ZW50cygpO1xuICAgICAgICAgIGlmIChpbnRlbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHByaW50U2VjdGlvbignRHJhaW5pbmcgcGVuZGluZyBpbnRlbnRzJyk7XG4gICAgICAgICAgICBwcmludEluZm8oJ0ZvdW5kIHBlbmRpbmcgcmVnaXN0cmF0aW9ucyBmcm9tIHByaW9yIGZhaWxlZCBkZXBsb3lzJywge1xuICAgICAgICAgICAgICBjb3VudDogU3RyaW5nKGludGVudHMubGVuZ3RoKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZm9yIChjb25zdCBpbnRlbnQgb2YgaW50ZW50cykge1xuICAgICAgICAgICAgICAvLyBTa2lwIHRoZSBleHBsaWNpdCBwaXBlbGluZSDigJQgd2UnbGwgcmUtYnVpbGQgYSBmcmVzaCBwYXlsb2FkIGJlbG93LlxuICAgICAgICAgICAgICBpZiAob3B0aW9ucy5pZCAmJiBpbnRlbnQucGlwZWxpbmVJZCA9PT0gb3B0aW9ucy5pZCkgY29udGludWU7XG4gICAgICAgICAgICAgIGNvbnN0IG9rID0gYXdhaXQgcG9zdFJlZ2lzdHJhdGlvbihjbGllbnQsIHBpcGVsaW5lVXJsLCBpbnRlbnQsIGludGVudC5waXBlbGluZUlkKTtcbiAgICAgICAgICAgICAgaWYgKG9rKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2xlYXJQZW5kaW5nSW50ZW50KGludGVudC5waXBlbGluZUlkKTtcbiAgICAgICAgICAgICAgICBkcmFpbmVkLmFkZChpbnRlbnQucGlwZWxpbmVJZCk7XG4gICAgICAgICAgICAgICAgcmVnaXN0ZXJlZENvdW50Kys7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW55RmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOKUgOKUgCBFeHBsaWNpdCByZWdpc3RyYXRpb24g4pSA4pSAXG4gICAgICAgIGlmIChvcHRpb25zLmlkKSB7XG4gICAgICAgICAgcHJpbnRTZWN0aW9uKCdSZS1yZWdpc3RlcmluZyBwaXBlbGluZScpO1xuICAgICAgICAgIGNvbnN0IHBpcGVsaW5lUmVzID0gYXdhaXQgY2xpZW50LmdldDxQaXBlbGluZVJlc3BvbnNlPihgJHtwaXBlbGluZVVybH0vJHtvcHRpb25zLmlkfWApO1xuICAgICAgICAgIGNvbnN0IHBpcGVsaW5lID0gZXh0cmFjdFNpbmdsZVJlc3BvbnNlPFBpcGVsaW5lPihwaXBlbGluZVJlcywgJ3BpcGVsaW5lJywgJ2lkJyk7XG4gICAgICAgICAgaWYgKCFwaXBlbGluZSkge1xuICAgICAgICAgICAgcHJpbnRFcnJvcignUGlwZWxpbmUgbm90IGZvdW5kIGluIHBsYXRmb3JtJyk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHBpcGVsaW5lIHJldHVybmVkIGZvciBpZCAke29wdGlvbnMuaWR9YCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFwaXBlbGluZS5vcmdJZCkge1xuICAgICAgICAgICAgcHJpbnRFcnJvcignUGlwZWxpbmUgaGFzIG5vIG9yZ0lkIOKAlCBjYW5ub3QgcmVnaXN0ZXInKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUGlwZWxpbmUgJHtwaXBlbGluZS5pZH0gaXMgbWlzc2luZyBvcmdJZGApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBwYXlsb2FkID0gYXdhaXQgYnVpbGRSZWdpc3RyeVBheWxvYWQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBwaXBlbGluZS5pZCxcbiAgICAgICAgICAgICAgb3JnSWQ6IHBpcGVsaW5lLm9yZ0lkLFxuICAgICAgICAgICAgICBwaXBlbGluZU5hbWU6IHBpcGVsaW5lLnBpcGVsaW5lTmFtZSxcbiAgICAgICAgICAgICAgcHJvamVjdDogcGlwZWxpbmUucHJvamVjdCxcbiAgICAgICAgICAgICAgb3JnYW5pemF0aW9uOiBwaXBlbGluZS5vcmdhbml6YXRpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9ucy5yZWdpb24sXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIENsZWFyIGFueSBzdGFsZSBpbnRlbnQgZm9yIHRoaXMgcGlwZWxpbmVJZCBiZWZvcmUgcmV0cnlpbmcgc28gd2VcbiAgICAgICAgICAvLyBkb24ndCBsZWF2ZSBhIGR1cGxpY2F0ZSBmaWxlIGJlaGluZCBvbiBzdWNjZXNzLlxuICAgICAgICAgIGF3YWl0IGNsZWFyUGVuZGluZ0ludGVudChwYXlsb2FkLnBpcGVsaW5lSWQpO1xuXG4gICAgICAgICAgY29uc3Qgb2sgPSBhd2FpdCBwb3N0UmVnaXN0cmF0aW9uKGNsaWVudCwgcGlwZWxpbmVVcmwsIHBheWxvYWQsIHBheWxvYWQucGlwZWxpbmVJZCk7XG4gICAgICAgICAgaWYgKG9rKSB7XG4gICAgICAgICAgICByZWdpc3RlcmVkQ291bnQrKztcbiAgICAgICAgICAgIHByaW50U3VjY2VzcygnUGlwZWxpbmUgcmVnaXN0ZXJlZCBmb3IgZXZlbnQgcmVwb3J0aW5nJywge1xuICAgICAgICAgICAgICBwaXBlbGluZUlkOiBwYXlsb2FkLnBpcGVsaW5lSWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYW55RmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IHBhdGggPSBhd2FpdCB3cml0ZVBlbmRpbmdJbnRlbnQocGF5bG9hZCk7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoJ1JlZ2lzdHJhdGlvbiBmYWlsZWQ7IGludGVudCBzYXZlZCBmb3IgcmV0cnknLCB7IGludGVudDogcGF0aCB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwcmludFNlY3Rpb24oJ1N1bW1hcnknKTtcbiAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgJ1JlZ2lzdGVyZWQnOiBTdHJpbmcocmVnaXN0ZXJlZENvdW50KSxcbiAgICAgICAgICAnRHJhaW5lZCBmcm9tIHF1ZXVlJzogU3RyaW5nKGRyYWluZWQuc2l6ZSksXG4gICAgICAgICAgJ1N0YXR1cyc6IGFueUZhaWxlZCA/ICdTb21lIHJlZ2lzdHJhdGlvbnMgc3RpbGwgcGVuZGluZycgOiAnQWxsIGNsZWFyJyxcbiAgICAgICAgICAnRXhlY3V0aW9uIElEJzogZXhlY3V0aW9uSWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb2Nlc3MuZXhpdChhbnlGYWlsZWQgPyAxIDogMCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuQVBJX1JFUVVFU1QsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogeyBjb21tYW5kOiAncmVnaXN0ZXInLCBleGVjdXRpb25JZCwgcGlwZWxpbmVJZDogb3B0aW9ucy5pZCB9LFxuICAgICAgICB9KTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIFBPU1QgYSByZWdpc3RyYXRpb24gcGF5bG9hZCB0byB0aGUgcGxhdGZvcm0uIE9uIGZhaWx1cmUsIHRoZSBjYWxsZXIgZGVjaWRlc1xuICogd2hldGhlciB0byB3cml0ZS9wcmVzZXJ2ZSBhIHBlbmRpbmcgaW50ZW50IOKAlCB0aGlzIGhlbHBlciBqdXN0IHJlcG9ydHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHBvc3RSZWdpc3RyYXRpb24oXG4gIGNsaWVudDogUmV0dXJuVHlwZTx0eXBlb2YgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudD4sXG4gIHBpcGVsaW5lVXJsOiBzdHJpbmcsXG4gIHBheWxvYWQ6IFJlZ2lzdHJ5UGF5bG9hZCxcbiAgcGlwZWxpbmVJZDogc3RyaW5nLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgY2xpZW50LnBvc3QoYCR7cGlwZWxpbmVVcmx9L3JlZ2lzdHJ5YCwgcGF5bG9hZCk7XG4gICAgcHJpbnRJbmZvKCdSZWdpc3RlcmVkJywgeyBwaXBlbGluZUlkIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBwcmludFdhcm5pbmcoJ1JlZ2lzdHJhdGlvbiBmYWlsZWQnLCB7XG4gICAgICBwaXBlbGluZUlkLFxuICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICB9KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,15 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `setup-events` command with the CLI program.
4
+ *
5
+ * Deploys EventBridge → SQS → Lambda infrastructure for pipeline reporting.
6
+ *
7
+ * 1. Deploys CloudFormation stack (rule + queue + Lambda shell + IAM)
8
+ * 2. Downloads @pipeline-builder/pipeline-events from npm registry
9
+ * 3. Uploads handler code directly to Lambda (no S3 needed)
10
+ *
11
+ * Uses PLATFORM_BASE_URL from environment (same as all other commands).
12
+ * Idempotent — running again updates the stack and code.
13
+ */
14
+ export declare function setupEvents(program: Command): void;
15
+ //# sourceMappingURL=setup-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-events.d.ts","sourceRoot":"","sources":["../../src/commands/setup-events.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4JlD"}