From 4b42c69412bd1e696e426721ea43d1d62da58e96 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 13:41:44 +0000 Subject: [PATCH 01/43] chore: use _shared folder --- infra/modules/aws/{ => _shared}/lambda/data.tf | 0 infra/modules/aws/{ => _shared}/lambda/locals.tf | 0 infra/modules/aws/{ => _shared}/lambda/main.tf | 0 infra/modules/aws/{ => _shared}/lambda/outputs.tf | 0 infra/modules/aws/{ => _shared}/lambda/variables.tf | 0 infra/modules/aws/api/main.tf | 2 +- 6 files changed, 1 insertion(+), 1 deletion(-) rename infra/modules/aws/{ => _shared}/lambda/data.tf (100%) rename infra/modules/aws/{ => _shared}/lambda/locals.tf (100%) rename infra/modules/aws/{ => _shared}/lambda/main.tf (100%) rename infra/modules/aws/{ => _shared}/lambda/outputs.tf (100%) rename infra/modules/aws/{ => _shared}/lambda/variables.tf (100%) diff --git a/infra/modules/aws/lambda/data.tf b/infra/modules/aws/_shared/lambda/data.tf similarity index 100% rename from infra/modules/aws/lambda/data.tf rename to infra/modules/aws/_shared/lambda/data.tf diff --git a/infra/modules/aws/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf similarity index 100% rename from infra/modules/aws/lambda/locals.tf rename to infra/modules/aws/_shared/lambda/locals.tf diff --git a/infra/modules/aws/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf similarity index 100% rename from infra/modules/aws/lambda/main.tf rename to infra/modules/aws/_shared/lambda/main.tf diff --git a/infra/modules/aws/lambda/outputs.tf b/infra/modules/aws/_shared/lambda/outputs.tf similarity index 100% rename from infra/modules/aws/lambda/outputs.tf rename to infra/modules/aws/_shared/lambda/outputs.tf diff --git a/infra/modules/aws/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf similarity index 100% rename from infra/modules/aws/lambda/variables.tf rename to infra/modules/aws/_shared/lambda/variables.tf diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 3dd7cb9..4f9cf63 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -1,5 +1,5 @@ module "lambda_api" { - source = "../lambda" + source = "../_shared/lambda" project_name = var.project_name environment = var.environment From d79d9c333da093cbf5c9d0e5d26062f22b6a68ff Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 13:46:42 +0000 Subject: [PATCH 02/43] chore: sqs module --- infra/modules/aws/_shared/sqs/data.tf | 24 ++++++++++++++++++++++ infra/modules/aws/_shared/sqs/main.tf | 16 +++++++++++++++ infra/modules/aws/_shared/sqs/outputs.tf | 15 ++++++++++++++ infra/modules/aws/_shared/sqs/variables.tf | 3 +++ 4 files changed, 58 insertions(+) create mode 100644 infra/modules/aws/_shared/sqs/data.tf create mode 100644 infra/modules/aws/_shared/sqs/main.tf create mode 100644 infra/modules/aws/_shared/sqs/outputs.tf create mode 100644 infra/modules/aws/_shared/sqs/variables.tf diff --git a/infra/modules/aws/_shared/sqs/data.tf b/infra/modules/aws/_shared/sqs/data.tf new file mode 100644 index 0000000..87c2f8e --- /dev/null +++ b/infra/modules/aws/_shared/sqs/data.tf @@ -0,0 +1,24 @@ +data "aws_iam_policy_document" "sqs_read" { + statement { + effect = "Allow" + actions = [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:ChangeMessageVisibility" + ] + resources = [aws_sqs_queue.queue.arn] + } +} + +data "aws_iam_policy_document" "sqs_write" { + statement { + effect = "Allow" + actions = [ + "sqs:SendMessage", + "sqs:SendMessageBatch", + "sqs:GetQueueAttributes" + ] + resources = [aws_sqs_queue.queue.arn] + } +} diff --git a/infra/modules/aws/_shared/sqs/main.tf b/infra/modules/aws/_shared/sqs/main.tf new file mode 100644 index 0000000..2d59ae2 --- /dev/null +++ b/infra/modules/aws/_shared/sqs/main.tf @@ -0,0 +1,16 @@ +resource "aws_sqs_queue" "queue" { + name = var.sqs_queue_name + delay_seconds = 0 + message_retention_seconds = 86400 + receive_wait_time_seconds = 10 +} + +resource "aws_iam_policy" "queue_read_policy" { + name = "${var.sqs_queue_name}-sqs-read-policy" + policy = data.aws_iam_policy_document.sqs_read.json +} + +resource "aws_iam_policy" "queue_write_policy" { + name = "${var.sqs_queue_name}-sqs-write-policy" + policy = data.aws_iam_policy_document.sqs_write.json +} diff --git a/infra/modules/aws/_shared/sqs/outputs.tf b/infra/modules/aws/_shared/sqs/outputs.tf new file mode 100644 index 0000000..a731422 --- /dev/null +++ b/infra/modules/aws/_shared/sqs/outputs.tf @@ -0,0 +1,15 @@ +output "sqs_queue_name" { + value = aws_sqs_queue.queue.name +} + +output "sqs_queue_url" { + value = aws_sqs_queue.queue.url +} + +output "sqs_queue_read_policy_arn" { + value = aws_iam_policy.queue_read_policy.arn +} + +output "sqs_queue_write_policy_arn" { + value = aws_iam_policy.queue_write_policy.arn +} diff --git a/infra/modules/aws/_shared/sqs/variables.tf b/infra/modules/aws/_shared/sqs/variables.tf new file mode 100644 index 0000000..13661c6 --- /dev/null +++ b/infra/modules/aws/_shared/sqs/variables.tf @@ -0,0 +1,3 @@ +variable "sqs_queue_name" { + type = string +} From fd18e6210a4f43e07748816d83c6a036593269e6 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 15:22:02 +0000 Subject: [PATCH 03/43] feat: var for reserved --- infra/modules/aws/_shared/lambda/locals.tf | 6 ++++-- infra/modules/aws/_shared/lambda/main.tf | 6 ++++-- infra/modules/aws/_shared/lambda/variables.tf | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index efdb97e..c81aaf0 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -1,6 +1,7 @@ locals { - lambda_runtime = "python3.12" - lambda_handler = "lambda_handler.lambda_handler" + lambda_runtime = "python3.12" + lambda_handler = "lambda_handler.lambda_handler" + compute_platform = "Lambda" lambda_name = "${var.environment}-${var.project_name}-${var.lambda_name}" lambda_code_zip_key = "${var.lambda_version}/${var.lambda_name}.zip" @@ -22,6 +23,7 @@ locals { fixed_mode = try(var.provisioned_config.fixed != null, true) pc_fixed_count = try(var.provisioned_config.fixed, 0) + pc_reserved_count = try(var.provisioned_config.reserved, 0) pc_min_capacity = try(var.provisioned_config.auto_scale.min, 0) pc_max_capacity = try(var.provisioned_config.auto_scale.max, 0) pc_trigger_percent = try(var.provisioned_config.auto_scale.trigger_percent, var.provisioned_config_defaults.trigger_percent) / 100 diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index e9301a0..0ce05fd 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -9,6 +9,8 @@ resource "aws_lambda_function" "lambda" { handler = local.lambda_handler runtime = local.lambda_runtime + reserved_concurrent_executions = local.pc_reserved_count + s3_bucket = data.aws_s3_bucket.lambda_code.bucket s3_key = local.lambda_code_zip_key @@ -53,7 +55,7 @@ resource "aws_lambda_provisioned_concurrency_config" "alias_pc_fixed" { resource "aws_codedeploy_app" "app" { name = "${local.lambda_name}-app" - compute_platform = "Lambda" + compute_platform = local.compute_platform } resource "aws_iam_role" "code_deploy_role" { @@ -69,7 +71,7 @@ resource "aws_iam_role_policy" "cd_lambda" { resource "aws_codedeploy_deployment_config" "lambda_config" { deployment_config_name = "${local.lambda_name}-deploy-config" - compute_platform = "Lambda" + compute_platform = local.compute_platform traffic_routing_config { type = local.deploy_config.type diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 1fc9b64..942b59d 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -77,7 +77,9 @@ variable "provisioned_config_defaults" { variable "provisioned_config" { description = "Either fixed provisioned concurrency (fixed) or autoscaled (auto_scale); omit/zero = none" type = object({ - fixed = optional(number) # 0/omit = off, >0 = fixed PC + fixed = optional(number) # 0/omit = off, >0 = fixed PC + reserved = optional(number) # 0/omit = unreserved, >0 = reserved + auto_scale = optional(object({ min = number max = number @@ -86,7 +88,8 @@ variable "provisioned_config" { })) }) default = { - fixed = 0 + fixed = 0 + reserved = 1 # auto_scale = { # max = 1, # min = 0, @@ -95,6 +98,15 @@ variable "provisioned_config" { # } } + validation { + condition = ( + var.provisioned_config.fixed == null + ? true + : var.provisioned_config.reserved > var.provisioned_config.fixed + ) + error_message = "When provisioned_config.fixed is set, provisioned_config.reserved must be greater than fixed to avoid Lambda throttling." + } + validation { condition = !( (var.provisioned_config.fixed != null) && From 233a19da6c52329a978aad3fece976edcabdeff7 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 15:26:58 +0000 Subject: [PATCH 04/43] fix: null reserved --- infra/modules/aws/_shared/lambda/variables.tf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 942b59d..4d952d3 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -100,11 +100,14 @@ variable "provisioned_config" { validation { condition = ( - var.provisioned_config.fixed == null + var.provisioned_config.fixed == null || var.provisioned_config.fixed == 0 ? true - : var.provisioned_config.reserved > var.provisioned_config.fixed + : ( + var.provisioned_config.reserved != null && + var.provisioned_config.reserved > var.provisioned_config.fixed + ) ) - error_message = "When provisioned_config.fixed is set, provisioned_config.reserved must be greater than fixed to avoid Lambda throttling." + error_message = "When provisioned_config.fixed > 0, provisioned_config.reserved must be set and greater than fixed to avoid Lambda throttling." } validation { From ac68b0b8fd9919deb67b61f681dd010e31672b4b Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 15:29:21 +0000 Subject: [PATCH 05/43] chore: update comment --- infra/modules/aws/_shared/lambda/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 4d952d3..ee4ccad 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -78,7 +78,7 @@ variable "provisioned_config" { description = "Either fixed provisioned concurrency (fixed) or autoscaled (auto_scale); omit/zero = none" type = object({ fixed = optional(number) # 0/omit = off, >0 = fixed PC - reserved = optional(number) # 0/omit = unreserved, >0 = reserved + reserved = optional(number) # 0/omit = no concurrency limit, >0 = limited concurrency auto_scale = optional(object({ min = number From c05312c47f75bcbb87b3336a9f775be1874ed425 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 16:40:31 +0000 Subject: [PATCH 06/43] chore: rename var + example --- infra/modules/aws/_shared/lambda/locals.tf | 2 +- infra/modules/aws/_shared/lambda/variables.tf | 16 ++++++++-------- infra/modules/aws/api/main.tf | 7 ++++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index c81aaf0..cb4696f 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -23,7 +23,7 @@ locals { fixed_mode = try(var.provisioned_config.fixed != null, true) pc_fixed_count = try(var.provisioned_config.fixed, 0) - pc_reserved_count = try(var.provisioned_config.reserved, 0) + pc_reserved_count = try(var.provisioned_config.reserved_concurrency, 0) pc_min_capacity = try(var.provisioned_config.auto_scale.min, 0) pc_max_capacity = try(var.provisioned_config.auto_scale.max, 0) pc_trigger_percent = try(var.provisioned_config.auto_scale.trigger_percent, var.provisioned_config_defaults.trigger_percent) / 100 diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index ee4ccad..9f61060 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -77,8 +77,8 @@ variable "provisioned_config_defaults" { variable "provisioned_config" { description = "Either fixed provisioned concurrency (fixed) or autoscaled (auto_scale); omit/zero = none" type = object({ - fixed = optional(number) # 0/omit = off, >0 = fixed PC - reserved = optional(number) # 0/omit = no concurrency limit, >0 = limited concurrency + fixed = optional(number) # 0/omit = off, >0 = fixed PC + reserved_concurrency = optional(number) # 0/omit = no concurrency limit, >0 = limited concurrency auto_scale = optional(object({ min = number @@ -88,8 +88,8 @@ variable "provisioned_config" { })) }) default = { - fixed = 0 - reserved = 1 + fixed = 0 + reserved_concurrency = 1 # auto_scale = { # max = 1, # min = 0, @@ -103,11 +103,11 @@ variable "provisioned_config" { var.provisioned_config.fixed == null || var.provisioned_config.fixed == 0 ? true : ( - var.provisioned_config.reserved != null && - var.provisioned_config.reserved > var.provisioned_config.fixed - ) + var.provisioned_config.reserved_concurrency != null && + var.provisioned_config.reserved_concurrency > var.provisioned_config.fixed + ) ) - error_message = "When provisioned_config.fixed > 0, provisioned_config.reserved must be set and greater than fixed to avoid Lambda throttling." + error_message = "When provisioned_config.fixed > 0, provisioned_config.reserved_concurrency must be set and greater than fixed to avoid Lambda throttling." } validation { diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 4f9cf63..a3ce20d 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -13,8 +13,13 @@ module "lambda_api" { } provisioned_config = { - fixed = 0 + fixed = 0 # cold starts only } + + # provisioned_config = { + # fixed = 1 # always have 1 lambda ready to go + # reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + # } } resource "aws_apigatewayv2_api" "http_api" { From ac9a3abfe189d612e5ed90191edd494a077bcd00 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 17:04:29 +0000 Subject: [PATCH 07/43] chore: use lambda alias arn --- infra/modules/aws/_shared/lambda/outputs.tf | 4 ++++ infra/modules/aws/api/main.tf | 16 ++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/outputs.tf b/infra/modules/aws/_shared/lambda/outputs.tf index 4fe1631..d6fea95 100644 --- a/infra/modules/aws/_shared/lambda/outputs.tf +++ b/infra/modules/aws/_shared/lambda/outputs.tf @@ -14,6 +14,10 @@ output "alias_name" { value = aws_lambda_alias.live.name } +output "alias_arn" { + value = aws_lambda_alias.live.arn +} + output "cloudwatch_log_group" { value = aws_cloudwatch_log_group.lambda_cloudwatch_group.name } diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index a3ce20d..5d97c2f 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -12,14 +12,14 @@ module "lambda_api" { strategy = "all_at_once" } - provisioned_config = { - fixed = 0 # cold starts only - } - # provisioned_config = { - # fixed = 1 # always have 1 lambda ready to go - # reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + # fixed = 0 # cold starts only # } + + provisioned_config = { + fixed = 1 # always have 1 lambda ready to go + reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + } } resource "aws_apigatewayv2_api" "http_api" { @@ -30,7 +30,7 @@ resource "aws_apigatewayv2_api" "http_api" { resource "aws_apigatewayv2_integration" "lambda_proxy" { api_id = aws_apigatewayv2_api.http_api.id integration_type = "AWS_PROXY" - integration_uri = module.lambda_api.arn + integration_uri = module.lambda_api.alias_arn payload_format_version = "2.0" } @@ -55,7 +55,7 @@ resource "aws_apigatewayv2_stage" "default" { resource "aws_lambda_permission" "allow_invoke" { statement_id = "AllowAPIGatewayInvoke" action = "lambda:InvokeFunction" - function_name = module.lambda_api.arn + function_name = module.lambda_api.alias_arn principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.http_api.execution_arn}/*/*" # all routes/stages } From baf35e6a6b51e44680bfc5cd7c5008c95124027c Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Fri, 16 Jan 2026 17:05:48 +0000 Subject: [PATCH 08/43] fix: fmt --- infra/modules/aws/api/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 5d97c2f..25a14dc 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -17,7 +17,7 @@ module "lambda_api" { # } provisioned_config = { - fixed = 1 # always have 1 lambda ready to go + fixed = 1 # always have 1 lambda ready to go reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING } } From 3d811b77836c14093cfb396254d3b96dc45deeac Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Mon, 19 Jan 2026 16:44:07 +0000 Subject: [PATCH 09/43] feat: consumer sqs queue --- infra/modules/aws/consumer/main.tf | 29 +++++++++++++++++++++++++ infra/modules/aws/consumer/outputs.tf | 27 +++++++++++++++++++++++ infra/modules/aws/consumer/variables.tf | 24 ++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 infra/modules/aws/consumer/main.tf create mode 100644 infra/modules/aws/consumer/outputs.tf create mode 100644 infra/modules/aws/consumer/variables.tf diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf new file mode 100644 index 0000000..6a05b32 --- /dev/null +++ b/infra/modules/aws/consumer/main.tf @@ -0,0 +1,29 @@ +module "lambda_consumer" { + source = "../_shared/lambda" + + project_name = var.project_name + environment = var.environment + lambda_bucket = var.lambda_bucket + + lambda_name = "consumer" + lambda_version = var.lambda_version + + deployment_config = { + strategy = "all_at_once" + } + + # provisioned_config = { + # fixed = 0 # cold starts only + # } + + provisioned_config = { + fixed = 1 # always have 1 lambda ready to go + reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + } +} + +module "sqs_queue" { + source = "../_shared/sqs" + + sqs_queue_name = "${var.project_name}-${var.environment}-consumer-queue" +} \ No newline at end of file diff --git a/infra/modules/aws/consumer/outputs.tf b/infra/modules/aws/consumer/outputs.tf new file mode 100644 index 0000000..e4e37c2 --- /dev/null +++ b/infra/modules/aws/consumer/outputs.tf @@ -0,0 +1,27 @@ +output "cloudwatch_log_group" { + value = module.lambda_consumer.cloudwatch_log_group +} + +output "lambda_zip_key" { + value = module.lambda_consumer.lambda_zip_key +} + +output "code_deploy_app_name" { + value = module.lambda_consumer.code_deploy_app_name +} + +output "code_deploy_group_name" { + value = module.lambda_consumer.code_deploy_group_name +} + +output "lambda_arn" { + value = module.lambda_consumer.arn +} + +output "lambda_function_name" { + value = module.lambda_consumer.function_name +} + +output "lambda_alias_name" { + value = module.lambda_consumer.alias_name +} diff --git a/infra/modules/aws/consumer/variables.tf b/infra/modules/aws/consumer/variables.tf new file mode 100644 index 0000000..da3c3a3 --- /dev/null +++ b/infra/modules/aws/consumer/variables.tf @@ -0,0 +1,24 @@ +### start of static vars set in root.hcl ### +variable "project_name" { + type = string + description = "Project name used in naming resources" +} + +variable "environment" { + type = string + description = "Environment reference used in naming resources i.e. 'dev'" +} + +variable "lambda_bucket" { + type = string + description = "Lambda bucket where the code zip(s) are uploaded to" +} +### end of static vars set in root.hcl ### + + +### start of dynamic vars required for resources ### +variable "lambda_version" { + type = string + description = "Lambda code version to be deployed. Used in locating zip file keys" +} +### end of dynamic vars required for resources ### From 91a5b6f07a5177a576a806f8ea32940e1b278fb2 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Mon, 19 Jan 2026 16:44:57 +0000 Subject: [PATCH 10/43] fix: fmt --- infra/modules/aws/consumer/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index 6a05b32..ef53f1b 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -25,5 +25,5 @@ module "lambda_consumer" { module "sqs_queue" { source = "../_shared/sqs" - sqs_queue_name = "${var.project_name}-${var.environment}-consumer-queue" + sqs_queue_name = "${var.project_name}-${var.environment}-consumer-queue" } \ No newline at end of file From 15c8c5ecd1a1fb00fa469f47e50ba1afebb24a83 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Mon, 19 Jan 2026 16:55:28 +0000 Subject: [PATCH 11/43] chore: add lambda trigger from sqs --- backend/consumer/lambda_handler.py | 65 ++++++++++++++++++++++++++++++ infra/modules/aws/consumer/main.tf | 10 +++++ 2 files changed, 75 insertions(+) create mode 100644 backend/consumer/lambda_handler.py diff --git a/backend/consumer/lambda_handler.py b/backend/consumer/lambda_handler.py new file mode 100644 index 0000000..163a1c5 --- /dev/null +++ b/backend/consumer/lambda_handler.py @@ -0,0 +1,65 @@ +import json +from typing import List, Dict + +CHUNK_SIZE = 50 + + +def chunk(items: List[Dict], size: int): + """Yield successive chunks from a list.""" + for i in range(0, len(items), size): + yield items[i:i + size] + + +def process_message(record: Dict): + """ + Process a single SQS message. + Raise an exception to mark it as failed. + """ + body = record["body"] + + # If your messages are JSON: + # payload = json.loads(body) + + # TODO: your business logic here + print({ + "message_id": record["messageId"], + "body_preview": body[:200] + }) + + +def process_chunk(records: List[Dict]) -> List[str]: + """ + Process a chunk of messages. + Returns a list of messageIds that failed. + """ + failed_message_ids = [] + + for record in records: + try: + process_message(record) + except Exception as exc: + print(f"Failed processing message {record['messageId']}: {exc}") + failed_message_ids.append(record["messageId"]) + + return failed_message_ids + + +def lambda_handler(event, context): + """ + AWS Lambda entry point. + Uses partial batch response so only failed messages are retried. + """ + records = event.get("Records", []) + batch_item_failures = [] + + for records_chunk in chunk(records, CHUNK_SIZE): + failed_ids = process_chunk(records_chunk) + + for message_id in failed_ids: + batch_item_failures.append({ + "itemIdentifier": message_id + }) + + return { + "batchItemFailures": batch_item_failures + } diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index ef53f1b..bb9a55a 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -26,4 +26,14 @@ module "sqs_queue" { source = "../_shared/sqs" sqs_queue_name = "${var.project_name}-${var.environment}-consumer-queue" +} + +resource "aws_lambda_event_source_mapping" "sqs" { + event_source_arn = module.sqs_queue.sqs_queue_arn + function_name = module.sqs_queue.lambda_function_name + + batch_size = 500 + maximum_batching_window_in_seconds = 10 + + function_response_types = ["ReportBatchItemFailures"] } \ No newline at end of file From 9822e7cac17cc1a7dd63af9cd6c0108a23eac836 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Mon, 19 Jan 2026 17:10:47 +0000 Subject: [PATCH 12/43] chore: breadcrumb sqs scale --- infra/modules/aws/_shared/lambda/main.tf | 30 +++++++++++++++++++ infra/modules/aws/_shared/lambda/variables.tf | 14 +++++---- infra/modules/aws/api/main.tf | 7 +++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index 0ce05fd..918215d 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -139,3 +139,33 @@ resource "aws_appautoscaling_policy" "pc_policy" { } } } + +resource "aws_appautoscaling_policy" "pc_policy" { + count = local.fixed_mode ? 0 : 1 + name = "${local.lambda_name}-pc-sqs-depth-tt" + policy_type = "TargetTrackingScaling" + resource_id = aws_appautoscaling_target.pc_target.resource_id + scalable_dimension = aws_appautoscaling_target.pc_target.scalable_dimension + service_namespace = aws_appautoscaling_target.pc_target.service_namespace + + target_tracking_scaling_policy_configuration { + # Example: try to keep ~1000 visible messages in the queue. + # Tune this based on your batch size + desired drain speed. + target_value = local.pc_sqs_target_visible_messages + + scale_in_cooldown = local.pc_scale_in_cooldown_seconds + scale_out_cooldown = local.pc_scale_out_cooldown_seconds + + customized_metric_specification { + metric_name = "ApproximateNumberOfMessagesVisible" + namespace = "AWS/SQS" + statistic = "Average" + unit = "Count" + + dimensions { + name = "QueueName" + value = var.sqs_queue_name + } + } + } +} diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 9f61060..3c1d093 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -86,16 +86,18 @@ variable "provisioned_config" { trigger_percent = optional(number) cool_down_seconds = optional(number) })) + + sqs_scale = optional(object({ + min = number + max = number + visible_messages = number + queue_name = optional(string) + cool_down_seconds = optional(number) + })) }) default = { fixed = 0 reserved_concurrency = 1 - # auto_scale = { - # max = 1, - # min = 0, - # trigger_percent = 70 - # cool_down_seconds = 60 - # } } validation { diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 25a14dc..600e0a8 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -16,6 +16,13 @@ module "lambda_api" { # fixed = 0 # cold starts only # } + # auto_scale = { + # max = 1, + # min = 0, + # trigger_percent = 70 + # cool_down_seconds = 60 + # } + provisioned_config = { fixed = 1 # always have 1 lambda ready to go reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING From 0e720434e3fdacf6683919c059319fcf9a7a57ef Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 12:06:30 +0000 Subject: [PATCH 13/43] chore: pass in an validate sqs vars --- infra/modules/aws/_shared/lambda/locals.tf | 20 ++- infra/modules/aws/_shared/lambda/main.tf | 2 +- infra/modules/aws/_shared/lambda/variables.tf | 126 +++++++++++++----- infra/modules/aws/api/main.tf | 3 +- infra/modules/aws/consumer/main.tf | 12 +- 5 files changed, 117 insertions(+), 46 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index cb4696f..be4091e 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -21,11 +21,17 @@ locals { minutes = var.deployment_config.interval_minutes } - fixed_mode = try(var.provisioned_config.fixed != null, true) - pc_fixed_count = try(var.provisioned_config.fixed, 0) - pc_reserved_count = try(var.provisioned_config.reserved_concurrency, 0) - pc_min_capacity = try(var.provisioned_config.auto_scale.min, 0) - pc_max_capacity = try(var.provisioned_config.auto_scale.max, 0) - pc_trigger_percent = try(var.provisioned_config.auto_scale.trigger_percent, var.provisioned_config_defaults.trigger_percent) / 100 - pc_cool_down_seconds = try(var.provisioned_config.auto_scale.cool_down_seconds, var.provisioned_config_defaults.cool_down_seconds) + fixed_mode = try(var.provisioned_config.fixed != null, true) + pc_fixed_count = try(var.provisioned_config.fixed, 0) + pc_reserved_count = try(var.provisioned_config.reserved_concurrency, 0) + + pc_min_capacity = try(var.provisioned_config.sqs_scale.min, var.provisioned_config.auto_scale.min, 0) + pc_max_capacity = try(var.provisioned_config.sqs_scale.max, var.provisioned_config.auto_scale.max, 0) + + pc_scale_in_cooldown_seconds = try(var.provisioned_config.auto_scale.scale_in_cooldown_seconds, var.provisioned_config.sqs_scale.scale_in_cooldown_seconds, 60) + pc_scale_out_cooldown_seconds = try(var.provisioned_config.auto_scale.scale_out_cooldown_seconds, var.provisioned_config.sqs_scale.scale_out_cooldown_seconds, 60) + + pc_trigger_percent = try(var.provisioned_config.auto_scale.trigger_percent, 70) / 100 + pc_sqs_target_visible_messages = try(var.provisioned_config.sqs_scale.visible_messages, 0) + pc_sqs_queue_name = var.provisioned_config.sqs_scale.queue_name } diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index 918215d..36e553a 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -164,7 +164,7 @@ resource "aws_appautoscaling_policy" "pc_policy" { dimensions { name = "QueueName" - value = var.sqs_queue_name + value = local.pc_sqs_queue_name } } } diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 3c1d093..edeeb04 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -62,18 +62,6 @@ variable "deployment_config" { } } -variable "provisioned_config_defaults" { - description = "Fall back values for provisioned_config.auto_scale.trigger_percent and provisioned_config.auto_scale.cool_down_seconds" - type = object({ - trigger_percent = number - cool_down_seconds = number - }) - default = { - trigger_percent = 70 - cool_down_seconds = 60 - } -} - variable "provisioned_config" { description = "Either fixed provisioned concurrency (fixed) or autoscaled (auto_scale); omit/zero = none" type = object({ @@ -81,18 +69,20 @@ variable "provisioned_config" { reserved_concurrency = optional(number) # 0/omit = no concurrency limit, >0 = limited concurrency auto_scale = optional(object({ - min = number - max = number - trigger_percent = optional(number) - cool_down_seconds = optional(number) + min = number + max = number + trigger_percent = optional(number) + scale_in_cooldown_seconds = optional(number) + scale_out_cooldown_seconds = optional(number) })) sqs_scale = optional(object({ - min = number - max = number - visible_messages = number - queue_name = optional(string) - cool_down_seconds = optional(number) + min = number + max = number + visible_messages = number + queue_name = optional(string) + scale_in_cooldown_seconds = optional(number) + scale_out_cooldown_seconds = optional(number) })) }) default = { @@ -114,23 +104,38 @@ variable "provisioned_config" { validation { condition = !( - (var.provisioned_config.fixed != null) && - (var.provisioned_config.auto_scale != null) + ( + var.provisioned_config.fixed != null && + var.provisioned_config.fixed > 0 + ) && + ( + var.provisioned_config.auto_scale != null || + var.provisioned_config.sqs_scale != null + ) + ) && !( + var.provisioned_config.auto_scale != null && + var.provisioned_config.sqs_scale != null ) - error_message = "Specify either 'fixed' or 'auto_scale' (or neither), not both." + error_message = "Specify only one of 'fixed', 'auto_scale', or 'sqs_scale' (or none)." } - # When autoscale is set, ensure max > min validation { condition = ( - var.provisioned_config.auto_scale != null - ? (var.provisioned_config.auto_scale.max > var.provisioned_config.auto_scale.min) - : true + ( + var.provisioned_config.auto_scale != null + ? var.provisioned_config.auto_scale.max > var.provisioned_config.auto_scale.min + : true + ) + && + ( + var.provisioned_config.sqs_scale != null + ? var.provisioned_config.sqs_scale.max > var.provisioned_config.sqs_scale.min + : true + ) ) - error_message = "When auto_scale is set, 'max' must be greater than 'min'." + error_message = "When auto_scale or sqs_scale is set, 'max' must be greater than 'min'." } - # When autoscale.trigger_percent is set, ensure is 1-99 validation { condition = ( var.provisioned_config.auto_scale != null @@ -140,13 +145,68 @@ variable "provisioned_config" { error_message = "When autoscale.trigger_percent, must be > 0 && < 100" } - # When autoscale.cool_down_seconds is set, ensure is at least a minute, max and hour validation { condition = ( var.provisioned_config.auto_scale != null - ? (var.provisioned_config.auto_scale.cool_down_seconds > 59 && var.provisioned_config.auto_scale.cool_down_seconds < 3600) + ? ( + var.provisioned_config.auto_scale.scale_in_cooldown_seconds != null && + var.provisioned_config.auto_scale.scale_out_cooldown_seconds != null && + + var.provisioned_config.auto_scale.scale_in_cooldown_seconds >= 60 && + var.provisioned_config.auto_scale.scale_out_cooldown_seconds >= 60 + ) + : true + ) + error_message = "When auto_scale is set, both scale_in_cooldown_seconds and scale_out_cooldown_seconds must be specified and each must be at least 60 seconds." + } + + validation { + condition = ( + var.provisioned_config.sqs_scale != null + ? ( + var.provisioned_config.sqs_scale.min >= 0 && + var.provisioned_config.sqs_scale.max > var.provisioned_config.sqs_scale.min && + floor(var.provisioned_config.sqs_scale.min) == var.provisioned_config.sqs_scale.min && + floor(var.provisioned_config.sqs_scale.max) == var.provisioned_config.sqs_scale.max + ) + : true + ) + error_message = "When sqs_scale is set, 'min' must be an integer >= 0 and 'max' must be an integer greater than 'min'." + } + + validation { + condition = ( + var.provisioned_config.sqs_scale != null + ? ( + var.provisioned_config.sqs_scale.visible_messages > 0 && + floor(var.provisioned_config.sqs_scale.visible_messages) == var.provisioned_config.sqs_scale.visible_messages + ) + : true + ) + error_message = "When sqs_scale is set, 'visible_messages' must be a positive integer." + } + + validation { + condition = ( + var.provisioned_config.sqs_scale != null && var.provisioned_config.sqs_scale.queue_name != null + ? length(trim(var.provisioned_config.sqs_scale.queue_name)) > 0 + : true + ) + error_message = "When sqs_scale.queue_name is set, it must be a non-empty string." + } + + validation { + condition = ( + var.provisioned_config.sqs_scale != null + ? ( + var.provisioned_config.sqs_scale.scale_in_cooldown_seconds != null && + var.provisioned_config.sqs_scale.scale_out_cooldown_seconds != null && + + var.provisioned_config.sqs_scale.scale_in_cooldown_seconds >= 60 && + var.provisioned_config.sqs_scale.scale_out_cooldown_seconds >= 60 + ) : true ) - error_message = "When autoscale.cool_down_seconds, must be > 59 && < 3600" + error_message = "When sqs_scale is set, both scale_in_cooldown_seconds and scale_out_cooldown_seconds must be specified and each must be at least 60 seconds." } } \ No newline at end of file diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 600e0a8..66f2a1a 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -20,7 +20,8 @@ module "lambda_api" { # max = 1, # min = 0, # trigger_percent = 70 - # cool_down_seconds = 60 + # scale_in_cooldown_seconds = 60 + # scale_out_cooldown_seconds = 60 # } provisioned_config = { diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index bb9a55a..ed193a6 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -12,13 +12,17 @@ module "lambda_consumer" { strategy = "all_at_once" } - # provisioned_config = { - # fixed = 0 # cold starts only - # } - provisioned_config = { fixed = 1 # always have 1 lambda ready to go reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + sqs_scale = { + min = 1 + max = 10 + visible_messages = 100 + queue_name = module.sqs_queue.sqs_queue_name + scale_in_cooldown_seconds = 60 + scale_out_cooldown_seconds = 60 + } } } From 1554e222ec4a993c777c2dff7147a5b759921378 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 12:13:52 +0000 Subject: [PATCH 14/43] chore: enable consumer deployment --- .github/workflows/deploy.yml | 79 +++++++++++++++++++++ infra/live/dev/aws/consumer/terragrunt.hcl | 7 ++ infra/live/prod/aws/consumer/terragrunt.hcl | 7 ++ 3 files changed, 93 insertions(+) create mode 100644 infra/live/dev/aws/consumer/terragrunt.hcl create mode 100644 infra/live/prod/aws/consumer/terragrunt.hcl diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e19afe2..344a1f8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -135,3 +135,82 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} just_action: lambda-prune + + + consumer: + needs: setup + runs-on: ubuntu-latest + env: + APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml + APP_SPEC_KEY: ${{ inputs.lambda_version }}/appspec.zip + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + + - name: deploy consumer + id: deploy-consumer + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + - name: get consumer variables + id: get-consumer-vars + env: + TG_OUTPUTS: ${{ steps.deploy-consumer.outputs.tg_outputs }} + run: | + echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT + echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT + echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT + echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT + echo "code_deploy_group_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_group_name.value')" >> $GITHUB_OUTPUT + + - name: get lambda version + id: lambda-get-version + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: lambda-get-version + + - name: create lambda version + id: lambda-create-version + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + LAMBDA_ZIP_KEY: ${{ steps.get-consumer-vars.outputs.lambda_zip_key }} + FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: lambda-create-version + + - name: Prepare and upload AppSpec File to s3 + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} + CURRENT_VERSION: ${{ steps.lambda-get-version.outputs.just_outputs }} + NEW_VERSION: ${{ steps.lambda-create-version.outputs.just_outputs }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: lambda-upload-bundle + + - name: deploy lambda + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + CODE_DEPLOY_APP_NAME: ${{ steps.get-consumer-vars.outputs.code_deploy_app_name }} + CODE_DEPLOY_GROUP_NAME: ${{ steps.get-consumer-vars.outputs.code_deploy_group_name }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: lambda-deploy + + - name: prune lambda + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + KEEP: ${{ inputs.lambda_keep }} + FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: lambda-prune \ No newline at end of file diff --git a/infra/live/dev/aws/consumer/terragrunt.hcl b/infra/live/dev/aws/consumer/terragrunt.hcl new file mode 100644 index 0000000..211f485 --- /dev/null +++ b/infra/live/dev/aws/consumer/terragrunt.hcl @@ -0,0 +1,7 @@ +include { + path = find_in_parent_folders("root.hcl") +} + +terraform { + source = "../../../../modules//aws//consumer" +} diff --git a/infra/live/prod/aws/consumer/terragrunt.hcl b/infra/live/prod/aws/consumer/terragrunt.hcl new file mode 100644 index 0000000..211f485 --- /dev/null +++ b/infra/live/prod/aws/consumer/terragrunt.hcl @@ -0,0 +1,7 @@ +include { + path = find_in_parent_folders("root.hcl") +} + +terraform { + source = "../../../../modules//aws//consumer" +} From 719cb10523b1aca8fca3646188383b2912cabe3e Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 12:14:00 +0000 Subject: [PATCH 15/43] fix: fmt --- infra/modules/aws/api/main.tf | 4 ++-- infra/modules/aws/consumer/main.tf | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index 66f2a1a..fa70656 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -20,8 +20,8 @@ module "lambda_api" { # max = 1, # min = 0, # trigger_percent = 70 - # scale_in_cooldown_seconds = 60 - # scale_out_cooldown_seconds = 60 + # scale_in_cooldown_seconds = 60 + # scale_out_cooldown_seconds = 60 # } provisioned_config = { diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index ed193a6..d2b2682 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -13,13 +13,11 @@ module "lambda_consumer" { } provisioned_config = { - fixed = 1 # always have 1 lambda ready to go - reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING sqs_scale = { - min = 1 - max = 10 - visible_messages = 100 - queue_name = module.sqs_queue.sqs_queue_name + min = 1 + max = 10 + visible_messages = 100 + queue_name = module.sqs_queue.sqs_queue_name scale_in_cooldown_seconds = 60 scale_out_cooldown_seconds = 60 } From 8c1686e6a530a629a868b8a3a7719d7ddc49c8a1 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 12:20:32 +0000 Subject: [PATCH 16/43] fix: add requirements.txt --- backend/consumer/requirements.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 backend/consumer/requirements.txt diff --git a/backend/consumer/requirements.txt b/backend/consumer/requirements.txt new file mode 100644 index 0000000..e69de29 From 7c7eaefb80ed73daa0e2563176ce56784ea26632 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 12:27:59 +0000 Subject: [PATCH 17/43] fix: rename to rm dupe --- infra/modules/aws/_shared/lambda/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index 36e553a..edd4235 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -140,7 +140,7 @@ resource "aws_appautoscaling_policy" "pc_policy" { } } -resource "aws_appautoscaling_policy" "pc_policy" { +resource "aws_appautoscaling_policy" "pc_sqs_policy" { count = local.fixed_mode ? 0 : 1 name = "${local.lambda_name}-pc-sqs-depth-tt" policy_type = "TargetTrackingScaling" From 9bcda9e7f3feed4fcb6d089f88f153a6cb88a81c Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 15:00:56 +0000 Subject: [PATCH 18/43] fix: module output fixes --- infra/modules/aws/_shared/lambda/variables.tf | 2 +- infra/modules/aws/_shared/sqs/outputs.tf | 4 ++++ infra/modules/aws/consumer/main.tf | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index edeeb04..9a6cb12 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -189,7 +189,7 @@ variable "provisioned_config" { validation { condition = ( var.provisioned_config.sqs_scale != null && var.provisioned_config.sqs_scale.queue_name != null - ? length(trim(var.provisioned_config.sqs_scale.queue_name)) > 0 + ? length(trimspace(var.provisioned_config.sqs_scale.queue_name)) > 0 : true ) error_message = "When sqs_scale.queue_name is set, it must be a non-empty string." diff --git a/infra/modules/aws/_shared/sqs/outputs.tf b/infra/modules/aws/_shared/sqs/outputs.tf index a731422..35ac0bc 100644 --- a/infra/modules/aws/_shared/sqs/outputs.tf +++ b/infra/modules/aws/_shared/sqs/outputs.tf @@ -2,6 +2,10 @@ output "sqs_queue_name" { value = aws_sqs_queue.queue.name } +output "sqs_queue_arn" { + value = aws_sqs_queue.queue.arn +} + output "sqs_queue_url" { value = aws_sqs_queue.queue.url } diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index d2b2682..62bbfbc 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -32,7 +32,7 @@ module "sqs_queue" { resource "aws_lambda_event_source_mapping" "sqs" { event_source_arn = module.sqs_queue.sqs_queue_arn - function_name = module.sqs_queue.lambda_function_name + function_name = module.lambda_consumer.function_name batch_size = 500 maximum_batching_window_in_seconds = 10 From 8b51943477b6b4bdbce8e26c25e4d8463aaa0540 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 15:03:45 +0000 Subject: [PATCH 19/43] fix: handle sqs queue name when not sqs --- infra/modules/aws/_shared/lambda/locals.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index be4091e..6f57f16 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -33,5 +33,5 @@ locals { pc_trigger_percent = try(var.provisioned_config.auto_scale.trigger_percent, 70) / 100 pc_sqs_target_visible_messages = try(var.provisioned_config.sqs_scale.visible_messages, 0) - pc_sqs_queue_name = var.provisioned_config.sqs_scale.queue_name + pc_sqs_queue_name = try(var.provisioned_config.sqs_scale.queue_name, "") } From a0121e001cfa88194dd11c5e13a8b1c190dc1d0e Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 15:10:44 +0000 Subject: [PATCH 20/43] fix: validation --- infra/modules/aws/_shared/lambda/variables.tf | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 9a6cb12..89bd862 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -105,16 +105,14 @@ variable "provisioned_config" { validation { condition = !( ( - var.provisioned_config.fixed != null && - var.provisioned_config.fixed > 0 - ) && - ( + try(var.provisioned_config.fixed, 0) > 0 + ) && ( var.provisioned_config.auto_scale != null || - var.provisioned_config.sqs_scale != null + var.provisioned_config.sqs_scale != null ) - ) && !( + ) && !( var.provisioned_config.auto_scale != null && - var.provisioned_config.sqs_scale != null + var.provisioned_config.sqs_scale != null ) error_message = "Specify only one of 'fixed', 'auto_scale', or 'sqs_scale' (or none)." } From e8b1b2f26839b23a0e8373ce89027066758efb7a Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 15:16:10 +0000 Subject: [PATCH 21/43] fix: use coalesce --- infra/modules/aws/_shared/lambda/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 89bd862..5210f12 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -105,7 +105,7 @@ variable "provisioned_config" { validation { condition = !( ( - try(var.provisioned_config.fixed, 0) > 0 + coalesce(var.provisioned_config.fixed, 0) > 0 ) && ( var.provisioned_config.auto_scale != null || var.provisioned_config.sqs_scale != null From 2e1ff3af69f4918b5687ead5d3b42e627d651e16 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 15:40:34 +0000 Subject: [PATCH 22/43] fix: working iams and vars --- infra/modules/aws/_shared/lambda/main.tf | 7 +++++++ infra/modules/aws/_shared/lambda/variables.tf | 14 ++++++++++---- infra/modules/aws/consumer/main.tf | 4 ++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index edd4235..7cb0359 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -3,6 +3,13 @@ resource "aws_iam_role" "iam_for_lambda" { assume_role_policy = data.aws_iam_policy_document.assume_role.json } +resource "aws_iam_role_policy_attachment" "additional_iam_attachments" { + for_each = { for idx, arn in var.additional_policy_arns : idx => arn } + + role = aws_iam_role.iam_for_lambda.name + policy_arn = each.value +} + resource "aws_lambda_function" "lambda" { function_name = local.lambda_name role = aws_iam_role.iam_for_lambda.arn diff --git a/infra/modules/aws/_shared/lambda/variables.tf b/infra/modules/aws/_shared/lambda/variables.tf index 5210f12..d485464 100644 --- a/infra/modules/aws/_shared/lambda/variables.tf +++ b/infra/modules/aws/_shared/lambda/variables.tf @@ -35,6 +35,12 @@ variable "log_retention_days" { default = 1 } +variable "additional_policy_arns" { + description = "List of IAM policy ARNs to attach to the role" + type = list(string) + default = [] +} + variable "deployment_config" { description = "Traffic shifting: all_at_once | canary | linear" type = object({ @@ -106,13 +112,13 @@ variable "provisioned_config" { condition = !( ( coalesce(var.provisioned_config.fixed, 0) > 0 - ) && ( + ) && ( var.provisioned_config.auto_scale != null || - var.provisioned_config.sqs_scale != null + var.provisioned_config.sqs_scale != null ) - ) && !( + ) && !( var.provisioned_config.auto_scale != null && - var.provisioned_config.sqs_scale != null + var.provisioned_config.sqs_scale != null ) error_message = "Specify only one of 'fixed', 'auto_scale', or 'sqs_scale' (or none)." } diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index 62bbfbc..a10f999 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -8,6 +8,10 @@ module "lambda_consumer" { lambda_name = "consumer" lambda_version = var.lambda_version + additional_policy_arns = [ + module.sqs_queue.sqs_queue_read_policy_arn + ] + deployment_config = { strategy = "all_at_once" } From 9807bf62cc80ac20ccb7f0e198da1fededb42af1 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 16:38:58 +0000 Subject: [PATCH 23/43] fix: local modes --- infra/modules/aws/_shared/lambda/locals.tf | 5 ++++- infra/modules/aws/_shared/lambda/main.tf | 4 ++-- infra/modules/aws/api/main.tf | 26 ++++++++++++---------- infra/modules/aws/consumer/main.tf | 25 ++++++++++++++------- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index 6f57f16..764b052 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -21,7 +21,10 @@ locals { minutes = var.deployment_config.interval_minutes } - fixed_mode = try(var.provisioned_config.fixed != null, true) + fixed_mode = try(var.provisioned_config.fixed != null, true) && try(var.provisioned_config.fixed > 0, false) + auto_scale_mode = try(var.provisioned_config.auto_scale != null, false) + sqs_scale_mode = try(var.provisioned_config.sqs_scale != null, false) + pc_fixed_count = try(var.provisioned_config.fixed, 0) pc_reserved_count = try(var.provisioned_config.reserved_concurrency, 0) diff --git a/infra/modules/aws/_shared/lambda/main.tf b/infra/modules/aws/_shared/lambda/main.tf index 7cb0359..9343337 100644 --- a/infra/modules/aws/_shared/lambda/main.tf +++ b/infra/modules/aws/_shared/lambda/main.tf @@ -130,7 +130,7 @@ resource "aws_appautoscaling_target" "pc_target" { } resource "aws_appautoscaling_policy" "pc_policy" { - count = local.fixed_mode ? 0 : 1 + count = local.auto_scale_mode ? 1 : 0 name = "${local.lambda_name}-pc-tt" policy_type = "TargetTrackingScaling" resource_id = aws_appautoscaling_target.pc_target.resource_id @@ -148,7 +148,7 @@ resource "aws_appautoscaling_policy" "pc_policy" { } resource "aws_appautoscaling_policy" "pc_sqs_policy" { - count = local.fixed_mode ? 0 : 1 + count = local.sqs_scale_mode ? 1 : 0 name = "${local.lambda_name}-pc-sqs-depth-tt" policy_type = "TargetTrackingScaling" resource_id = aws_appautoscaling_target.pc_target.resource_id diff --git a/infra/modules/aws/api/main.tf b/infra/modules/aws/api/main.tf index fa70656..215895d 100644 --- a/infra/modules/aws/api/main.tf +++ b/infra/modules/aws/api/main.tf @@ -12,22 +12,24 @@ module "lambda_api" { strategy = "all_at_once" } + provisioned_config = { + fixed = 0 # cold starts only + } + # provisioned_config = { - # fixed = 0 # cold starts only + # fixed = 1 # always have 1 lambda ready to go + # reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING # } - # auto_scale = { - # max = 1, - # min = 0, - # trigger_percent = 70 - # scale_in_cooldown_seconds = 60 - # scale_out_cooldown_seconds = 60 + # provisioned_config = { + # auto_scale = { + # max = 5 + # min = 0 + # trigger_percent = 70 + # scale_in_cooldown_seconds = 60 + # scale_out_cooldown_seconds = 60 + # } # } - - provisioned_config = { - fixed = 1 # always have 1 lambda ready to go - reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING - } } resource "aws_apigatewayv2_api" "http_api" { diff --git a/infra/modules/aws/consumer/main.tf b/infra/modules/aws/consumer/main.tf index a10f999..78cfa08 100644 --- a/infra/modules/aws/consumer/main.tf +++ b/infra/modules/aws/consumer/main.tf @@ -17,15 +17,24 @@ module "lambda_consumer" { } provisioned_config = { - sqs_scale = { - min = 1 - max = 10 - visible_messages = 100 - queue_name = module.sqs_queue.sqs_queue_name - scale_in_cooldown_seconds = 60 - scale_out_cooldown_seconds = 60 - } + fixed = 0 # cold starts only } + + # provisioned_config = { + # fixed = 1 # always have 1 lambda ready to go + # reserved_concurrency = 2 # only allow 2 concurrent executions THIS ALSO SERVES AS A LIMIT TO AVOID THROTTLING + # } + + # provisioned_config = { + # sqs_scale = { + # min = 1 + # max = 5 + # visible_messages = 100 + # queue_name = module.sqs_queue.sqs_queue_name + # scale_in_cooldown_seconds = 60 + # scale_out_cooldown_seconds = 60 + # } + # } } module "sqs_queue" { From 704c612cb59acafa86c8363c05269240fa87838c Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 16:39:16 +0000 Subject: [PATCH 24/43] fix: fmt --- infra/modules/aws/_shared/lambda/locals.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index 764b052..7b9943c 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -21,9 +21,9 @@ locals { minutes = var.deployment_config.interval_minutes } - fixed_mode = try(var.provisioned_config.fixed != null, true) && try(var.provisioned_config.fixed > 0, false) - auto_scale_mode = try(var.provisioned_config.auto_scale != null, false) - sqs_scale_mode = try(var.provisioned_config.sqs_scale != null, false) + fixed_mode = try(var.provisioned_config.fixed != null, true) && try(var.provisioned_config.fixed > 0, false) + auto_scale_mode = try(var.provisioned_config.auto_scale != null, false) + sqs_scale_mode = try(var.provisioned_config.sqs_scale != null, false) pc_fixed_count = try(var.provisioned_config.fixed, 0) pc_reserved_count = try(var.provisioned_config.reserved_concurrency, 0) From 397e17b5651933da836d07c3c2bc0922bcb4076a Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 16:48:23 +0000 Subject: [PATCH 25/43] chore: try tf v1.13.3 --- .github/workflows/build.yml | 1 + .github/workflows/deploy.yml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 663a8cc..e412f7f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,6 +43,7 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/code_bucket + tf_version: "1.13.3" - name: Get bucket name id: get_bucket_name diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 344a1f8..22622dc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -48,6 +48,7 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/oidc + tf_version: "1.13.3" - name: check Lambda version uses: chrispsheehan/just-aws-oidc-action@0.1.3 @@ -74,6 +75,7 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/api + tf_version: "1.13.3" - name: get api variables id: get-api-vars @@ -154,6 +156,7 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + tf_version: "1.13.3" - name: get consumer variables id: get-consumer-vars env: From fa8cb3ae743fb4febfaa7e39cbd861e83345ab51 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 16:53:04 +0000 Subject: [PATCH 26/43] chore: +sqs:* --- infra/live/global_vars.hcl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infra/live/global_vars.hcl b/infra/live/global_vars.hcl index 571ab7f..5b61d4b 100644 --- a/infra/live/global_vars.hcl +++ b/infra/live/global_vars.hcl @@ -8,7 +8,8 @@ locals { "apigateway:*", "codedeploy:*", "application-autoscaling:*", - "cloudwatch:*" + "cloudwatch:*", + "sqs:*" ] } From e16cbc4596862942c50a4ed40ecbf29169915246 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 16:57:27 +0000 Subject: [PATCH 27/43] chore: terragrunt-aws-oidc-action@0.4.1 --- .github/workflows/build.yml | 3 +-- .github/workflows/deploy.yml | 10 ++++------ .github/workflows/destroy.yml | 4 ++-- .github/workflows/get_build.yml | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e412f7f..44e27dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,12 +38,11 @@ jobs: ref: ${{ inputs.version }} - name: Deploy code buckets - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 id: code_action with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/code_bucket - tf_version: "1.13.3" - name: Get bucket name id: get_bucket_name diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 22622dc..c64fc08 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -44,11 +44,10 @@ jobs: with: ref: ${{ inputs.infra_version }} - - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/oidc - tf_version: "1.13.3" - name: check Lambda version uses: chrispsheehan/just-aws-oidc-action@0.1.3 @@ -71,11 +70,10 @@ jobs: - name: deploy api id: deploy-api - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/api - tf_version: "1.13.3" - name: get api variables id: get-api-vars @@ -152,11 +150,11 @@ jobs: - name: deploy consumer id: deploy-consumer - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/consumer - tf_version: "1.13.3" + - name: get consumer variables id: get-consumer-vars env: diff --git a/.github/workflows/destroy.yml b/.github/workflows/destroy.yml index 341fd81..fc6b3e9 100644 --- a/.github/workflows/destroy.yml +++ b/.github/workflows/destroy.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v4 - name: Destroy backend - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/api @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v4 - name: Destroy code - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/code_bucket diff --git a/.github/workflows/get_build.yml b/.github/workflows/get_build.yml index 1480ca2..f3e45ff 100644 --- a/.github/workflows/get_build.yml +++ b/.github/workflows/get_build.yml @@ -38,7 +38,7 @@ jobs: ref: ${{ inputs.version }} - name: Get code bucket outputs - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.0 + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 id: code_action with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} From c4df201abf1faa65777834a2144b695a0a09832a Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 17:15:47 +0000 Subject: [PATCH 28/43] fix: appspec.yml rm duped names --- .github/workflows/deploy.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c64fc08..7738606 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -61,8 +61,8 @@ jobs: needs: setup runs-on: ubuntu-latest env: - APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml - APP_SPEC_KEY: ${{ inputs.lambda_version }}/appspec.zip + APP_SPEC_FILE: ${{ github.workspace }}/api-appspec.yml + APP_SPEC_KEY: ${{ inputs.lambda_version }}/api-appspec.zip steps: - uses: actions/checkout@v4 with: @@ -141,8 +141,8 @@ jobs: needs: setup runs-on: ubuntu-latest env: - APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml - APP_SPEC_KEY: ${{ inputs.lambda_version }}/appspec.zip + APP_SPEC_FILE: ${{ github.workspace }}/consumer-appspec.yml + APP_SPEC_KEY: ${{ inputs.lambda_version }}/consumer-appspec.zip steps: - uses: actions/checkout@v4 with: From 03c77d8539c1d124b1e5f4687cf890de32b914e0 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Wed, 21 Jan 2026 17:23:56 +0000 Subject: [PATCH 29/43] chore: add consumer to destroy --- .github/workflows/destroy.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/destroy.yml b/.github/workflows/destroy.yml index fc6b3e9..d0c157a 100644 --- a/.github/workflows/destroy.yml +++ b/.github/workflows/destroy.yml @@ -35,6 +35,18 @@ jobs: tg_directory: infra/live/${{ inputs.environment }}/aws/api tg_action: destroy + consumer: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Destroy backend + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + tg_action: destroy + build: needs: - api From a2ef1755d20627c812b69b1439a30fb666b1b5aa Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 11:05:40 +0000 Subject: [PATCH 30/43] chore: lambda deploy action --- .github/actions/deploy_lambda/action.yml | 105 +++++++++++++++++++++++ .github/workflows/deploy.yml | 76 ++-------------- 2 files changed, 110 insertions(+), 71 deletions(-) create mode 100644 .github/actions/deploy_lambda/action.yml diff --git a/.github/actions/deploy_lambda/action.yml b/.github/actions/deploy_lambda/action.yml new file mode 100644 index 0000000..920d69f --- /dev/null +++ b/.github/actions/deploy_lambda/action.yml @@ -0,0 +1,105 @@ +name: Deploy Lambda with CodeDeploy +description: Deploy a Lambda using Terragrunt + CodeDeploy (publish version, traffic shift, prune) + +inputs: + aws_oidc_role_arn: + description: AWS OIDC role to assume + required: true + + infra_version: + description: Git ref containing Terraform/Terragrunt config + required: true + + environment: + description: Environment name (dev/prod/etc) + required: true + + tg_directory: + description: Terragrunt directory for this lambda + required: true + + lambda_version: + description: Lambda artifact version (S3 prefix) + required: true + + lambda_keep: + description: Number of lambda versions to keep + required: true + +runs: + using: composite + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + + - name: Deploy infra (Terragrunt) + id: deploy + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + tg_directory: ${{ inputs.tg_directory }} + + - name: Extract Terragrunt outputs + id: vars + shell: bash + env: + TG_OUTPUTS: ${{ steps.deploy.outputs.tg_outputs }} + run: | + echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT + echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT + echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT + echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT + echo "code_deploy_group_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_group_name.value')" >> $GITHUB_OUTPUT + + - name: Get current lambda version + id: get-version + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.vars.outputs.lambda_alias_name }} + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + just_action: lambda-get-version + + - name: Publish new lambda version + id: publish + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} + LAMBDA_ZIP_KEY: ${{ steps.vars.outputs.lambda_zip_key }} + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + just_action: lambda-create-version + + - name: Upload AppSpec bundle + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.vars.outputs.lambda_alias_name }} + CURRENT_VERSION: ${{ steps.get-version.outputs.just_outputs }} + NEW_VERSION: ${{ steps.publish.outputs.just_outputs }} + APP_SPEC_FILE: ${{ github.workspace }}/${{ github.workspace }}/appspec.yml + APP_SPEC_KEY: ${{ github.workspace }}/${{ github.workspace }}/appspec.zip + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + just_action: lambda-upload-bundle + + - name: Run CodeDeploy + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + CODE_DEPLOY_APP_NAME: ${{ steps.vars.outputs.code_deploy_app_name }} + CODE_DEPLOY_GROUP_NAME: ${{ steps.vars.outputs.code_deploy_group_name }} + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + just_action: lambda-deploy + + - name: Prune old lambda versions + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + KEEP: ${{ inputs.lambda_keep }} + FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} + ALIAS_NAME: ${{ steps.vars.outputs.lambda_alias_name }} + with: + aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} + just_action: lambda-prune diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7738606..084c5fc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -140,78 +140,12 @@ jobs: consumer: needs: setup runs-on: ubuntu-latest - env: - APP_SPEC_FILE: ${{ github.workspace }}/consumer-appspec.yml - APP_SPEC_KEY: ${{ inputs.lambda_version }}/consumer-appspec.zip steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.infra_version }} - - - name: deploy consumer - id: deploy-consumer - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + - uses: ./.github/actions/deploy-lambda-with-codedeploy with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + infra_version: ${{ inputs.infra_version }} + environment: ${{ inputs.environment }} tg_directory: infra/live/${{ inputs.environment }}/aws/consumer - - - name: get consumer variables - id: get-consumer-vars - env: - TG_OUTPUTS: ${{ steps.deploy-consumer.outputs.tg_outputs }} - run: | - echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT - echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT - echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT - echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT - echo "code_deploy_group_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_group_name.value')" >> $GITHUB_OUTPUT - - - name: get lambda version - id: lambda-get-version - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-get-version - - - name: create lambda version - id: lambda-create-version - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - LAMBDA_ZIP_KEY: ${{ steps.get-consumer-vars.outputs.lambda_zip_key }} - FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-create-version - - - name: Prepare and upload AppSpec File to s3 - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} - CURRENT_VERSION: ${{ steps.lambda-get-version.outputs.just_outputs }} - NEW_VERSION: ${{ steps.lambda-create-version.outputs.just_outputs }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-upload-bundle - - - name: deploy lambda - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - CODE_DEPLOY_APP_NAME: ${{ steps.get-consumer-vars.outputs.code_deploy_app_name }} - CODE_DEPLOY_GROUP_NAME: ${{ steps.get-consumer-vars.outputs.code_deploy_group_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-deploy - - - name: prune lambda - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - KEEP: ${{ inputs.lambda_keep }} - FUNCTION_NAME: ${{ steps.get-consumer-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-consumer-vars.outputs.lambda_alias_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-prune \ No newline at end of file + lambda_version: ${{ inputs.lambda_version }} + lambda_keep: ${{ inputs.lambda_keep }} From 1aad36c8d7b8e80f2b17afd5ae7f732375ee96c6 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 11:06:19 +0000 Subject: [PATCH 31/43] fix: action path --- .github/actions/{deploy_lambda => deploy-lambda}/action.yml | 0 .github/workflows/deploy.yml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/actions/{deploy_lambda => deploy-lambda}/action.yml (100%) diff --git a/.github/actions/deploy_lambda/action.yml b/.github/actions/deploy-lambda/action.yml similarity index 100% rename from .github/actions/deploy_lambda/action.yml rename to .github/actions/deploy-lambda/action.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 084c5fc..c8becd1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -141,7 +141,7 @@ jobs: needs: setup runs-on: ubuntu-latest steps: - - uses: ./.github/actions/deploy-lambda-with-codedeploy + - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} infra_version: ${{ inputs.infra_version }} From 060f758a894b8e6fce8265058e2a9f18435628e1 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 11:10:57 +0000 Subject: [PATCH 32/43] chore: add actions/checkout@v4 --- .github/workflows/deploy.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c8becd1..57ce7b8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -141,6 +141,9 @@ jobs: needs: setup runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} From 28081dee96ccc8513bd0f106e56039630f65f9f2 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 11:21:25 +0000 Subject: [PATCH 33/43] fix: use correct appspec path --- .github/actions/deploy-lambda/action.yml | 4 ++-- .github/workflows/deploy.yml | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index 920d69f..06c146b 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -79,8 +79,8 @@ runs: ALIAS_NAME: ${{ steps.vars.outputs.lambda_alias_name }} CURRENT_VERSION: ${{ steps.get-version.outputs.just_outputs }} NEW_VERSION: ${{ steps.publish.outputs.just_outputs }} - APP_SPEC_FILE: ${{ github.workspace }}/${{ github.workspace }}/appspec.yml - APP_SPEC_KEY: ${{ github.workspace }}/${{ github.workspace }}/appspec.zip + APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml + APP_SPEC_KEY: ${{ github.workspace }}/${{ inputs.tg_directory }}/appspec.zip with: aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} just_action: lambda-upload-bundle diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 57ce7b8..8f3e150 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -61,7 +61,7 @@ jobs: needs: setup runs-on: ubuntu-latest env: - APP_SPEC_FILE: ${{ github.workspace }}/api-appspec.yml + APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml APP_SPEC_KEY: ${{ inputs.lambda_version }}/api-appspec.zip steps: - uses: actions/checkout@v4 @@ -144,6 +144,14 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.infra_version }} + + - name: Deploy infra (Terragrunt) + id: deploy + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} From 4759e57be636c3c183a3f0b15a7c8c3d5cf57e81 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 11:34:22 +0000 Subject: [PATCH 34/43] feat: decouple infra to deploy --- .github/actions/deploy-lambda/action.yml | 15 ++++----------- .github/workflows/deploy.yml | 5 ++++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index 06c146b..a23f61b 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -10,10 +10,6 @@ inputs: description: Git ref containing Terraform/Terragrunt config required: true - environment: - description: Environment name (dev/prod/etc) - required: true - tg_directory: description: Terragrunt directory for this lambda required: true @@ -29,22 +25,19 @@ inputs: runs: using: composite steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.infra_version }} - - - name: Deploy infra (Terragrunt) - id: deploy + - name: Get Terragrunt outputs + id: init uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} tg_directory: ${{ inputs.tg_directory }} + tg_action: init - name: Extract Terragrunt outputs id: vars shell: bash env: - TG_OUTPUTS: ${{ steps.deploy.outputs.tg_outputs }} + TG_OUTPUTS: ${{ steps.init.outputs.tg_outputs }} run: | echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8f3e150..e7c498a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -100,6 +100,7 @@ jobs: id: lambda-create-version uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} LAMBDA_ZIP_KEY: ${{ steps.get-api-vars.outputs.lambda_zip_key }} FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} with: @@ -109,6 +110,7 @@ jobs: - name: Prepare and upload AppSpec File to s3 uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} ALIAS_NAME: ${{ steps.get-api-vars.outputs.lambda_alias_name }} CURRENT_VERSION: ${{ steps.lambda-get-version.outputs.just_outputs }} @@ -120,6 +122,7 @@ jobs: - name: deploy lambda uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} CODE_DEPLOY_APP_NAME: ${{ steps.get-api-vars.outputs.code_deploy_app_name }} CODE_DEPLOY_GROUP_NAME: ${{ steps.get-api-vars.outputs.code_deploy_group_name }} with: @@ -155,8 +158,8 @@ jobs: - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + bucket_name: ${{ inputs.lambda_bucket }} infra_version: ${{ inputs.infra_version }} - environment: ${{ inputs.environment }} tg_directory: infra/live/${{ inputs.environment }}/aws/consumer lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} From 0d06f866ed29f4a5cc5cf64ccef8088fdca1dd5e Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 13:30:37 +0000 Subject: [PATCH 35/43] fix: BUCKET_NAME: ${{ inputs.lambda_bucket }} --- .github/actions/deploy-lambda/action.yml | 7 +++ .github/workflows/deploy.yml | 79 +++--------------------- .github/workflows/destroy.yml | 1 + 3 files changed, 18 insertions(+), 69 deletions(-) diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index a23f61b..ada573b 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -14,6 +14,10 @@ inputs: description: Terragrunt directory for this lambda required: true + lambda_bucket: + description: "Bucket containing lambda zips" + required: true + lambda_version: description: Lambda artifact version (S3 prefix) required: true @@ -59,6 +63,7 @@ runs: id: publish uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} LAMBDA_ZIP_KEY: ${{ steps.vars.outputs.lambda_zip_key }} with: @@ -68,6 +73,7 @@ runs: - name: Upload AppSpec bundle uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} FUNCTION_NAME: ${{ steps.vars.outputs.lambda_function_name }} ALIAS_NAME: ${{ steps.vars.outputs.lambda_alias_name }} CURRENT_VERSION: ${{ steps.get-version.outputs.just_outputs }} @@ -81,6 +87,7 @@ runs: - name: Run CodeDeploy uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} CODE_DEPLOY_APP_NAME: ${{ steps.vars.outputs.code_deploy_app_name }} CODE_DEPLOY_GROUP_NAME: ${{ steps.vars.outputs.code_deploy_group_name }} with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e7c498a..7c3bcf0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -34,7 +34,6 @@ permissions: env: TF_VAR_lambda_version: ${{ inputs.lambda_version }} AWS_OIDC_ROLE_ARN: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/aws-serverless-github-deploy-${{ inputs.environment }}-github-oidc-role - BUCKET_NAME: ${{ inputs.lambda_bucket }} jobs: setup: @@ -52,6 +51,7 @@ jobs: - name: check Lambda version uses: chrispsheehan/just-aws-oidc-action@0.1.3 env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} VERSION: ${{ inputs.lambda_version }} with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} @@ -60,85 +60,26 @@ jobs: api: needs: setup runs-on: ubuntu-latest - env: - APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml - APP_SPEC_KEY: ${{ inputs.lambda_version }}/api-appspec.zip steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.infra_version }} - - name: deploy api - id: deploy-api + - name: Deploy infra (Terragrunt) + id: deploy uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/api - - name: get api variables - id: get-api-vars - env: - TG_OUTPUTS: ${{ steps.deploy-api.outputs.tg_outputs }} - run: | - echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT - echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT - echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT - echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT - echo "code_deploy_group_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_group_name.value')" >> $GITHUB_OUTPUT - - - name: get lambda version - id: lambda-get-version - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-api-vars.outputs.lambda_alias_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-get-version - - - name: create lambda version - id: lambda-create-version - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - BUCKET_NAME: ${{ inputs.lambda_bucket }} - LAMBDA_ZIP_KEY: ${{ steps.get-api-vars.outputs.lambda_zip_key }} - FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-create-version - - - name: Prepare and upload AppSpec File to s3 - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - BUCKET_NAME: ${{ inputs.lambda_bucket }} - FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-api-vars.outputs.lambda_alias_name }} - CURRENT_VERSION: ${{ steps.lambda-get-version.outputs.just_outputs }} - NEW_VERSION: ${{ steps.lambda-create-version.outputs.just_outputs }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-upload-bundle - - - name: deploy lambda - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - BUCKET_NAME: ${{ inputs.lambda_bucket }} - CODE_DEPLOY_APP_NAME: ${{ steps.get-api-vars.outputs.code_deploy_app_name }} - CODE_DEPLOY_GROUP_NAME: ${{ steps.get-api-vars.outputs.code_deploy_group_name }} - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-deploy - - - name: prune lambda - uses: chrispsheehan/just-aws-oidc-action@0.1.3 - env: - KEEP: ${{ inputs.lambda_keep }} - FUNCTION_NAME: ${{ steps.get-api-vars.outputs.lambda_function_name }} - ALIAS_NAME: ${{ steps.get-api-vars.outputs.lambda_alias_name }} + - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - just_action: lambda-prune - + infra_version: ${{ inputs.infra_version }} + tg_directory: infra/live/${{ inputs.environment }}/aws/api + lambda_bucket: ${{ inputs.lambda_bucket }} + lambda_version: ${{ inputs.lambda_version }} + lambda_keep: ${{ inputs.lambda_keep }} consumer: needs: setup @@ -158,8 +99,8 @@ jobs: - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - bucket_name: ${{ inputs.lambda_bucket }} infra_version: ${{ inputs.infra_version }} tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + lambda_bucket: ${{ inputs.lambda_bucket }} lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} diff --git a/.github/workflows/destroy.yml b/.github/workflows/destroy.yml index d0c157a..90465fa 100644 --- a/.github/workflows/destroy.yml +++ b/.github/workflows/destroy.yml @@ -50,6 +50,7 @@ jobs: build: needs: - api + - consumer runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 927df77cd229ab9d441a9bcaa4b9da58b5fff029 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 13:33:14 +0000 Subject: [PATCH 36/43] chore: separate jobs --- .github/workflows/deploy.yml | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7c3bcf0..36b77af 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -57,7 +57,7 @@ jobs: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} just_action: check-version - api: + api-infra: needs: setup runs-on: ubuntu-latest steps: @@ -65,13 +65,21 @@ jobs: with: ref: ${{ inputs.infra_version }} - - name: Deploy infra (Terragrunt) + - name: Deploy api infra id: deploy uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} tg_directory: infra/live/${{ inputs.environment }}/aws/api + api: + needs: api-infra + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} @@ -81,7 +89,7 @@ jobs: lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} - consumer: + consumer-infra: needs: setup runs-on: ubuntu-latest steps: @@ -89,18 +97,27 @@ jobs: with: ref: ${{ inputs.infra_version }} - - name: Deploy infra (Terragrunt) + - name: Deploy api infra id: deploy uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + tg_directory: infra/live/${{ inputs.environment }}/aws/api + + consumer: + needs: consumer-infra + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} - uses: ./.github/actions/deploy-lambda with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} infra_version: ${{ inputs.infra_version }} - tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + tg_directory: infra/live/${{ inputs.environment }}/aws/api lambda_bucket: ${{ inputs.lambda_bucket }} lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} + From 87be5410e12fd05a49ecb7a103ba5d4b282bdd83 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 13:39:29 +0000 Subject: [PATCH 37/43] fix: consumer naming --- .github/workflows/deploy.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 36b77af..4daf08b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -97,12 +97,12 @@ jobs: with: ref: ${{ inputs.infra_version }} - - name: Deploy api infra + - name: Deploy consumer infra id: deploy uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - tg_directory: infra/live/${{ inputs.environment }}/aws/api + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer consumer: needs: consumer-infra @@ -116,7 +116,7 @@ jobs: with: aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} infra_version: ${{ inputs.infra_version }} - tg_directory: infra/live/${{ inputs.environment }}/aws/api + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer lambda_bucket: ${{ inputs.lambda_bucket }} lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} From d953da737d5db5a38affe528c8702b8d505db861 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 13:45:17 +0000 Subject: [PATCH 38/43] chore: add APP_SPEC_KEY --- .github/actions/deploy-lambda/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index ada573b..fdb1d11 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -90,6 +90,7 @@ runs: BUCKET_NAME: ${{ inputs.lambda_bucket }} CODE_DEPLOY_APP_NAME: ${{ steps.vars.outputs.code_deploy_app_name }} CODE_DEPLOY_GROUP_NAME: ${{ steps.vars.outputs.code_deploy_group_name }} + APP_SPEC_KEY: ${{ github.workspace }}/${{ inputs.tg_directory }}/appspec.zip with: aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} just_action: lambda-deploy From acb5fc25646f13b70e771f4fe3ad788f1e8beb19 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 14:31:07 +0000 Subject: [PATCH 39/43] feat: set appsec key in infra --- .github/actions/deploy-lambda/action.yml | 5 +++-- infra/modules/aws/_shared/lambda/locals.tf | 1 + infra/modules/aws/_shared/lambda/outputs.tf | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index fdb1d11..c94e5f5 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -44,6 +44,7 @@ runs: TG_OUTPUTS: ${{ steps.init.outputs.tg_outputs }} run: | echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT + echo "lambda_appspec_key=$(echo $TG_OUTPUTS | jq -r '.lambda_appspec_key.value')" >> $GITHUB_OUTPUT echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT @@ -79,7 +80,7 @@ runs: CURRENT_VERSION: ${{ steps.get-version.outputs.just_outputs }} NEW_VERSION: ${{ steps.publish.outputs.just_outputs }} APP_SPEC_FILE: ${{ github.workspace }}/appspec.yml - APP_SPEC_KEY: ${{ github.workspace }}/${{ inputs.tg_directory }}/appspec.zip + APP_SPEC_KEY: ${{ steps.vars.outputs.lambda_appspec_key }} with: aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} just_action: lambda-upload-bundle @@ -90,7 +91,7 @@ runs: BUCKET_NAME: ${{ inputs.lambda_bucket }} CODE_DEPLOY_APP_NAME: ${{ steps.vars.outputs.code_deploy_app_name }} CODE_DEPLOY_GROUP_NAME: ${{ steps.vars.outputs.code_deploy_group_name }} - APP_SPEC_KEY: ${{ github.workspace }}/${{ inputs.tg_directory }}/appspec.zip + APP_SPEC_KEY: ${{ steps.vars.outputs.lambda_appspec_key }} with: aws_oidc_role_arn: ${{ inputs.aws_oidc_role_arn }} just_action: lambda-deploy diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index 7b9943c..3bca619 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -5,6 +5,7 @@ locals { lambda_name = "${var.environment}-${var.project_name}-${var.lambda_name}" lambda_code_zip_key = "${var.lambda_version}/${var.lambda_name}.zip" + lambda_appspec_key = "${var.lambda_name}/appspec.zip" deploy_all_at_once_type = "AllAtOnce" deploy_canary_type = "TimeBasedCanary" diff --git a/infra/modules/aws/_shared/lambda/outputs.tf b/infra/modules/aws/_shared/lambda/outputs.tf index d6fea95..7cb9b65 100644 --- a/infra/modules/aws/_shared/lambda/outputs.tf +++ b/infra/modules/aws/_shared/lambda/outputs.tf @@ -26,6 +26,10 @@ output "lambda_zip_key" { value = local.lambda_code_zip_key } +output "lambda_appspec_key" { + value = local.lambda_appspec_key +} + output "code_deploy_app_name" { value = aws_codedeploy_app.app.name } From 76003ef40fbaca37228711b885a0fcfa608bf6a1 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 14:37:53 +0000 Subject: [PATCH 40/43] fix: add lambda_appspec_key outputs --- infra/modules/aws/api/outputs.tf | 4 ++++ infra/modules/aws/consumer/outputs.tf | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/infra/modules/aws/api/outputs.tf b/infra/modules/aws/api/outputs.tf index babcf18..7b343aa 100644 --- a/infra/modules/aws/api/outputs.tf +++ b/infra/modules/aws/api/outputs.tf @@ -10,6 +10,10 @@ output "lambda_zip_key" { value = module.lambda_api.lambda_zip_key } +output "lambda_appspec_key" { + value = module.lambda_api.lambda_appspec_key +} + output "code_deploy_app_name" { value = module.lambda_api.code_deploy_app_name } diff --git a/infra/modules/aws/consumer/outputs.tf b/infra/modules/aws/consumer/outputs.tf index e4e37c2..76bb203 100644 --- a/infra/modules/aws/consumer/outputs.tf +++ b/infra/modules/aws/consumer/outputs.tf @@ -6,6 +6,10 @@ output "lambda_zip_key" { value = module.lambda_consumer.lambda_zip_key } +output "lambda_appspec_key" { + value = module.lambda_consumer.lambda_appspec_key +} + output "code_deploy_app_name" { value = module.lambda_consumer.code_deploy_app_name } From 7702891296f36e4c41733000e587de2b457446a8 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 15:03:47 +0000 Subject: [PATCH 41/43] debug: only 1 lambda --- .github/workflows/deploy.yml | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4daf08b..2b83dfd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -89,35 +89,35 @@ jobs: lambda_version: ${{ inputs.lambda_version }} lambda_keep: ${{ inputs.lambda_keep }} - consumer-infra: - needs: setup - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.infra_version }} - - - name: Deploy consumer infra - id: deploy - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - tg_directory: infra/live/${{ inputs.environment }}/aws/consumer - - consumer: - needs: consumer-infra - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.infra_version }} - - - uses: ./.github/actions/deploy-lambda - with: - aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} - infra_version: ${{ inputs.infra_version }} - tg_directory: infra/live/${{ inputs.environment }}/aws/consumer - lambda_bucket: ${{ inputs.lambda_bucket }} - lambda_version: ${{ inputs.lambda_version }} - lambda_keep: ${{ inputs.lambda_keep }} + # consumer-infra: + # needs: setup + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # ref: ${{ inputs.infra_version }} + + # - name: Deploy consumer infra + # id: deploy + # uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + # with: + # aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + # tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + + # consumer: + # needs: consumer-infra + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # ref: ${{ inputs.infra_version }} + + # - uses: ./.github/actions/deploy-lambda + # with: + # aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + # infra_version: ${{ inputs.infra_version }} + # tg_directory: infra/live/${{ inputs.environment }}/aws/consumer + # lambda_bucket: ${{ inputs.lambda_bucket }} + # lambda_version: ${{ inputs.lambda_version }} + # lambda_keep: ${{ inputs.lambda_keep }} From f947872407a69a5543d304880cebd40dbddb4afa Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 15:11:17 +0000 Subject: [PATCH 42/43] fix: code deploy iam --- infra/modules/aws/_shared/lambda/data.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/modules/aws/_shared/lambda/data.tf b/infra/modules/aws/_shared/lambda/data.tf index dfcb8a7..c8d5af5 100644 --- a/infra/modules/aws/_shared/lambda/data.tf +++ b/infra/modules/aws/_shared/lambda/data.tf @@ -49,7 +49,7 @@ data "aws_iam_policy_document" "codedeploy_lambda" { effect = "Allow" actions = ["s3:GetObject", "s3:GetObjectVersion"] resources = [ - "arn:aws:s3:::${data.aws_s3_bucket.lambda_code.bucket}/${var.lambda_version}/*" + "arn:aws:s3:::${data.aws_s3_bucket.lambda_code.bucket}/*" ] } From d0013e05c3fce796a454e7443e53930c76f5a427 Mon Sep 17 00:00:00 2001 From: chrispsheehan Date: Thu, 22 Jan 2026 17:04:49 +0000 Subject: [PATCH 43/43] chore: breadcrumb --- .github/actions/deploy-lambda/action.yml | 14 +++- .github/workflows/dev_deploy.yml | 13 +++- .github/workflows/infra_deploy.yml | 84 +++++++++++++++++++++ infra/modules/aws/_shared/lambda/locals.tf | 2 +- infra/modules/aws/_shared/lambda/outputs.tf | 4 - infra/modules/aws/api/outputs.tf | 4 - infra/modules/aws/consumer/outputs.tf | 4 - 7 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/infra_deploy.yml diff --git a/.github/actions/deploy-lambda/action.yml b/.github/actions/deploy-lambda/action.yml index c94e5f5..b3e5adf 100644 --- a/.github/actions/deploy-lambda/action.yml +++ b/.github/actions/deploy-lambda/action.yml @@ -29,6 +29,10 @@ inputs: runs: using: composite steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + - name: Get Terragrunt outputs id: init uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 @@ -43,13 +47,19 @@ runs: env: TG_OUTPUTS: ${{ steps.init.outputs.tg_outputs }} run: | - echo "lambda_zip_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT - echo "lambda_appspec_key=$(echo $TG_OUTPUTS | jq -r '.lambda_appspec_key.value')" >> $GITHUB_OUTPUT echo "lambda_function_name=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT echo "lambda_alias_name=$(echo $TG_OUTPUTS | jq -r '.lambda_alias_name.value')" >> $GITHUB_OUTPUT echo "code_deploy_app_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_app_name.value')" >> $GITHUB_OUTPUT echo "code_deploy_group_name=$(echo $TG_OUTPUTS | jq -r '.code_deploy_group_name.value')" >> $GITHUB_OUTPUT + - name: Set AppSpec paths + id: appspec + shell: bash + run: | + lambda_zip_key="${{ inputs.lambda_version }}/${{ steps.vars.outputs.lambda_function_name }}.zip" + echo "lambda_appspec_key=$(echo $TG_OUTPUTS | jq -r '.lambda_zip_key.value')" >> $GITHUB_OUTPUT + echo "lambda_appspec_zip=$(echo $TG_OUTPUTS | jq -r '.lambda_function_name.value')" >> $GITHUB_OUTPUT + - name: Get current lambda version id: get-version uses: chrispsheehan/just-aws-oidc-action@0.1.3 diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index 14a6598..2d1695a 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -14,9 +14,20 @@ jobs: environment: dev version: ${{ github.sha }} + lambdas: + needs: build + uses: ./.github/workflows/infra_deploy.yml + with: + environment: dev + infra_version: ${{ github.sha }} + lambda_bucket: ${{ needs.build.outputs.lambda_bucket }} + lambda_version: ${{ github.sha }} + dev: uses: ./.github/workflows/deploy.yml - needs: build + needs: + - build + - lambdas with: environment: dev infra_version: ${{ github.sha }} diff --git a/.github/workflows/infra_deploy.yml b/.github/workflows/infra_deploy.yml new file mode 100644 index 0000000..d65a298 --- /dev/null +++ b/.github/workflows/infra_deploy.yml @@ -0,0 +1,84 @@ +on: + workflow_call: + inputs: + environment: + description: environment reference i.e. 'prod' or 'dev' + required: true + type: string + infra_version: + description: "Version of infrastructure (terraform) to be deployed" + required: true + type: string + lambda_bucket: + description: "Bucket containing lambda zips" + required: true + type: string + lambda_version: + description: "Valid lambda version" + required: true + type: string + + +concurrency: # only run one instance of workflow at any one time + group: ${{ github.workflow }}-${{ inputs.environment }} + cancel-in-progress: false + +permissions: + id-token: write + contents: write + +env: + TF_VAR_lambda_version: ${{ inputs.lambda_version }} + AWS_OIDC_ROLE_ARN: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/aws-serverless-github-deploy-${{ inputs.environment }}-github-oidc-role + +jobs: + setup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + + - uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/oidc + + - name: check Lambda version + uses: chrispsheehan/just-aws-oidc-action@0.1.3 + env: + BUCKET_NAME: ${{ inputs.lambda_bucket }} + VERSION: ${{ inputs.lambda_version }} + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + just_action: check-version + + api: + needs: setup + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + + - name: Deploy api infra + id: deploy + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/api + + consumer: + needs: setup + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.infra_version }} + + - name: Deploy consumer infra + id: deploy + uses: chrispsheehan/terragrunt-aws-oidc-action@0.4.1 + with: + aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }} + tg_directory: infra/live/${{ inputs.environment }}/aws/consumer diff --git a/infra/modules/aws/_shared/lambda/locals.tf b/infra/modules/aws/_shared/lambda/locals.tf index 3bca619..0e25064 100644 --- a/infra/modules/aws/_shared/lambda/locals.tf +++ b/infra/modules/aws/_shared/lambda/locals.tf @@ -5,7 +5,7 @@ locals { lambda_name = "${var.environment}-${var.project_name}-${var.lambda_name}" lambda_code_zip_key = "${var.lambda_version}/${var.lambda_name}.zip" - lambda_appspec_key = "${var.lambda_name}/appspec.zip" + lambda_appspec_key = "appspecs/${var.lambda_name}-appspec.zip" deploy_all_at_once_type = "AllAtOnce" deploy_canary_type = "TimeBasedCanary" diff --git a/infra/modules/aws/_shared/lambda/outputs.tf b/infra/modules/aws/_shared/lambda/outputs.tf index 7cb9b65..d6fea95 100644 --- a/infra/modules/aws/_shared/lambda/outputs.tf +++ b/infra/modules/aws/_shared/lambda/outputs.tf @@ -26,10 +26,6 @@ output "lambda_zip_key" { value = local.lambda_code_zip_key } -output "lambda_appspec_key" { - value = local.lambda_appspec_key -} - output "code_deploy_app_name" { value = aws_codedeploy_app.app.name } diff --git a/infra/modules/aws/api/outputs.tf b/infra/modules/aws/api/outputs.tf index 7b343aa..babcf18 100644 --- a/infra/modules/aws/api/outputs.tf +++ b/infra/modules/aws/api/outputs.tf @@ -10,10 +10,6 @@ output "lambda_zip_key" { value = module.lambda_api.lambda_zip_key } -output "lambda_appspec_key" { - value = module.lambda_api.lambda_appspec_key -} - output "code_deploy_app_name" { value = module.lambda_api.code_deploy_app_name } diff --git a/infra/modules/aws/consumer/outputs.tf b/infra/modules/aws/consumer/outputs.tf index 76bb203..e4e37c2 100644 --- a/infra/modules/aws/consumer/outputs.tf +++ b/infra/modules/aws/consumer/outputs.tf @@ -6,10 +6,6 @@ output "lambda_zip_key" { value = module.lambda_consumer.lambda_zip_key } -output "lambda_appspec_key" { - value = module.lambda_consumer.lambda_appspec_key -} - output "code_deploy_app_name" { value = module.lambda_consumer.code_deploy_app_name }