So you created a Lambda function via aws-cdk. The first deploy worked fine and you were able to try the function. When attempting to deploy an update of the function, no changes are deployed. The output of the cdk diff command says “There were no differences”.

When using the aws-cdk Lambda docs and examples, the code for the Lambda function is fetched by lambda.Code.fromAsset() This is from a local directory within the cdk project and works as expected because the cdk is able to calculate a hash of the files to detect a change in the code.

My GitHub Actions workflow was pushing zip files to S3 containing the code for the Lambda functions. This meant that I use lambda.Code.fromBucket.

Something like this:


// bucket is of type Bucket construct from aws-cdk/aws-s3 package.

// This is path of the release zip file in s3.
const releaseFileKey = "my-function/latest.zip"

const fn = new lambda.Function(this, 'MyFunction', {
  runtime: lambda.Runtime.NODEJS_14_X,
  handler: 'handler.hello',
  code: lambda.Code.fromBucket(bucket, releaseFileKey)
})

cdk would not detect updates to the lambda function. There are some notes in the cdk documentation that mentions passing the version options to inform cdk that an update is being made.

I was looking for a mechanism to be able to pass the version of the lambda function to deploy, to the cdk deploy command. I definitely do not want to be updating the s3 release file name in the stack definitions manually everytime I want to deploy.

I stumbled upon CfnParameters. This can be used to pass parameters to the cdk on the command line.

I made some code changes to read releaseFileKey using CfnParameter. Here is how I would pass the release file key in the command line.

$ cdk deploy MyAppStack \
    --parameter MyAppStack:releaseFileKey=my-function/3badf1b7.zip

Nope - that did not work. The Lambda function still wasn’t being updated when I passed a new file key that included the git commit SHA in the file name. When I opened the CloudFormation templates in cdk.out dir, I noticed that the places where I was expected to see the release file key, there was something like {"ref": "releaseFileKey"}.

I learnt that these CfnParameters are CloudFormation parameters that are injected during deploy time. The CloudFormation templates generated by cdk would always have placeholders for these parameters and therefore the cdk would not detect any changes to deploy.

Solutions that worked

Option-1: Read the S3 file key from environment variables

const fn = new lambda.Function(this, 'MyFunction', {
  runtime: lambda.Runtime.NODEJS_14_X,
  handler: 'handler.hello',
  code: lambda.Code.fromBucket(bucket, process.env.RELEASE_FILE)
})

Run the diff command now and you’ll notice cdk is detecting changes to the stack and will update the Lambda function.

RELEASE_FILE="my-function/3badf1b7.zip" cdk diff --all

Option-2: Add the code version as an env var that is passed to the Lambda function

Incase your S3 file name always remains the same, then the other option is to pass some environment variable to your Lambda function that always changes when your code changes.

The easy way is to pass the git commit SHA like below.

const fn = new lambda.Function(this, 'MyFunction', {
  runtime: lambda.Runtime.NODEJS_14_X,
  handler: 'handler.hello',
  code: lambda.Code.fromBucket(bucket, "my-function/latest.zip")
  environment: {
    GIT_VERSION: process.env.RELEASE_VERSION
  }
})

And then pass the env var to the diff or deploy commands like this.

RELEASE_VERSION="3badf1b7" cdk diff --all

Option-3: Pass version options to lambda.Function

You can also pass the version options to lambda.Function like below. But it is required that you access the currentVersion property after the lambda function is declared. This ensures that the version is output to the CloudFormation template. Notice the last line in the snippet below.

If you notice below, the snippet still reads the release version from an env var.

const fn = new lambda.Function(this, 'MyFunction', {
  runtime: lambda.Runtime.NODEJS_14_X,
  handler: 'handler.hello',
  code: lambda.Code.fromBucket(bucket, "my-function/latest.zip")
  currentVersionOptions: {
    codeSha256: process.env.RELEASE_VERSION
  }
})

fn.currentVersion

Try running the cdk diff or deploy commands with RELEASE_VERSION env var.

RELEASE_VERSION="3badf1b7" cdk diff --all