@go-to-k/cdkd 0.31.0 → 0.31.2

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.
package/README.md CHANGED
@@ -414,6 +414,24 @@ per-resource timeout flags (`--resource-warn-after`,
414
414
  and the rationale for the 30m default), see
415
415
  **[docs/cli-reference.md](docs/cli-reference.md)**.
416
416
 
417
+ ## Exit codes
418
+
419
+ cdkd commands distinguish three outcomes via the process exit code so
420
+ CI / bench scripts can react without grepping log output:
421
+
422
+ | Exit | Meaning |
423
+ |------|---------|
424
+ | `0` | Success — command completed and no resources are in an error state |
425
+ | `1` | Command-level failure — auth error, bad arguments, synth crash, unhandled exception |
426
+ | `2` | **Partial failure** — work completed but one or more resources failed (state.json is preserved, re-running typically resolves it) |
427
+
428
+ Exit `2` is currently emitted by `cdkd destroy` and `cdkd state
429
+ destroy` when one or more per-resource deletes fail. The summary line
430
+ also switches from `✓ Stack X destroyed` to `⚠ Stack X partially
431
+ destroyed (...). State preserved — re-run 'cdkd destroy' / 'cdkd
432
+ state destroy' to clean up.` so the visual marker matches the exit
433
+ code.
434
+
417
435
  ## Example
418
436
 
419
437
  ```typescript
package/dist/cli.js CHANGED
@@ -1170,6 +1170,14 @@ var DependencyError = class _DependencyError extends CdkdError {
1170
1170
  Object.setPrototypeOf(this, _DependencyError.prototype);
1171
1171
  }
1172
1172
  };
1173
+ var PartialFailureError = class _PartialFailureError extends CdkdError {
1174
+ exitCode = 2;
1175
+ constructor(message, cause) {
1176
+ super(message, "PARTIAL_FAILURE", cause);
1177
+ this.name = "PartialFailureError";
1178
+ Object.setPrototypeOf(this, _PartialFailureError.prototype);
1179
+ }
1180
+ };
1173
1181
  function isCdkdError(error) {
1174
1182
  return error instanceof CdkdError;
1175
1183
  }
@@ -1193,7 +1201,8 @@ function handleError(error) {
1193
1201
  if (error instanceof Error && error.stack) {
1194
1202
  logger.debug("Stack trace:", error.stack);
1195
1203
  }
1196
- process.exit(1);
1204
+ const exitCode = error instanceof PartialFailureError ? error.exitCode : 1;
1205
+ process.exit(exitCode);
1197
1206
  }
1198
1207
  function withErrorHandling(fn) {
1199
1208
  return async (...args) => {
@@ -13027,6 +13036,11 @@ import {
13027
13036
  DeleteNetworkInterfaceCommand
13028
13037
  } from "@aws-sdk/client-ec2";
13029
13038
  init_aws_clients();
13039
+ function inlineCodeFileNameForRuntime(runtime) {
13040
+ if (runtime?.startsWith("python"))
13041
+ return "index.py";
13042
+ return "index.js";
13043
+ }
13030
13044
  var LambdaFunctionProvider = class {
13031
13045
  lambdaClient;
13032
13046
  ec2Client;
@@ -13129,7 +13143,7 @@ var LambdaFunctionProvider = class {
13129
13143
  const createParams = {
13130
13144
  FunctionName: functionName,
13131
13145
  Role: role,
13132
- Code: this.buildCode(code),
13146
+ Code: this.buildCode(code, properties["Runtime"]),
13133
13147
  Handler: properties["Handler"],
13134
13148
  Runtime: properties["Runtime"],
13135
13149
  Timeout: properties["Timeout"],
@@ -13215,7 +13229,7 @@ var LambdaFunctionProvider = class {
13215
13229
  const newCode = properties["Code"];
13216
13230
  const oldCode = previousProperties["Code"];
13217
13231
  if (newCode && JSON.stringify(newCode) !== JSON.stringify(oldCode)) {
13218
- const builtCode = this.buildCode(newCode);
13232
+ const builtCode = this.buildCode(newCode, properties["Runtime"]);
13219
13233
  const codeParams = {
13220
13234
  FunctionName: physicalId,
13221
13235
  S3Bucket: builtCode.S3Bucket,
@@ -13583,7 +13597,7 @@ var LambdaFunctionProvider = class {
13583
13597
  /**
13584
13598
  * Build Lambda Code parameter from CDK properties
13585
13599
  */
13586
- buildCode(code) {
13600
+ buildCode(code, runtime) {
13587
13601
  const result = {};
13588
13602
  if (code["S3Bucket"]) {
13589
13603
  result.S3Bucket = code["S3Bucket"];
@@ -13595,7 +13609,7 @@ var LambdaFunctionProvider = class {
13595
13609
  result.S3ObjectVersion = code["S3ObjectVersion"];
13596
13610
  }
13597
13611
  if (code["ZipFile"]) {
13598
- result.ZipFile = this.createZipFromInlineCode(code["ZipFile"]);
13612
+ result.ZipFile = this.createZipFromInlineCode(code["ZipFile"], runtime);
13599
13613
  }
13600
13614
  if (code["ImageUri"]) {
13601
13615
  result.ImageUri = code["ImageUri"];
@@ -13607,13 +13621,14 @@ var LambdaFunctionProvider = class {
13607
13621
  *
13608
13622
  * CloudFormation's ZipFile property automatically wraps inline code in a zip,
13609
13623
  * but the Lambda SDK expects actual zip binary. This creates a minimal zip
13610
- * containing the code as index.* (matching the Handler).
13624
+ * containing the code as index.* (extension derived from runtime — nodejs
13625
+ * runtimes use index.js, python runtimes use index.py; see CFn ZipFile docs).
13611
13626
  */
13612
- createZipFromInlineCode(code) {
13627
+ createZipFromInlineCode(code, runtime) {
13613
13628
  const fileData = Buffer.from(code, "utf-8");
13614
13629
  const crc32 = this.crc32(fileData);
13615
13630
  const compressedData = zlib.deflateRawSync(fileData);
13616
- const fileName = Buffer.from("index.py");
13631
+ const fileName = Buffer.from(inlineCodeFileNameForRuntime(runtime));
13617
13632
  const now = /* @__PURE__ */ new Date();
13618
13633
  const modTime = (now.getHours() << 11 | now.getMinutes() << 5 | now.getSeconds() >> 1) & 65535;
13619
13634
  const modDate = (now.getFullYear() - 1980 << 9 | now.getMonth() + 1 << 5 | now.getDate()) & 65535;
@@ -33548,10 +33563,17 @@ Acquiring lock for stack ${stackName}...`);
33548
33563
  } else {
33549
33564
  logger.warn(`${result.errorCount} resource(s) failed to delete. State preserved.`);
33550
33565
  }
33551
- logger.info(
33552
- `
33566
+ if (result.errorCount === 0) {
33567
+ logger.info(
33568
+ `
33553
33569
  \u2713 Stack ${stackName} destroyed (${result.deletedCount} deleted, ${result.errorCount} errors)`
33554
- );
33570
+ );
33571
+ } else {
33572
+ logger.warn(
33573
+ `
33574
+ \u26A0 Stack ${stackName} partially destroyed (${result.deletedCount} deleted, ${result.errorCount} errors). State preserved \u2014 re-run 'cdkd destroy' / 'cdkd state destroy' to clean up.`
33575
+ );
33576
+ }
33555
33577
  } finally {
33556
33578
  renderer.stop();
33557
33579
  logger.debug("Releasing lock...");
@@ -33671,6 +33693,7 @@ async function destroyCommand(stackArgs, options) {
33671
33693
  arr.push(ref);
33672
33694
  stateRefsByName.set(ref.stackName, arr);
33673
33695
  }
33696
+ let totalErrors = 0;
33674
33697
  for (const stackName of stackNames) {
33675
33698
  logger.info(`
33676
33699
  Preparing to destroy stack: ${stackName}`);
@@ -33701,7 +33724,7 @@ Preparing to destroy stack: ${stackName}`);
33701
33724
  logger.warn(`No state found for stack ${stackName}, skipping`);
33702
33725
  continue;
33703
33726
  }
33704
- await runDestroyForStack(stackName, stateResult.state, {
33727
+ const result = await runDestroyForStack(stackName, stateResult.state, {
33705
33728
  stateBackend,
33706
33729
  lockManager,
33707
33730
  providerRegistry,
@@ -33723,6 +33746,12 @@ Preparing to destroy stack: ${stackName}`);
33723
33746
  resourceTimeoutByType: options.resourceTimeout.perTypeMs
33724
33747
  }
33725
33748
  });
33749
+ totalErrors += result.errorCount;
33750
+ }
33751
+ if (totalErrors > 0) {
33752
+ throw new PartialFailureError(
33753
+ `Destroy completed with ${totalErrors} resource error(s). State preserved \u2014 inspect 'cdkd state show <stack>' and re-run 'cdkd destroy' to retry.`
33754
+ );
33726
33755
  }
33727
33756
  } finally {
33728
33757
  awsClients.destroy();
@@ -35420,8 +35449,8 @@ Preparing to destroy stack: ${stackName}${ref.region ? ` (${ref.region})` : ""}`
35420
35449
  }
35421
35450
  }
35422
35451
  if (totalErrors > 0) {
35423
- throw new Error(
35424
- `Destroy completed with ${totalErrors} resource error(s). Inspect 'cdkd state show <stack>' and re-run.`
35452
+ throw new PartialFailureError(
35453
+ `Destroy completed with ${totalErrors} resource error(s). State preserved \u2014 inspect 'cdkd state show <stack>' and re-run 'cdkd state destroy' to retry.`
35425
35454
  );
35426
35455
  }
35427
35456
  } finally {
@@ -36330,7 +36359,7 @@ function reorderArgs(argv) {
36330
36359
  }
36331
36360
  async function main() {
36332
36361
  const program = new Command13();
36333
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.31.0");
36362
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.31.2");
36334
36363
  program.addCommand(createBootstrapCommand());
36335
36364
  program.addCommand(createSynthCommand());
36336
36365
  program.addCommand(createListCommand());