For all my funsies projects (except the Rust ones), I use pantsbuild to build and deploy my code. It’s a great tool, and but its separation between artifacts requires that CDK code be run during the build step.

Artifacts that contain multiple files to be output in the pants package need to be archives. For my use case, I have a single Python file that builds every CDK stack and merges them into a single Cloud Assembly. For example, here is a simplified build file:

# take the CDK python script and package it into a PEX file
python_source(name="stacks", source="bin/", dependencies=["//project1:stacks", "//project2:stacks"])

# run the earlier pex file to build the CloudASM
    # build cloud assembly zip given the cdk.json and stack objects
    tools=["node", "python3.10"],
    command="./cdkapp.pex .",
# zip the CloudASM into a package artifact
archive(name="cloudasm", format="zip", files=[":cdk"])

This will create a dist/ file that contains all the files needed to deploy the CDK stacks. The CDK CLI can deploy CloudASM without running any of your application code. By default, the tree of templates and artifacts (Lambda zips, etc) are stored in the cdk.out directory. Usually CloudASM is used like this:

cdk deploy --app cdk.out Project1

This reads the already-rendered template without re-running your CDK code. However, because we have the CloudASM in a zip file that doesn’t quite work. We need to extract the CloudASM from the zip file and then run the cdk command. Here’s a simple bash script that does that:

#!/usr/bin/env bash
set -euo pipefail

if [[ ! -f "${1}" ]] ; then
  echo "Could not find cloudassembly zip '${1}'"
  exit 1

DIR=$(mktemp -d -t cloudasm)

unzip -q -d "${DIR}" "${1}" 1>&2

echo "${DIR}"

With this script in build-support, we can run the CDK command like this:

cdk deploy -a "$(build-support/ ./dist/"

The same script is also useful if you’ve got approval steps in your deployment pipeline, or want to keep artifacts to enable rollbacks. If you have a pipeline that doesn’t save artifacts it’s worth considering adding a step to have a history of past deploys for troubleshooting.