@go-to-k/cdkd 0.76.0 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,15 @@
1
1
  # cdkd
2
2
 
3
- **cdkd** (CDK Direct) - A from-scratch CDK CLI with its own deployment engine — provisions via AWS SDK instead of CloudFormation.
3
+ **cdkd** (CDK Direct) a from-scratch CDK CLI that provisions via AWS SDK instead of CloudFormation.
4
4
 
5
- - **Direct provisioning** via AWS SDK instead of CloudFormation
6
- - **From-scratch CDK CLI** - synthesis orchestration, asset publishing, context resolution (no aws-cdk / toolkit-lib dependency)
7
- - **CDK compatible** - use your existing CDK app code as-is
8
- - **Own deployment engine** - diff calculation, dependency graph, parallel execution, state management (what CloudFormation handles internally)
5
+ - **Drop-in CDK compatible** your existing CDK app code runs as-is.
6
+ - **Up to 15x faster deploys than the AWS CDK CLI (CloudFormation)**
9
7
 
10
8
  ![cdkd demo](https://github.com/user-attachments/assets/0128730d-186d-4bd3-abea-aabc80ba4dd5)
11
9
 
12
10
  > **⚠️ WARNING: NOT PRODUCTION READY**
13
11
  >
14
- > This project is in early development and is **NOT suitable for production use**. Features are incomplete, APIs may change without notice, and there may be bugs that could affect your AWS infrastructure. Use at your own risk in development/testing environments only.
15
-
16
- > **Note**: This is an experimental/educational project exploring alternative deployment approaches for AWS CDK. It is **not intended to replace** the official AWS CDK CLI, but rather to experiment with direct SDK provisioning as a learning exercise and proof of concept.
12
+ > An experimental project exploring direct SDK provisioning as an alternative to the AWS CDK CLI — **NOT a replacement** and **NOT suitable for production use**. Features are incomplete, APIs may change without notice, and bugs may affect your AWS infrastructure. Use at your own risk in development / testing environments only.
17
13
 
18
14
  ## Features
19
15
 
@@ -32,31 +28,37 @@
32
28
 
33
29
  ## Benchmark
34
30
 
35
- **cdkd deploys up to ~5x faster than AWS CDK (CloudFormation).**
31
+ **cdkd deploys up to 15x faster than AWS CDK (CloudFormation)** on SDK-Provider-handled stacks; the per-stack speedup widens with size and parallelism, and drops to ~1.5-3x on stacks dominated by Cloud Control API fallback resources.
32
+
33
+ Numbers below are deploy-phase only (CDK app synthesis is identical between cdkd and AWS CDK — both run the same user code through `aws-cdk-lib`'s synthesizer — so synth time is excluded from the speedup calculation).
34
+
35
+ ### SDK Provider path — **5.5x faster** (17.0s vs 94.4s)
36
+
37
+ Stack: S3 Bucket, DynamoDB Table, SQS Queue, SNS Topic, SSM Parameter (5 independent resources, fully parallelized by cdkd's DAG scheduler).
38
+
39
+ | | AWS CDK (CFn) | cdkd | Speedup |
40
+ | --- | ---: | ---: | ---: |
41
+ | Deploy | **94.4s** | **17.0s** | **5.5x** |
36
42
 
37
- Measured on `us-east-1` with 5 independent resources per stack (fully parallelized by cdkd's DAG scheduler).
43
+ ### VPC + CloudFront + Lambda stack **15x faster with `--no-wait`** (40s vs 599s)
38
44
 
39
- ### SDK Provider path **4.8x faster** (20.5s vs 98.4s)
45
+ Real-world stack: 1 VPC (2 AZs, NAT Gateway, public + private subnets) + Lambda Function (with `VpcConfig`) + Lambda Function URL (AWS_IAM) + CloudFront Distribution (OAC, caching disabled) + SQS Queue + EventSourceMapping + Consumer Lambda.
40
46
 
41
- Stack: S3 Bucket, DynamoDB Table, SQS Queue, SNS Topic, SSM Parameter.
47
+ | | AWS CDK (CFn) | cdkd | cdkd `--no-wait` |
48
+ | --- | ---: | ---: | ---: |
49
+ | Deploy | **599s** | 197s (3.0x) | **40s (15.0x)** |
42
50
 
43
- | Phase | cdkd | AWS CDK (CFn) | Speedup |
44
- | --- | --- | --- | --- |
45
- | Synthesis | 3.5s | 4.1s | 1.2x |
46
- | Deploy | 17.0s | 94.4s | **5.5x** |
47
- | **Total** | **20.5s** | **98.4s** | **4.8x** |
51
+ The 15x figure requires `cdkd deploy --no-wait`, which returns as soon as each Create call returns and lets AWS finish CloudFront's ~5min propagation + NAT Gateway stabilization in the background. cdkd's default scheduler already parallelizes `CloudFront::Distribution` / `Lambda::Url` / VPC Lambda with NAT Gateway propagation (pass `--no-aggressive-vpc-parallel` to opt out); on this stack the default gives ~3x. `--no-wait` adds the rest of the gap by skipping the propagation waits entirely.
48
52
 
49
- ### Cloud Control API fallback path — **1.5x faster** (44.6s vs 69.1s)
53
+ ### Cloud Control API fallback path — **1.6x faster** (40.9s vs 64.9s)
50
54
 
51
55
  Stack: SSM Document × 3 + Athena WorkGroup × 2 (no SDK provider — CC API fallback).
52
56
 
53
- | Phase | cdkd | AWS CDK (CFn) | Speedup |
54
- | --- | --- | --- | --- |
55
- | Synthesis | 3.7s | 4.2s | 1.1x |
56
- | Deploy | 40.9s | 64.9s | **1.6x** |
57
- | **Total** | **44.6s** | **69.1s** | **1.5x** |
57
+ | | AWS CDK (CFn) | cdkd | Speedup |
58
+ | --- | ---: | ---: | ---: |
59
+ | Deploy | **64.9s** | **40.9s** | **1.6x** |
58
60
 
59
- Reproduce with `./tests/benchmark/run-benchmark.sh all`. See [tests/benchmark/README.md](tests/benchmark/README.md) for details.
61
+ Reproduce the first two with `./tests/benchmark/run-benchmark.sh all`. See [tests/benchmark/README.md](tests/benchmark/README.md) for details.
60
62
 
61
63
  ## How it works
62
64
 
@@ -97,87 +99,11 @@ For a step-by-step walkthrough of the full `cdkd deploy` pipeline (CLI
97
99
  parsing → synthesis → asset publishing → per-stack deploy), see
98
100
  [docs/architecture.md](docs/architecture.md#5-end-to-end-pipeline-walkthrough-cdkd-deploy).
99
101
 
100
- ## Supported Features
101
-
102
- ### Intrinsic Functions
103
-
104
- | Function | Status | Notes |
105
- |----------|--------|-------|
106
- | `Ref` | ✅ Supported | Resource physical IDs, Parameters, Pseudo parameters |
107
- | `Fn::GetAtt` | ✅ Supported | Resource attributes (ARN, DomainName, etc.) |
108
- | `Fn::Join` | ✅ Supported | String concatenation |
109
- | `Fn::Sub` | ✅ Supported | Template string substitution |
110
- | `Fn::Select` | ✅ Supported | Array index selection |
111
- | `Fn::Split` | ✅ Supported | String splitting |
112
- | `Fn::If` | ✅ Supported | Conditional values |
113
- | `Fn::Equals` | ✅ Supported | Equality comparison |
114
- | `Fn::And` | ✅ Supported | Logical AND (2-10 conditions) |
115
- | `Fn::Or` | ✅ Supported | Logical OR (2-10 conditions) |
116
- | `Fn::Not` | ✅ Supported | Logical NOT |
117
- | `Fn::ImportValue` | ✅ Supported | Cross-stack references via S3 state |
118
- | `Fn::GetStackOutput` | ✅ Supported (same-account) | Cross-stack / cross-region output reference via S3 state. Cross-account `RoleArn` is rejected with a clear error (not yet implemented). |
119
- | `Fn::FindInMap` | ✅ Supported | Mapping lookup |
120
- | `Fn::GetAZs` | ✅ Supported | Availability Zone list |
121
- | `Fn::Base64` | ✅ Supported | Base64 encoding |
122
- | `Fn::Cidr` | ✅ Supported | CIDR address block generation |
123
-
124
- ### Pseudo Parameters
125
-
126
- | Parameter | Status |
127
- |-----------|--------|
128
- | `AWS::Region` | ✅ |
129
- | `AWS::AccountId` | ✅ (via STS) |
130
- | `AWS::Partition` | ✅ |
131
- | `AWS::URLSuffix` | ✅ |
132
- | `AWS::NoValue` | ✅ |
133
- | `AWS::StackName` | ✅ |
134
- | `AWS::StackId` | ✅ |
135
-
136
- ### Resource Provisioning
137
-
138
- cdkd ships **90+ dedicated SDK Providers** (direct AWS SDK calls, no
139
- polling overhead) covering the most-used services — IAM, Lambda, S3,
140
- DynamoDB, EC2, RDS, ECS, API Gateway, CloudFront, Step Functions, EFS,
141
- KMS, Cognito, AppSync, and more. **Any other CloudFormation resource
142
- type** is handled via the Cloud Control API fallback (async polling).
143
- Resource types not supported by either path fail at deploy time with a
144
- clear error.
145
-
146
- See **[docs/supported-resources.md](docs/supported-resources.md)** for
147
- the full per-type table.
148
-
149
- ### Other Features
150
-
151
- | Feature | Status | Notes |
152
- |---------|--------|-------|
153
- | CloudFormation Parameters | ✅ | Default values, type coercion |
154
- | Conditions | ✅ | With logical operators |
155
- | Cross-stack references | ✅ | Via `Fn::ImportValue` + S3 state |
156
- | Cross-region references | ✅ (same-account) | Via `Fn::GetStackOutput` + S3 state. Cross-account `RoleArn` not yet implemented. |
157
- | JSON Patch updates | ✅ | RFC 6902, minimal patches |
158
- | Resource replacement detection | ✅ | 10+ resource types |
159
- | Dynamic References | ✅ | `{{resolve:secretsmanager:...}}`, `{{resolve:ssm:...}}` |
160
- | DELETE idempotency | ✅ | Not-found errors treated as success |
161
- | Asset publishing (S3) | ✅ | Lambda code packages |
162
- | Asset publishing (ECR) | ✅ | Self-implemented Docker image publishing |
163
- | Custom Resources (SNS-backed) | ✅ | SNS Topic ServiceToken + S3 response |
164
- | Custom Resources (CDK Provider) | ✅ | isCompleteHandler/onEventHandler async pattern detection |
165
- | Rollback | ✅ | Auto-rollback on mid-deploy failure (deletes already-completed resources to keep state consistent); `--no-rollback` skips for Terraform-style failed-state inspection. See [Rollback behavior](#rollback-behavior) below. |
166
- | DeletionPolicy: Retain | ✅ | Skip deletion for retained resources |
167
- | UpdateReplacePolicy: Retain | ✅ | Keep old resource on replacement |
168
- | Implicit delete dependencies | ✅ | VPC/IGW/EventBus/Subnet/RouteTable ordering |
169
- | Stack dependency resolution | ✅ | Auto-deploy dependency stacks, `-e` to skip |
170
- | Multi-stack parallel deploy | ✅ | Independent stacks deployed in parallel |
171
- | Attribute enrichment | ✅ | CloudFront OAI, DynamoDB StreamArn, API Gateway RootResourceId, Lambda FunctionUrl, Route53 HealthCheckId, ECR Repository Arn |
172
- | CC API null value stripping | ✅ | Removes null values before API calls |
173
- | Retry with HTTP status codes | ✅ | 429/503 + cause chain inspection |
174
- | Drift detection | ✅ | `cdkd drift` — state vs AWS reality, including console-side changes to keys you didn't template. See [Drift detection](#drift-detection) below. |
175
-
176
102
  ## Prerequisites
177
103
 
178
104
  - **Node.js** >= 20.0.0
179
105
  - **AWS CDK Bootstrap**: You must run `cdk bootstrap` before using cdkd. cdkd uses CDK's bootstrap bucket (`cdk-hnb659fds-assets-*`) for asset uploads (Lambda code, Docker images). Custom bootstrap qualifiers are supported — CDK embeds the correct bucket/repo names in the asset manifest during synthesis.
180
- - **AWS Credentials**: Configured via environment variables, `~/.aws/credentials`, `--profile`, or `--role-arn` option. **The credentials must have admin-equivalent permissions for the resources being deployed.** Unlike `cdk deploy`, cdkd does NOT route through CloudFormation, so there is no cfn-exec-role to delegate to — every IAM / EC2 / Lambda / etc. API call is issued from cdkd directly. CDK CLI's `cdk-hnb659fds-deploy-role-*` only carries CFn + asset-publish permissions and is therefore NOT sufficient for cdkd. See `--role-arn` in [docs/cli-reference.md](docs/cli-reference.md) for assuming a role with the right permissions.
106
+ - **AWS credentials with admin-equivalent permissions** for the resources being deployed. cdkd does NOT route through CloudFormation, so CDK CLI's `cdk-hnb659fds-deploy-role-*` is NOT sufficient see [`--role-arn`](docs/cli-reference.md).
181
107
 
182
108
  ## Installation
183
109
 
@@ -188,8 +114,6 @@ npm i -g @go-to-k/cdkd@0.0.2 # pin to a specific version
188
114
 
189
115
  The installed binary is `cdkd`.
190
116
 
191
- > cdkd is an experimental / educational project and is not intended for production use — see the warning at the top of this README. Pin to a specific version if you need reproducible installs.
192
-
193
117
  ## Quick Start
194
118
 
195
119
  > **First-time setup**: cdkd requires a one-time `cdkd bootstrap` per AWS
@@ -388,6 +312,16 @@ cdkd state destroy --all -y # every stack in the bucket
388
312
  cdkd state destroy MyStack --region us-east-1
389
313
  ```
390
314
 
315
+ ## Compatibility
316
+
317
+ cdkd supports the standard CloudFormation surface — intrinsic functions,
318
+ pseudo parameters, parameters / conditions, cross-stack / cross-region
319
+ references, asset publishing, custom resources, and so on. See
320
+ **[docs/supported-features.md](docs/supported-features.md)** for the
321
+ full reference. For per-resource-type provisioning support (SDK Providers
322
+ vs Cloud Control API fallback), see
323
+ **[docs/supported-resources.md](docs/supported-resources.md)**.
324
+
391
325
  ## Rollback behavior
392
326
 
393
327
  When a deploy fails mid-stack (e.g. a resource hits a validation error
@@ -564,17 +498,23 @@ Lambda Runtime Interface Emulator (RIE). Modeled on `sam local invoke`
564
498
  but reusing cdkd's synthesis / asset / construct-path plumbing — no
565
499
  `template.yaml` to maintain, no `cdk synth | sam ...` round-trip.
566
500
 
567
- Requires Docker. v1 supports Node.js and Python runtimes (`nodejs18.x` /
568
- `nodejs20.x` / `nodejs22.x` / `nodejs24.x` / `python3.11` / `python3.12` /
569
- `python3.13` / `python3.14`); other runtimes follow in subsequent PRs.
570
-
571
- **Container Lambdas (PR 5 of #224)** — `lambda.DockerImageFunction(...)` /
501
+ Requires Docker. Supports Node.js, Python, Ruby, and Java runtimes
502
+ (`nodejs18.x` / `nodejs20.x` / `nodejs22.x` / `nodejs24.x` / `python3.11` /
503
+ `python3.12` / `python3.13` / `python3.14` / `ruby3.2` / `ruby3.3` /
504
+ `java8.al2` / `java11` / `java17` / `java21`); other runtimes (.NET / Go /
505
+ `provided.*`) are not yet supported. Java Lambdas are **asset-backed only**
506
+ the Handler shape `package.Class::method` names a compiled class, so use
507
+ `lambda.Code.fromAsset(<dir>)` with a directory containing the compiled
508
+ output (`.class` hierarchy or `.jar`); inline `Code.ZipFile` is rejected
509
+ with a clear routing message.
510
+
511
+ **Container Lambdas** — `lambda.DockerImageFunction(...)` /
572
512
  `Code.ImageUri` is supported alongside ZIP Lambdas. cdkd reads the
573
513
  function's local `Dockerfile` from `cdk.out` and runs `docker build`
574
514
  locally before invoking. When no asset matches (typically: invoking a
575
515
  stack deployed elsewhere), cdkd falls back to `docker pull` from
576
516
  ECR — same-account / same-region only in v1; cross-account /
577
- cross-region is deferred to a follow-up PR. `Architectures: [x86_64]` /
517
+ cross-region is not yet supported. `Architectures: [x86_64]` /
578
518
  `[arm64]` are honored via `--platform` so an arm64 host running an
579
519
  x86_64 Lambda doesn't hit emulation.
580
520
 
@@ -615,7 +555,7 @@ cdkd local invoke MyStack/Handler --debug-port 9229
615
555
  cdkd local invoke MyStack/Handler --from-state
616
556
  ```
617
557
 
618
- **Lambda Layers (PR 6 of #224, issue #232)** — same-stack
558
+ **Lambda Layers** — same-stack
619
559
  `AWS::Lambda::LayerVersion` references in `Properties.Layers` are
620
560
  resolved automatically and bind-mounted at `/opt` (read-only) inside
621
561
  the container. Each layer's unzipped asset directory under `cdk.out/`
@@ -663,12 +603,11 @@ cdkd local start-api --stage prod
663
603
  ```
664
604
 
665
605
  Scope: REST v1 + HTTP API + Function URL with AWS_PROXY integrations.
666
- Authorizers (PR 8b — Lambda TOKEN/REQUEST + Cognito User Pool + HTTP v2
667
- JWT), VPC-config Lambda warnings (PR 8b), CORS preflight (PR 8c), hot
668
- reload (PR 8c), and stage variables (PR 8c) are supported. WebSocket
669
- APIs are deferred to a follow-up PR.
606
+ Authorizers (Lambda TOKEN/REQUEST + Cognito User Pool + HTTP v2 JWT),
607
+ VPC-config Lambda warnings, CORS preflight, hot reload, and stage
608
+ variables are supported. WebSocket APIs are not.
670
609
 
671
- **Authorizers (PR 8b)**: `Authorization: Bearer <token>`-protected
610
+ **Authorizers**: `Authorization: Bearer <token>`-protected
672
611
  routes are gated on the authorizer Lambda's response (TOKEN / REQUEST
673
612
  authorizers, IAM-policy or HTTP v2 simple shape) or on a JWKS-based JWT
674
613
  verification (Cognito User Pool authorizers, HTTP v2 JWT authorizers).
@@ -677,7 +616,7 @@ back to **pass-through mode** (every JWT accepted, with a warn line at
677
616
  startup) — local-dev-only fallback so a corporate proxy doesn't block
678
617
  iteration. **Do NOT rely on this in any shared environment.**
679
618
 
680
- **VPC-config Lambdas (PR 8b)**: handlers with `Properties.VpcConfig`
619
+ **VPC-config Lambdas**: handlers with `Properties.VpcConfig`
681
620
  still run locally, but the local container is NOT attached to the
682
621
  deployed VPC's subnets — calls to private RDS / ElastiCache will fail.
683
622
  cdkd warns at startup naming each affected Lambda; AWS SDK calls still
package/dist/cli.js CHANGED
@@ -70571,7 +70571,13 @@ var SUPPORTED_RUNTIMES = {
70571
70571
  "python3.11": { image: "public.ecr.aws/lambda/python:3.11", fileExtension: ".py" },
70572
70572
  "python3.12": { image: "public.ecr.aws/lambda/python:3.12", fileExtension: ".py" },
70573
70573
  "python3.13": { image: "public.ecr.aws/lambda/python:3.13", fileExtension: ".py" },
70574
- "python3.14": { image: "public.ecr.aws/lambda/python:3.14", fileExtension: ".py" }
70574
+ "python3.14": { image: "public.ecr.aws/lambda/python:3.14", fileExtension: ".py" },
70575
+ "ruby3.2": { image: "public.ecr.aws/lambda/ruby:3.2", fileExtension: ".rb" },
70576
+ "ruby3.3": { image: "public.ecr.aws/lambda/ruby:3.3", fileExtension: ".rb" },
70577
+ "java8.al2": { image: "public.ecr.aws/lambda/java:8.al2", fileExtension: null },
70578
+ java11: { image: "public.ecr.aws/lambda/java:11", fileExtension: null },
70579
+ java17: { image: "public.ecr.aws/lambda/java:17", fileExtension: null },
70580
+ java21: { image: "public.ecr.aws/lambda/java:21", fileExtension: null }
70575
70581
  };
70576
70582
  var UnsupportedRuntimeError = class _UnsupportedRuntimeError extends Error {
70577
70583
  constructor(runtime, message) {
@@ -70585,7 +70591,14 @@ function resolveRuntimeImage(runtime) {
70585
70591
  return resolveRuntimeSpec(runtime).image;
70586
70592
  }
70587
70593
  function resolveRuntimeFileExtension(runtime) {
70588
- return resolveRuntimeSpec(runtime).fileExtension;
70594
+ const spec = resolveRuntimeSpec(runtime);
70595
+ if (spec.fileExtension === null) {
70596
+ throw new UnsupportedRuntimeError(
70597
+ runtime,
70598
+ `Inline 'Code.ZipFile' is not supported for runtime '${runtime}'. The Lambda Handler shape for this runtime names a compiled artifact (a JVM class, a .NET assembly, or a native binary) that cannot be expressed as a single inline source file. Use \`lambda.Code.fromAsset(<dir>)\` with a directory containing the compiled output (.class hierarchy / JAR / DLL / binary).`
70599
+ );
70600
+ }
70601
+ return spec.fileExtension;
70589
70602
  }
70590
70603
  function resolveRuntimeSpec(runtime) {
70591
70604
  if (typeof runtime !== "string" || runtime.length === 0) {
@@ -70597,15 +70610,15 @@ function resolveRuntimeSpec(runtime) {
70597
70610
  const spec = SUPPORTED_RUNTIMES[runtime];
70598
70611
  if (spec)
70599
70612
  return spec;
70600
- if (runtime.startsWith("java") || runtime.startsWith("dotnet") || runtime.startsWith("ruby") || runtime.startsWith("go") || runtime.startsWith("provided")) {
70613
+ if (runtime.startsWith("dotnet") || runtime.startsWith("go") || runtime.startsWith("provided")) {
70601
70614
  throw new UnsupportedRuntimeError(
70602
70615
  runtime,
70603
- `Runtime '${runtime}' is not supported in cdkd local invoke v1. Only Node.js (nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x) and Python (python3.11 / python3.12 / python3.13 / python3.14) runtimes are supported. Other runtimes follow in subsequent PRs.`
70616
+ `Runtime '${runtime}' is not yet supported in cdkd local invoke. Supported runtimes: Node.js (nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x), Python (python3.11 / python3.12 / python3.13 / python3.14), Ruby (ruby3.2 / ruby3.3), Java (java8.al2 / java11 / java17 / java21). Other runtimes follow in subsequent PRs.`
70604
70617
  );
70605
70618
  }
70606
70619
  throw new UnsupportedRuntimeError(
70607
70620
  runtime,
70608
- `Unknown runtime '${runtime}'. cdkd local invoke v1 supports nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x / python3.11 / python3.12 / python3.13 / python3.14.`
70621
+ `Unknown runtime '${runtime}'. cdkd local invoke supports nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x / python3.11 / python3.12 / python3.13 / python3.14 / ruby3.2 / ruby3.3 / java8.al2 / java11 / java17 / java21.`
70609
70622
  );
70610
70623
  }
70611
70624
 
@@ -77030,7 +77043,7 @@ function reorderArgs(argv) {
77030
77043
  }
77031
77044
  async function main() {
77032
77045
  const program = new Command16();
77033
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.76.0");
77046
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.78.0");
77034
77047
  program.addCommand(createBootstrapCommand());
77035
77048
  program.addCommand(createSynthCommand());
77036
77049
  program.addCommand(createListCommand());