@go-to-k/cdkd 0.35.0 → 0.36.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
@@ -376,6 +376,30 @@ cdkd state destroy MyStack --region us-east-1
376
376
  > `cdkd destroy` (synth-driven, deletes AWS resources + state) and
377
377
  > `cdkd state destroy` (state-driven, same effect) round out the matrix.
378
378
 
379
+ ## `publish-assets`: synth + build + publish, no deploy
380
+
381
+ `cdkd publish-assets` runs the asset half of the deploy pipeline only —
382
+ synthesize the CDK app, build any Docker images, upload file assets to
383
+ S3, push images to ECR — and stops. No state writes, no provisioning,
384
+ no lock acquisition. This is the typical CI split where one runner
385
+ builds and uploads assets and a separate runner deploys.
386
+
387
+ ```bash
388
+ cdkd publish-assets # synth + publish all stacks (or auto-detect single stack)
389
+ cdkd publish-assets MyStack # synth + publish a specific stack
390
+ cdkd publish-assets --all # synth + publish every stack in the app
391
+ cdkd publish-assets 'MyStage/*' # wildcard (CDK display path)
392
+ cdkd publish-assets -a cdk.out # skip synth — use a pre-synthesized cloud assembly
393
+ ```
394
+
395
+ Stack selection follows the same rules as `deploy` / `diff` / `destroy`
396
+ (positional > `--stack` > `--all` > auto-detect). Concurrency knobs
397
+ are `--asset-publish-concurrency` and `--image-build-concurrency`.
398
+ `-a/--app` accepts either a shell command (`"npx ts-node app.ts"`) or
399
+ a path to an already-synthesized cloud assembly directory; pointing at
400
+ `cdk.out` skips synthesis. See [docs/cli-reference.md](docs/cli-reference.md#publish-assets-synth--build--publish-no-deploy)
401
+ for details.
402
+
379
403
  ## `--no-wait`: skip async-resource waits
380
404
 
381
405
  CloudFront Distributions, RDS Clusters/Instances, ElastiCache, and
package/dist/cli.js CHANGED
@@ -34967,26 +34967,158 @@ function createOrphanCommand() {
34967
34967
 
34968
34968
  // src/cli/commands/publish-assets.ts
34969
34969
  import { Option as Option4, Command as Command9 } from "commander";
34970
- async function publishAssetsCommand(options) {
34970
+ async function publishAssetsCommand(stacks, options) {
34971
34971
  const logger = getLogger();
34972
34972
  if (options.verbose) {
34973
34973
  logger.setLevel("debug");
34974
34974
  }
34975
34975
  warnIfDeprecatedRegion(options);
34976
34976
  await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
34977
- logger.info("Publishing assets...");
34978
- logger.debug("Asset manifest path:", options.path);
34979
- const publisher = new AssetPublisher();
34980
- await publisher.publishFromManifest(options.path, {
34981
- ...options.profile && { profile: options.profile },
34977
+ const app = resolveApp(options.app);
34978
+ if (!app) {
34979
+ throw new Error(
34980
+ 'No app command specified. Use --app, set CDKD_APP env var, or add "app" to cdk.json'
34981
+ );
34982
+ }
34983
+ logger.info("Synthesizing CDK app...");
34984
+ const synthesizer = new Synthesizer();
34985
+ const context = parseContextOptions(options.context);
34986
+ const synthOptions = {
34987
+ app,
34988
+ output: options.output,
34982
34989
  ...options.region && { region: options.region },
34983
- assetPublishConcurrency: options.assetPublishConcurrency,
34984
- imageBuildConcurrency: options.imageBuildConcurrency
34985
- });
34986
- logger.info("\u2705 Asset publishing complete");
34990
+ ...options.profile && { profile: options.profile },
34991
+ ...Object.keys(context).length > 0 && { context }
34992
+ };
34993
+ const result = await synthesizer.synthesize(synthOptions);
34994
+ const { stacks: allStacks } = result;
34995
+ logger.debug(`Found ${allStacks.length} stack(s) in assembly`);
34996
+ const stackPatterns = stacks.length > 0 ? stacks : options.stack ? [options.stack] : [];
34997
+ let targetStacks;
34998
+ if (options.all) {
34999
+ targetStacks = allStacks;
35000
+ } else if (stackPatterns.length > 0) {
35001
+ targetStacks = matchStacks(allStacks, stackPatterns);
35002
+ } else if (allStacks.length === 1) {
35003
+ targetStacks = allStacks;
35004
+ } else {
35005
+ throw new Error(
35006
+ `Multiple stacks found: ${allStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`
35007
+ );
35008
+ }
35009
+ if (targetStacks.length === 0) {
35010
+ throw new Error(
35011
+ stackPatterns.length > 0 ? `No stacks matching ${stackPatterns.join(", ")} found in assembly. Available: ${allStacks.map(describeStack).join(", ")}` : "No stacks found in assembly"
35012
+ );
35013
+ }
35014
+ const baseRegion = options.region || process.env["AWS_REGION"] || "us-east-1";
35015
+ const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
35016
+ const stsClient = new STSClient10({ region: baseRegion });
35017
+ const callerIdentity = await stsClient.send(new GetCallerIdentityCommand11({}));
35018
+ const accountId = callerIdentity.Account;
35019
+ stsClient.destroy();
35020
+ const assetPublisher = new AssetPublisher();
35021
+ const results = [];
35022
+ for (const stack of targetStacks) {
35023
+ const startedAt = Date.now();
35024
+ let assetCount = 0;
35025
+ let error;
35026
+ try {
35027
+ if (!stack.assetManifestPath) {
35028
+ logger.debug(`Stack ${stack.stackName} has no asset manifest; nothing to publish`);
35029
+ results.push({
35030
+ stackName: stack.stackName,
35031
+ displayName: stack.displayName,
35032
+ assetCount: 0,
35033
+ durationMs: Date.now() - startedAt
35034
+ });
35035
+ continue;
35036
+ }
35037
+ logger.info(`
35038
+ Publishing assets for stack: ${describeStack(stack)}`);
35039
+ const workGraph = new WorkGraph();
35040
+ let nodeIds = [];
35041
+ try {
35042
+ nodeIds = assetPublisher.addAssetsToGraph(workGraph, stack.assetManifestPath, {
35043
+ accountId,
35044
+ region: stack.region || baseRegion,
35045
+ ...options.profile && { profile: options.profile },
35046
+ nodePrefix: `${stack.stackName}:`
35047
+ });
35048
+ } catch (err) {
35049
+ const e = err;
35050
+ if (e.code === "ENOENT") {
35051
+ logger.debug(
35052
+ `Asset manifest not found for ${stack.stackName} (${stack.assetManifestPath}); skipping`
35053
+ );
35054
+ results.push({
35055
+ stackName: stack.stackName,
35056
+ displayName: stack.displayName,
35057
+ assetCount: 0,
35058
+ durationMs: Date.now() - startedAt
35059
+ });
35060
+ continue;
35061
+ }
35062
+ throw err;
35063
+ }
35064
+ assetCount = nodeIds.filter((id) => id.startsWith("asset-publish:")).length;
35065
+ if (assetCount === 0) {
35066
+ logger.info(" (no assets to publish)");
35067
+ results.push({
35068
+ stackName: stack.stackName,
35069
+ displayName: stack.displayName,
35070
+ assetCount: 0,
35071
+ durationMs: Date.now() - startedAt
35072
+ });
35073
+ continue;
35074
+ }
35075
+ await workGraph.execute(
35076
+ {
35077
+ "asset-build": options.imageBuildConcurrency,
35078
+ "asset-publish": options.assetPublishConcurrency,
35079
+ stack: 0
35080
+ },
35081
+ (node) => assetPublisher.executeNode(node)
35082
+ );
35083
+ logger.info(
35084
+ ` \u2713 Published ${assetCount} asset(s) in ${((Date.now() - startedAt) / 1e3).toFixed(2)}s`
35085
+ );
35086
+ } catch (err) {
35087
+ error = err instanceof Error ? err : new Error(String(err));
35088
+ logger.error(` \u2717 ${stack.stackName}: ${error.message}`);
35089
+ }
35090
+ results.push({
35091
+ stackName: stack.stackName,
35092
+ displayName: stack.displayName,
35093
+ assetCount,
35094
+ durationMs: Date.now() - startedAt,
35095
+ ...error && { error }
35096
+ });
35097
+ }
35098
+ const failed = results.filter((r) => r.error);
35099
+ const totalAssets = results.reduce((sum, r) => sum + r.assetCount, 0);
35100
+ logger.info("\nPublish Summary:");
35101
+ for (const r of results) {
35102
+ const tag = r.error ? "\u2717" : "\u2713";
35103
+ const id = r.displayName === r.stackName ? r.stackName : `${r.displayName} (${r.stackName})`;
35104
+ const detail = r.error ? `failed: ${r.error.message}` : `${r.assetCount} asset(s), ${(r.durationMs / 1e3).toFixed(2)}s`;
35105
+ logger.info(` ${tag} ${id} \u2014 ${detail}`);
35106
+ }
35107
+ if (failed.length > 0) {
35108
+ throw new PartialFailureError(
35109
+ `Asset publishing completed with ${failed.length} stack failure(s) (${totalAssets} asset(s) published successfully across the rest).`
35110
+ );
35111
+ }
35112
+ logger.info(`
35113
+ \u2705 Asset publishing complete (${totalAssets} asset(s))`);
34987
35114
  }
34988
35115
  function createPublishAssetsCommand() {
34989
- const cmd = new Command9("publish-assets").description("Publish assets to S3/ECR from asset manifest").requiredOption("--path <path>", "Path to asset manifest file or directory").addOption(
35116
+ const cmd = new Command9("publish-assets").description(
35117
+ "Synthesize the CDK app and publish assets to S3/ECR for the selected stack(s) without deploying"
35118
+ ).argument(
35119
+ "[stacks...]",
35120
+ "Stack name(s) to publish assets for. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards."
35121
+ ).option("--all", "Publish assets for all stacks", false).addOption(
34990
35122
  new Option4(
34991
35123
  "--asset-publish-concurrency <number>",
34992
35124
  "Maximum concurrent asset publish operations"
@@ -34994,7 +35126,8 @@ function createPublishAssetsCommand() {
34994
35126
  ).addOption(
34995
35127
  new Option4("--image-build-concurrency <number>", "Maximum concurrent Docker image builds").default(4).argParser((value) => parseInt(value, 10))
34996
35128
  ).action(withErrorHandling(publishAssetsCommand));
34997
- commonOptions.forEach((opt) => cmd.addOption(opt));
35129
+ [...commonOptions, ...appOptions, ...contextOptions].forEach((opt) => cmd.addOption(opt));
35130
+ cmd.addOption(new Option4("--stack <name>", "Stack name to publish (alternative to positional)"));
34998
35131
  cmd.addOption(deprecatedRegionOption);
34999
35132
  return cmd;
35000
35133
  }
@@ -36849,7 +36982,7 @@ function reorderArgs(argv) {
36849
36982
  }
36850
36983
  async function main() {
36851
36984
  const program = new Command14();
36852
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.35.0");
36985
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.36.0");
36853
36986
  program.addCommand(createBootstrapCommand());
36854
36987
  program.addCommand(createSynthCommand());
36855
36988
  program.addCommand(createListCommand());