You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/changelog-cdkd.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,6 +45,7 @@ The CLAUDE.md `## Known Limitations` section retains the load-bearing summary
45
45
-**`cdkd events` no longer mislabels a successful run as `FAILED` in the index-fallback** (user-visible correctness fix). When `deployments/index.json` is missing / corrupt, `DeploymentEventsReader.listRuns` rebuilds the run listing by enumerating the `{runId}.jsonl` keys. It previously stamped every fallback row `result: 'FAILED'` — so a run that genuinely SUCCEEDED but whose `index.json` write lost the last-writer-wins race showed as `FAILED`. The fallback now reads each run's JSONL and derives the true terminal result (command / cdkd version / timestamps / event count too) from the run's last `RUN_FINISHED` event; a run with no terminal `RUN_FINISHED` (interrupted, or index write lost) reports the new `result: 'UNKNOWN'` (added to a `DeploymentRunSummaryResult = DeploymentRunResult | 'UNKNOWN'` type used only on the summary; the run-level emitters still only ever produce `SUCCEEDED` / `FAILED`) and is colored neutrally in the run listing rather than red.
46
46
-**Run-level bracket extracted to `src/cli/commands/deployment-events-run.ts`** (`startRunRecorder` / `recordRunSucceeded` / `recordRunFailed`) so the `RUN_STARTED` / `RUN_FINISHED` + `--dry-run`-skips-recorder + `extractDeploymentEventError`-on-failure contract is directly unit-testable and shared by both `deploy.ts` and `destroy.ts` (behavior identical to the prior inline code).
47
47
- Added tests: `tests/unit/types/deployment-events.test.ts` (`extractDeploymentEventError` deepest-AWS-shaped-error extraction, bounded-depth-10 + cyclic-chain guard, non-Error inputs), `tests/unit/cli/destroy-runner-events.test.ts` (destroy-runner `RESOURCE_STARTED` / `SUCCEEDED` / `FAILED` + `RESOURCE_RETAINED` for a `DeletionPolicy: Retain` skip + no-recorder back-compat), `tests/unit/cli/deployment-events-run.test.ts` (run-level bracket: dry-run = no recorder, `RUN_STARTED` at create, success `RUN_FINISHED` with counts, failure `RUN_FINISHED` with `result: 'FAILED'` + error metadata, no-properties-leak), a `ROLLBACK_RESOURCE_FAILED` case in `deployment-events-emission.test.ts`, the no-FAILED-fabrication + `UNKNOWN`-on-torn cases in `deployment-events-store.test.ts`, and a `listRawKeys` multi-page `ContinuationToken` pagination case in `tests/unit/state/s3-state-backend.test.ts`.
48
+
- **Integration coverage (follow-up PR, refs #808)**: new `tests/integration/deployment-events/` fixture — a tiny `CdkdDeploymentEventsExample` stack (an `AWS::SNS::Topic` + an `AWS::SSM::Parameter`, no VPC / NAT, deploy+destroy in well under a minute) with a `verify.sh` that exercises the feature end-to-end against real AWS: deploy writes the `deployments/{runId}.jsonl` + `index.json` sidecar; `cdkd events <stack> --stack-region <r>` lists a `deploy` run as `SUCCEEDED`; `--format json` is valid JSON carrying `RUN_STARTED` / `RUN_FINISHED` + at least one `RESOURCE_*` event for the topic / parameter; the SSM parameter's marker value (`events-integ-secret-value`) does NOT appear anywhere in the events JSON (the no-secrets guarantee); after `cdkd destroy --force`, `state.json` is gone but the `deployments/` sidecar survives (now carrying the destroy run too) and `cdkd events` lists BOTH a deploy and a destroy run; the fixture removes the events sidecar at the end (and on the failure path via an EXIT trap). New scenario tag `deployment-events`.
48
49
- ✅ **`LockManager` resolves the state bucket's actual region before lock operations (issue [#803](https://github.com/go-to-k/cdkd/issues/803))** — `src/state/lock-manager.ts`. PR #60 taught `S3StateBackend` to resolve a cross-region state bucket's real region via `GetBucketLocation` and rebuild its S3 client, but `LockManager` was left out: it kept using the raw client pinned to the CLI's base region (`AWS_REGION` / fallback `us-east-1`), so against a bucket in another region every state read/write succeeded while every lock acquisition failed with S3's 301 PermanentRedirect ("must be addressed using the specified endpoint") — contradicting the documented "the state bucket can live in any AWS region" guarantee. `LockManager` now has its own `ensureClientForBucket()` (awaited at the top of `acquireLock` / `getLockInfo` / `releaseLock` / `deleteLock`) mirroring the state backend's pattern with two deliberate differences: the replacement client reuses the original client's resolved credentials provider (so `--profile` / static credentials carry over without threading client options through the 8 `new LockManager(...)` call sites), and the original client is NOT destroyed (it is the shared `AwsClients.s3` instance other components still hold). `resolveBucketRegion` caches per bucket name, so when the state backend already resolved the same bucket the lock path adds no extra `GetBucketLocation` call. The fix is contained entirely inside `LockManager` — none of the 8 call sites changed. Unit tests: region-mismatch rebuild (pre-fix 301 path — the PutObject goes through the rebuilt client), same-region no-rebuild, single resolution across multiple lock ops, and resolver receives the caller's credentials + fallback region. The `cross-region-state-bucket` integ fixture is now AUTOMATED: its new `verify.sh` creates a temporary uniquely-named state bucket in `us-west-2`, runs deploy / state ls / destroy with `AWS_REGION=us-east-1`, asserts state.json written + lock.json released in the cross-region bucket, and deletes the bucket at the end (EXIT trap covers failure paths) — previously the fixture was manual-only and its 2026-06-02 ledger PASS ran against the default same-region bucket, never exercising the scenario it is named after. Docs: `state-management.md` (State Bucket Region + Lock Mechanism), `troubleshooting.md` (lock-path 301 symptom + fix note).
0 commit comments