2

How to run npm ci from Terraform

 2 years ago
source link: https://advancedweb.hu/how-to-run-npm-ci-from-terraform/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

NPM dependencies in Lambda

You can define Lambda code inline in an archive_file data source, but that works only for simple functions without any dependencies. For anything more serious, you’ll need a package.json and npm to install third-party libraries.

But then, before you upload the code to AWS you need to run npm ci. Terraform’s archive_file does little to help here: it’s a dumb construct that zips anything that happens to be in the source directory. Which, if you forgot to install the dependencies breaks the function.

How to make Terraform run npm ci automatically?

Running external programs

Terraform supports the external data source that provides support for arbitrary commands. This allows complex builds to run as part of the deploy process.

Related
Static files are easy to deploy with Terraform. But what about compiled apps?

We write articles like this regularly. Join our mailing list and let's keep in touch.

But npm ci is needed only occassionally, so if it’s run every time you run terraform apply or terraform plan, it slows down all deployments considerably.

Fortunately, both the node_modules and the package-lock.json have a modification timestamp. npm ci is only needed if the time of the node_modules is earlier than the time of package-lock.json. And this is exactly what make supports.

Create a makefile that has a node_modules target that depends on package-lock.json:

# Makefile

node_modules: package-lock.json
	npm ci

In the Terraform config, run make node_modules:

# main.tf

data "external" "build" {
	program = ["bash", "-c", <<EOT
(make node_modules) >&2 && echo "{\"dest\": \".\"}"
EOT
	]
	working_dir = "${path.module}/src"
}

data "archive_file" "lambda_zip" {
	type        = "zip"
	output_path = "/tmp/lambda-${random_id.id.hex}.zip"
	source_dir  = "${data.external.build.working_dir}/${data.external.build.result.dest}"
}

resource "aws_lambda_function" "lambda" {
	# ...
	filename         = data.archive_file.lambda_zip.output_path
	source_code_hash = data.archive_file.lambda_zip.output_base64sha256
}

Note the result value of the external build ({dest: "."}) and the source_dir argument of the archive_file. This defines an implicit dependency between the two, so the dependencies are guaranteed to be installed when the archive_file zips the folder.


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK