Why is it so infuriatingly hard to deploy lambdas with terraform using codepipeline\codedeploy

From what I can tell using the terraform archive_file within codebuild (pretty sure because of getting new timestamps) the zip files will hash differently each time. From what I can tell most people .zip their lambdas during the build process anyways, after linting etc.. so they don’t recommend using terraform for the zipping… I spent way too much time trying to get it to work anyways… cause I’m like bashing my head on problems I guess.

Anyways, this article recommends

View at Medium.com

In order to deploy updated Lambda function code when it is available and preventing unnecessary uploads, we need to re-process the data.archive_file source only when the source files (and only the relevant ones) have been modified.

A convenient way to do that is to set the ZIP file name to a “random UUID” and tie it to a hash of the actual source code files:

This didn’t work for me though….

This article says,

https://poznyakovskiy.medium.com/aws-lambda-and-terraform-a-fully-automated-deployment-pipeline-c5e3e520455c

Terraform provides the attribute source_code_hash to detect changes to the Lambda function code and update the Lambda. It expects a SHA256 hash of the zipfile with the code which we pass via aws_s3_bucket_object . This resource could provide access to the zipfile and return its checksum, but there is a catch: Terraform returns the MD5 checksum which, passed as the code hash, would trigger a rebuild every time. So, we build the SHA256 hash via command line and upload it alongside the zipfile as a file named lambda.zip.sha256.

This almost worked for me, but I was still getting hash changes so fixed it like this

- echo "set the filestamp the same"
- find folder/function/code -exec touch -t 201301250000 {} +
- zip -rq -D -X -9 -j app.zip folder/function/code/app.py
- touch -t 201301250000 {} + app.zip
- openssl dgst -sha256 -binary app.zip | openssl enc -base64 > app.zip.sha256

Basically set everything to the same date, zip it (-j junks the path so the lambda is unzipped correctly) and then set the timestamp on the zip before hashing

Then inside the terraform itself

data "aws_s3_object" "source_hash" {
  bucket                  = local.lambda_bucket_name
  key                     = "${local.lambda_s3_key}.sha256"
}

resource "aws_lambda_function" "send-msg_lambdafunc" {
  s3_bucket         = local.lambda_bucket_name
  s3_key            = local.lambda_s3_key
  source_code_hash = chomp(data.aws_s3_object.source_hash.body)

Reference it using an aws_s3_object (new style) the final trick is to chomp the value store in the .sha256 (because it has a linefeed which of course screws up the hash compare.)

Leave a comment