@go-to-k/cdkd 0.280.34 → 0.280.35

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
@@ -345,140 +345,95 @@ the per-resource table (what each mode does, next to what
345
345
  CloudFormation and Terraform do) and caveats (NAT egress, RDS
346
346
  final-snapshot timing, etc.).
347
347
 
348
- ## Local execution
349
-
350
- The `cdkd local` family runs AWS workloads on the developer's machine
351
- via Docker — Lambda functions, API Gateway routes, ECS tasks, and
352
- long-running ECS services — without an AWS deploy. Modeled on `sam local *` but reuses cdkd's
353
- synthesis / asset / construct-path plumbing — no `template.yaml` to
354
- maintain, no `cdk synth | sam ...` round-trip.
355
-
356
- | Subcommand | Emulates |
357
- | --- | --- |
358
- | `cdkd local invoke <target>` | One-shot Lambda invoke via the AWS Lambda Runtime Interface Emulator (RIE) |
359
- | `cdkd local start-api` | Long-running HTTP server for REST v1 / HTTP API / Function URL routes |
360
- | `cdkd local run-task <target>` | ECS RunTask — every container in a task definition started on a per-task docker network |
361
- | `cdkd local start-service <target>` | Long-running ECS Service emulator — `DesiredCount` replicas with restart-on-exit (no local load balancer in v1) |
362
- | `cdkd local invoke-agentcore <target>` | One-shot Bedrock AgentCore Runtime invoke (HTTP `/invocations` / MCP `/mcp` / A2A `/a2a` / AGUI / WebSocket `--ws`) |
363
- | `cdkd local start-agentcore [target]` | Long-running serve of a Bedrock AgentCore Runtime against a warm container (all four protocols): HTTP / AGUI serve `POST /invocations` + `GET /ping` plus the `/ws` bridge (injects the session-id / Authorization a header-less browser client cannot set); MCP serves `/mcp`, A2A serves `/`. `--sigv4` / `--watch` supported |
364
- | `cdkd local start-alb <targets...>` | Long-running local ALB front-door (HTTP + HTTPS listeners, path / host / header / weighted / redirect / fixed-response routing, authenticate-cognito / authenticate-oidc) for ECS / Lambda backing services |
365
- | `cdkd local start-cloudfront [target]` | Long-running local CloudFront distribution — viewer-request -> S3 / Lambda Function URL origin -> viewer-response pipeline, CloudFront Functions run in-process (Function URL origins use Docker/RIE) |
366
-
367
- The Docker-backed commands above require Docker. Pass `--from-state`
368
- (cdkd-deployed) or `--from-cfn-stack` (cdk-deployed / CFn-managed) to
369
- substitute deployed physical IDs into intrinsic-valued env vars /
370
- secrets / image URIs; without either, intrinsic values are dropped with
371
- a per-key warning (matches `sam local *`). The two flags are mutually
372
- exclusive. `start-cloudfront` carries both `--from-state` and
373
- `--from-cfn-stack` too (since cdk-local 0.128.0 / issue #766); a
374
- CloudFront-Functions + S3-origin distribution still serves entirely
375
- in-process (no Docker), while a Lambda Function URL origin runs via the
376
- RIE container.
377
-
378
- ### `local invoke`
379
-
380
- ```bash
381
- cdkd local invoke MyStack/Handler # one-shot invoke
382
- cdkd local invoke MyStack/Handler --event events/get.json
383
- cdkd local invoke MyStack/Handler --from-state # OR --from-cfn-stack
384
- ```
348
+ ## Use in CI: per-PR environments
385
349
 
386
- All AWS Lambda runtimes (Node.js / Python / Ruby / Java / .NET /
387
- `provided.al2023`), ZIP and container Lambdas, same-stack Lambda Layers
388
- bind-mounted at `/opt`.
350
+ Deploy time is CI job time, and a PR environment redeploys on every
351
+ push so cdkd's speedup compounds across a PR's lifetime. Because
352
+ cdkd needs **zero CDK code changes**, you can swap only the PR-environment
353
+ workflow to cdkd and keep production / staging on the CDK CLI; switching
354
+ back is a one-line workflow revert.
389
355
 
390
- ### `local start-api`
356
+ Run `cdkd bootstrap` once per AWS account beforehand (creates the state
357
+ bucket + asset storage; `cdk bootstrap` is not required).
391
358
 
392
- ```bash
393
- cdkd local start-api # one HTTP server per discovered API
394
- cdkd local start-api MyStack/MyHttpApi --watch # filter + hot reload
395
- cdkd local start-api --from-state # OR --from-cfn-stack
359
+ **One stack per PR** — pass the PR number as CDK context and suffix the
360
+ stack name; cdkd state is keyed by (stack name, region) and locks are
361
+ per-stack, so PR environments deploy concurrently without contention:
396
362
 
397
- # Typical shape — the bare `--from-cfn-stack` flag auto-resolves to the
398
- # routed stack's name (here `MyStack`). Pass an explicit value only when
399
- # the deployed CFn stack name differs from the CDK stack name.
400
- cdkd local start-api MyStack/MyHttpApi --from-cfn-stack
363
+ ```ts
364
+ const prNumber = app.node.tryGetContext('prNumber');
365
+ new WebAppStack(app, `WebApp${prNumber ? `-pr-${prNumber}` : ''}`);
401
366
  ```
402
367
 
403
- REST v1 + HTTP API v2 + Function URL with all integration kinds
404
- (AWS_PROXY / MOCK / HTTP_PROXY / HTTP / AWS Lambda non-proxy via
405
- hand-rolled VTL), authorizers (Lambda / Cognito / HTTP v2 JWT /
406
- AWS_IAM SigV4 on REST v1 + Function URL), CORS, stage variables,
407
- `--watch` hot reload.
408
-
409
- ### `local run-task`
410
-
411
- ```bash
412
- cdkd local run-task MyStack/MyService/TaskDef
413
- cdkd local run-task MyTaskDef --from-state # OR --from-cfn-stack
368
+ **Credentials** cdkd calls AWS APIs directly, so the deploying
369
+ identity needs permissions for every deployed resource (CDK's
370
+ `cdk-hnb659fds-*` roles do not work: they are designed for
371
+ CloudFormation delegation, and cdkd uses its own bootstrap storage).
372
+ Create a dedicated deploy role and switch into it with
373
+ [`--role-arn`](docs/cli-reference.md#--role-arn) (or the
374
+ `CDKD_ROLE_ARN` env var): the workflow's OIDC base role needs only
375
+ `sts:AssumeRole` on the deploy role, and the deploy role's trust policy
376
+ allows only that base role — the strong permissions live in exactly one
377
+ place, reachable through one path, and never sit on the CI runner
378
+ itself.
379
+
380
+ **Minimal GitHub Actions shape** (deploy on open/sync/reopen, destroy
381
+ on close):
382
+
383
+ ```yaml
384
+ on:
385
+ pull_request:
386
+ types: [opened, synchronize, reopened, closed]
387
+ permissions: { id-token: write, contents: read }
388
+ env:
389
+ CDKD_ROLE_ARN: arn:aws:iam::123456789012:role/cdkd-deploy-role
390
+ jobs:
391
+ deploy:
392
+ if: github.event.action != 'closed'
393
+ runs-on: ubuntu-latest
394
+ steps:
395
+ - uses: actions/checkout@v7
396
+ - uses: actions/setup-node@v7
397
+ with: { node-version: 24, cache: npm }
398
+ - run: npm ci
399
+ - uses: aws-actions/configure-aws-credentials@v6
400
+ with:
401
+ role-to-assume: arn:aws:iam::123456789012:role/github-actions-base
402
+ aws-region: us-east-1
403
+ - run: npx cdkd deploy --yes -c prNumber=${{ github.event.pull_request.number }}
404
+ destroy:
405
+ if: github.event.action == 'closed'
406
+ runs-on: ubuntu-latest
407
+ steps:
408
+ - uses: aws-actions/configure-aws-credentials@v6
409
+ with:
410
+ role-to-assume: arn:aws:iam::123456789012:role/github-actions-base
411
+ aws-region: us-east-1
412
+ - run: npx @go-to-k/cdkd state destroy WebApp-pr-${{ github.event.pull_request.number }} --yes
414
413
  ```
415
414
 
416
- Every container in the task definition on a per-task docker network
417
- with the AWS-published ECS metadata sidecar.
418
-
419
- ### `local start-service`
420
-
421
- ```bash
422
- cdkd local start-service MyStack/Orders MyStack/Web # multiple services in one invocation
423
- cdkd local start-service MyStack/Orders --from-state # OR --from-cfn-stack
424
- cdkd local start-service MyStack/Web --watch # hot reload (sub-second on interpreted handlers)
425
- ```
426
-
427
- Long-running ECS Service emulator: `DesiredCount` replicas with
428
- restart-on-exit, cross-service Service Connect / Cloud Map DNS
429
- discovery (peer containers reach each other by `<discoveryName>.<namespace>`).
430
- No local load-balancer in v1. `--watch` re-synths on every CDK source edit
431
- and reloads one replica at a time source-only edits on
432
- interpreted-language handlers (Node / Python / Ruby / shell) take a
433
- bind-mount fast path (`docker cp` + `docker restart`; no rebuild);
434
- Dockerfile / dependency manifest / compiled-language source edits fall
435
- through to a full rebuild + shadow boot + atomic swap.
436
-
437
- ### `local start-alb`
438
-
439
- ```bash
440
- cdkd local start-alb MyStack/MyAlb --lb-port 80=8080 # remap privileged listener port
441
- cdkd local start-alb MyStack/MyAlb --from-state # OR --from-cfn-stack
442
- cdkd local start-alb MyStack/MyAlb --watch # hot reload (sub-second on interpreted handlers)
443
- ```
444
-
445
- Long-running local ALB front-door: names an `AWS::ElasticLoadBalancingV2::LoadBalancer`,
446
- boots every ECS service behind its listeners, and stands up a local
447
- HTTP / HTTPS front-door on each listener port that round-robins across
448
- the running replicas and routes its listener rules across the backing
449
- services. Forward / redirect / fixed-response actions; ECS or Lambda
450
- targets; authenticate-cognito / authenticate-oidc via a local Bearer-JWT
451
- check. `--watch` reloads one backing-replica at a time across edits —
452
- interpreted-handler source edits go through the bind-mount fast path
453
- (no rebuild); Dockerfile / dependency / compiled-source edits fall
454
- through to a rebuild + atomic front-door pool swap.
455
-
456
- ### `local start-cloudfront`
457
-
458
- ```bash
459
- cdkd local start-cloudfront # interactive picker
460
- cdkd local start-cloudfront MyStack/MyDistribution # name the distribution
461
- cdkd local start-cloudfront MyStack/MyDistribution --watch # re-synth + swap on edit
462
- cdkd local start-cloudfront MyStack/MyDistribution --tls # real HTTPS termination
463
- ```
464
-
465
- Serves a CloudFront distribution's **viewer-request -> S3 origin ->
466
- viewer-response** pipeline locally so a routing-function change is
467
- verifiable in seconds instead of a deploy round-trip. The distribution's
468
- `AWS::CloudFront::Function`s (URL rewrites, trailing-slash normalization,
469
- SPA fallback, header tweaks) run in-process in a `node:vm` sandbox; the
470
- S3 origin content is the `BucketDeployment` source asset resolved out of
471
- the cloud assembly, served with `DefaultRootObject` and
472
- `CustomErrorResponses`. Path patterns route across the default + ordered
473
- cache behaviors. Pure-local: no Docker, no AWS call — `--watch` is just
474
- re-synth + an in-memory routing-model swap. S3 origins only (custom /
475
- Lambda@Edge origins are warn-and-skip); `--origin <id>=<dir>` points an
476
- origin at a local directory when `BucketDeployment` resolution can't.
477
-
478
- See **[docs/local-emulation.md](docs/local-emulation.md)** for the
479
- full reference — runtimes, target resolution, every flag, integration
480
- and authorizer detail, route precedence, container pool, networking,
481
- `--from-cfn-stack` semantics, v1 scope.
415
+ The destroy job has no checkout, `npm ci`, or synth
416
+ [`cdkd state destroy`](#orphan-vs-destroy) deletes from the state
417
+ record alone, so it works even after the branch is gone.
418
+
419
+ **Housekeeping**:
420
+
421
+ - Pick the wait mode from what runs next (see the section above):
422
+ review-only environments can use `--no-wait`; E2E tests after the
423
+ deploy should keep the default, or `--full-wait` when they need ECS
424
+ steady state / CloudFront propagation.
425
+ - A job cancelled mid-deploy (e.g. `concurrency.cancel-in-progress`)
426
+ can leave a stack lock; it expires on its own TTL (30 minutes), or
427
+ run `cdkd force-unlock <stack>` to clear it immediately.
428
+ - Sweep forgotten environments with `cdkd state list --json` on a
429
+ schedule, and reclaim unreferenced assets with
430
+ `cdkd gc --older-than 30d --dry-run` `gc` aborts if any stack is
431
+ locked, so schedule it outside deploy hours.
432
+ - To comment the environment URL on the PR, read stack outputs with
433
+ `cdkd state show <stack> --json`.
434
+ - To gate a PR without deploying, `cdkd diff --fail` exits `1` when any
435
+ change is detected (and `cdkd drift --json` machine-checks live
436
+ divergence). See [Exit codes](#exit-codes) for per-command semantics.
482
437
 
483
438
  ## Rollback behavior
484
439
 
@@ -849,6 +804,141 @@ destroyed (...). State preserved — re-run 'cdkd destroy' / 'cdkd
849
804
  state destroy' to clean up.` so the visual marker matches the exit
850
805
  code.
851
806
 
807
+ ## Local execution
808
+
809
+ The `cdkd local` family runs AWS workloads on the developer's machine
810
+ via Docker — Lambda functions, API Gateway routes, ECS tasks, and
811
+ long-running ECS services — without an AWS deploy. Modeled on `sam local *` but reuses cdkd's
812
+ synthesis / asset / construct-path plumbing — no `template.yaml` to
813
+ maintain, no `cdk synth | sam ...` round-trip.
814
+
815
+ | Subcommand | Emulates |
816
+ | --- | --- |
817
+ | `cdkd local invoke <target>` | One-shot Lambda invoke via the AWS Lambda Runtime Interface Emulator (RIE) |
818
+ | `cdkd local start-api` | Long-running HTTP server for REST v1 / HTTP API / Function URL routes |
819
+ | `cdkd local run-task <target>` | ECS RunTask — every container in a task definition started on a per-task docker network |
820
+ | `cdkd local start-service <target>` | Long-running ECS Service emulator — `DesiredCount` replicas with restart-on-exit (no local load balancer in v1) |
821
+ | `cdkd local invoke-agentcore <target>` | One-shot Bedrock AgentCore Runtime invoke (HTTP `/invocations` / MCP `/mcp` / A2A `/a2a` / AGUI / WebSocket `--ws`) |
822
+ | `cdkd local start-agentcore [target]` | Long-running serve of a Bedrock AgentCore Runtime against a warm container (all four protocols): HTTP / AGUI serve `POST /invocations` + `GET /ping` plus the `/ws` bridge (injects the session-id / Authorization a header-less browser client cannot set); MCP serves `/mcp`, A2A serves `/`. `--sigv4` / `--watch` supported |
823
+ | `cdkd local start-alb <targets...>` | Long-running local ALB front-door (HTTP + HTTPS listeners, path / host / header / weighted / redirect / fixed-response routing, authenticate-cognito / authenticate-oidc) for ECS / Lambda backing services |
824
+ | `cdkd local start-cloudfront [target]` | Long-running local CloudFront distribution — viewer-request -> S3 / Lambda Function URL origin -> viewer-response pipeline, CloudFront Functions run in-process (Function URL origins use Docker/RIE) |
825
+
826
+ The Docker-backed commands above require Docker. Pass `--from-state`
827
+ (cdkd-deployed) or `--from-cfn-stack` (cdk-deployed / CFn-managed) to
828
+ substitute deployed physical IDs into intrinsic-valued env vars /
829
+ secrets / image URIs; without either, intrinsic values are dropped with
830
+ a per-key warning (matches `sam local *`). The two flags are mutually
831
+ exclusive. `start-cloudfront` carries both `--from-state` and
832
+ `--from-cfn-stack` too (since cdk-local 0.128.0 / issue #766); a
833
+ CloudFront-Functions + S3-origin distribution still serves entirely
834
+ in-process (no Docker), while a Lambda Function URL origin runs via the
835
+ RIE container.
836
+
837
+ ### `local invoke`
838
+
839
+ ```bash
840
+ cdkd local invoke MyStack/Handler # one-shot invoke
841
+ cdkd local invoke MyStack/Handler --event events/get.json
842
+ cdkd local invoke MyStack/Handler --from-state # OR --from-cfn-stack
843
+ ```
844
+
845
+ All AWS Lambda runtimes (Node.js / Python / Ruby / Java / .NET /
846
+ `provided.al2023`), ZIP and container Lambdas, same-stack Lambda Layers
847
+ bind-mounted at `/opt`.
848
+
849
+ ### `local start-api`
850
+
851
+ ```bash
852
+ cdkd local start-api # one HTTP server per discovered API
853
+ cdkd local start-api MyStack/MyHttpApi --watch # filter + hot reload
854
+ cdkd local start-api --from-state # OR --from-cfn-stack
855
+
856
+ # Typical shape — the bare `--from-cfn-stack` flag auto-resolves to the
857
+ # routed stack's name (here `MyStack`). Pass an explicit value only when
858
+ # the deployed CFn stack name differs from the CDK stack name.
859
+ cdkd local start-api MyStack/MyHttpApi --from-cfn-stack
860
+ ```
861
+
862
+ REST v1 + HTTP API v2 + Function URL with all integration kinds
863
+ (AWS_PROXY / MOCK / HTTP_PROXY / HTTP / AWS Lambda non-proxy via
864
+ hand-rolled VTL), authorizers (Lambda / Cognito / HTTP v2 JWT /
865
+ AWS_IAM SigV4 on REST v1 + Function URL), CORS, stage variables,
866
+ `--watch` hot reload.
867
+
868
+ ### `local run-task`
869
+
870
+ ```bash
871
+ cdkd local run-task MyStack/MyService/TaskDef
872
+ cdkd local run-task MyTaskDef --from-state # OR --from-cfn-stack
873
+ ```
874
+
875
+ Every container in the task definition on a per-task docker network
876
+ with the AWS-published ECS metadata sidecar.
877
+
878
+ ### `local start-service`
879
+
880
+ ```bash
881
+ cdkd local start-service MyStack/Orders MyStack/Web # multiple services in one invocation
882
+ cdkd local start-service MyStack/Orders --from-state # OR --from-cfn-stack
883
+ cdkd local start-service MyStack/Web --watch # hot reload (sub-second on interpreted handlers)
884
+ ```
885
+
886
+ Long-running ECS Service emulator: `DesiredCount` replicas with
887
+ restart-on-exit, cross-service Service Connect / Cloud Map DNS
888
+ discovery (peer containers reach each other by `<discoveryName>.<namespace>`).
889
+ No local load-balancer in v1. `--watch` re-synths on every CDK source edit
890
+ and reloads one replica at a time — source-only edits on
891
+ interpreted-language handlers (Node / Python / Ruby / shell) take a
892
+ bind-mount fast path (`docker cp` + `docker restart`; no rebuild);
893
+ Dockerfile / dependency manifest / compiled-language source edits fall
894
+ through to a full rebuild + shadow boot + atomic swap.
895
+
896
+ ### `local start-alb`
897
+
898
+ ```bash
899
+ cdkd local start-alb MyStack/MyAlb --lb-port 80=8080 # remap privileged listener port
900
+ cdkd local start-alb MyStack/MyAlb --from-state # OR --from-cfn-stack
901
+ cdkd local start-alb MyStack/MyAlb --watch # hot reload (sub-second on interpreted handlers)
902
+ ```
903
+
904
+ Long-running local ALB front-door: names an `AWS::ElasticLoadBalancingV2::LoadBalancer`,
905
+ boots every ECS service behind its listeners, and stands up a local
906
+ HTTP / HTTPS front-door on each listener port that round-robins across
907
+ the running replicas and routes its listener rules across the backing
908
+ services. Forward / redirect / fixed-response actions; ECS or Lambda
909
+ targets; authenticate-cognito / authenticate-oidc via a local Bearer-JWT
910
+ check. `--watch` reloads one backing-replica at a time across edits —
911
+ interpreted-handler source edits go through the bind-mount fast path
912
+ (no rebuild); Dockerfile / dependency / compiled-source edits fall
913
+ through to a rebuild + atomic front-door pool swap.
914
+
915
+ ### `local start-cloudfront`
916
+
917
+ ```bash
918
+ cdkd local start-cloudfront # interactive picker
919
+ cdkd local start-cloudfront MyStack/MyDistribution # name the distribution
920
+ cdkd local start-cloudfront MyStack/MyDistribution --watch # re-synth + swap on edit
921
+ cdkd local start-cloudfront MyStack/MyDistribution --tls # real HTTPS termination
922
+ ```
923
+
924
+ Serves a CloudFront distribution's **viewer-request -> S3 origin ->
925
+ viewer-response** pipeline locally so a routing-function change is
926
+ verifiable in seconds instead of a deploy round-trip. The distribution's
927
+ `AWS::CloudFront::Function`s (URL rewrites, trailing-slash normalization,
928
+ SPA fallback, header tweaks) run in-process in a `node:vm` sandbox; the
929
+ S3 origin content is the `BucketDeployment` source asset resolved out of
930
+ the cloud assembly, served with `DefaultRootObject` and
931
+ `CustomErrorResponses`. Path patterns route across the default + ordered
932
+ cache behaviors. Pure-local: no Docker, no AWS call — `--watch` is just
933
+ re-synth + an in-memory routing-model swap. S3 origins only (custom /
934
+ Lambda@Edge origins are warn-and-skip); `--origin <id>=<dir>` points an
935
+ origin at a local directory when `BucketDeployment` resolution can't.
936
+
937
+ See **[docs/local-emulation.md](docs/local-emulation.md)** for the
938
+ full reference — runtimes, target resolution, every flag, integration
939
+ and authorizer detail, route precedence, container pool, networking,
940
+ `--from-cfn-stack` semantics, v1 scope.
941
+
852
942
  ## License
853
943
 
854
944
  Apache 2.0
@@ -1,4 +1,4 @@
1
- import { An as __exportAll, B as disableInstanceApiTermination, F as clearOnUpdateRemoval, J as assertRegionMatch, K as normalizeAwsTagsToCfn, xn as ResourceUpdateNotSupportedError, yn as ProvisioningError } from "./deploy-engine-DYDL4JxX.js";
1
+ import { An as __exportAll, B as disableInstanceApiTermination, F as clearOnUpdateRemoval, J as assertRegionMatch, K as normalizeAwsTagsToCfn, xn as ResourceUpdateNotSupportedError, yn as ProvisioningError } from "./deploy-engine-DjdMx6fC.js";
2
2
  import { n as getLogger, u as generateResourceName } from "./logger-zRrlbaQt.js";
3
3
  import { EC2Client } from "@aws-sdk/client-ec2";
4
4
  import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
@@ -810,4 +810,4 @@ function mapNotificationsToCfn(configurations) {
810
810
 
811
811
  //#endregion
812
812
  export { asg_provider_exports as n, ASGProvider as t };
813
- //# sourceMappingURL=asg-provider-Gk-TB9L0.js.map
813
+ //# sourceMappingURL=asg-provider-CL2zlhEi.js.map