Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c37dced
feat: code deploy setup
chrispsheehan Sep 5, 2025
9df4c76
chore: allow lambda to log to cloudwatch
chrispsheehan Sep 5, 2025
9766b38
fix: fmt
chrispsheehan Sep 5, 2025
cacb3de
chore: rename resource
chrispsheehan Sep 6, 2025
db1cf54
chore: s3 delete old files
chrispsheehan Sep 6, 2025
48e78a5
chore: outputs for code deploy
chrispsheehan Sep 6, 2025
fde4398
chore: lambda deploy flow
chrispsheehan Sep 6, 2025
0ca8916
fix: rm format-frontend
chrispsheehan Sep 6, 2025
d5b1df4
chore: oidc iam codedeploy
chrispsheehan Sep 6, 2025
c96c815
fix: use blue green deployment group
chrispsheehan Sep 8, 2025
f28a557
fix: failsafe check in deploy script + fix
chrispsheehan Sep 8, 2025
c380f59
debug: try passing region to just script
chrispsheehan Sep 8, 2025
ba7f5d0
fix: rm defined region from script
chrispsheehan Sep 8, 2025
80ada7a
debug: output just action errors
chrispsheehan Sep 8, 2025
751c80e
debug: use try catch in just runner
chrispsheehan Sep 8, 2025
201b34c
chore: ger deployment error message
chrispsheehan Sep 8, 2025
5a31d62
fix: allow iams for code deploy
chrispsheehan Sep 8, 2025
d196b79
chore: use latest just action version
chrispsheehan Sep 8, 2025
f4a463a
chore: output alias and function name
chrispsheehan Sep 8, 2025
501bf7a
chore: rename step
chrispsheehan Sep 9, 2025
07dc890
feat: get current alias version
chrispsheehan Sep 9, 2025
1b57ead
chore: add outputs to parent module
chrispsheehan Sep 9, 2025
229cc96
fix: env var set
chrispsheehan Sep 9, 2025
8ed9c0a
feat: lambda-create-version
chrispsheehan Sep 9, 2025
d49fe0f
fix: correct pass in bucket name
chrispsheehan Sep 9, 2025
baefe4c
feat: lambda-upload-bundle
chrispsheehan Sep 9, 2025
9942b62
fix: use defined zip paths
chrispsheehan Sep 9, 2025
38bfc21
fix: yaml -> yml
chrispsheehan Sep 9, 2025
0d8b430
chore: rm -f ${{ env.APP_SPEC_FILE }}
chrispsheehan Sep 9, 2025
04beda3
chore: re enable lambda deploy
chrispsheehan Sep 9, 2025
445c1f6
fix: upload appspec to version folder
chrispsheehan Sep 9, 2025
2dbd8a0
chore: use LOCAL_APP_SPEC_ZIP
chrispsheehan Sep 9, 2025
bda8957
fix: rm -f $LOCAL_APP_SPEC_ZIP
chrispsheehan Sep 9, 2025
2aaa75d
feat: lambda-prepare-appspec
chrispsheehan Sep 9, 2025
9147d84
chore: use standard ALIAS_NAME var name
chrispsheehan Sep 9, 2025
74eea60
fix: proper fix
chrispsheehan Sep 9, 2025
e2dbe63
debug: try to pipe output
chrispsheehan Sep 9, 2025
91927c7
chore: shorten deploy feedback loop
chrispsheehan Sep 9, 2025
2237823
debug: test just with output works still
chrispsheehan Sep 9, 2025
3d4ddb1
chore: try 50% switch
chrispsheehan Sep 9, 2025
dd7831f
chore: bump to just-aws-oidc-action@0.1.3
chrispsheehan Sep 9, 2025
f25a887
chore: set BUCKET_NAME: ${{ inputs.lambda_bucket }} at top
chrispsheehan Sep 9, 2025
8f4ffcd
chore: rename deploy config block
chrispsheehan Sep 9, 2025
1c1ce41
fix: rm --deployment-config-name from cli deploy
chrispsheehan Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
run: just backend-build

- name: Upload Lambda zips
uses: chrispsheehan/just-aws-oidc-action@0.1.1
uses: chrispsheehan/just-aws-oidc-action@0.1.3
env:
BUCKET_NAME: ${{ needs.infra.outputs.lambda_bucket_name }}
with:
Expand Down
77 changes: 61 additions & 16 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ 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:
oidc:
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -44,35 +45,79 @@ jobs:
aws_oidc_role_arn: ${{ env.AWS_OIDC_ROLE_ARN }}
tg_directory: infra/live/${{ inputs.environment }}/aws/oidc

backend:
needs:
- oidc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.infra_version }}

- name: check Lambda vars
uses: chrispsheehan/just-aws-oidc-action@0.1.1
- 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:
- oidc
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 API
- name: deploy api
id: deploy-api
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/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:
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:
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:
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
2 changes: 1 addition & 1 deletion .github/workflows/get_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
echo "bucket_lambda=$(echo $TG_OUTPUTS | jq -r '.bucket_lambda.value')" >> $GITHUB_OUTPUT

- name: Check Lambda version exists
uses: chrispsheehan/just-aws-oidc-action@0.1.1
uses: chrispsheehan/just-aws-oidc-action@0.1.3
env:
BUCKET_NAME: ${{ steps.get_bucket_name.outputs.bucket_lambda }}
VERSION: ${{ inputs.version }}
Expand Down
13 changes: 0 additions & 13 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,6 @@ jobs:
run: terragrunt hclfmt --terragrunt-check
working-directory: infra

format-frontend:
needs: check
runs-on: ubuntu-latest
if: ${{ needs.check.outputs.frontend == 'true' }}
name: Run astro formatting checks
timeout-minutes: 2
steps:
- uses: actions/checkout@v4
- name: Run prettier checks
run: |
npm install --prefix frontend
npm run format:check --prefix frontend

build-backend:
needs: check
runs-on: ubuntu-latest
Expand Down
9 changes: 9 additions & 0 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: 0.0
Resources:
- LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: ${FUNCTION_NAME}
Alias: ${FUNCTION_ALIAS}
CurrentVersion: ${CURRENT_VERSION}
TargetVersion: ${NEW_VERSION}
3 changes: 2 additions & 1 deletion infra/live/global_vars.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ locals {
"iam:*",
"lambda:*",
"logs:*",
"apigateway:*"
"apigateway:*",
"codedeploy:*"
]
}

Expand Down
28 changes: 28 additions & 0 deletions infra/modules/aws/api/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
output "invoke_url" {
value = aws_apigatewayv2_api.http_api.api_endpoint
}

output "cloudwatch_log_group" {
value = module.lambda_api.cloudwatch_log_group
}

output "lambda_zip_key" {
value = module.lambda_api.lambda_zip_key
}

output "code_deploy_app_name" {
value = module.lambda_api.code_deploy_app_name
}

output "code_deploy_group_name" {
value = module.lambda_api.code_deploy_group_name
}

output "lambda_arn" {
value = module.lambda_api.arn
}

output "lambda_function_name" {
value = module.lambda_api.function_name
}

output "lambda_alias_name" {
value = module.lambda_api.alias_name
}
15 changes: 15 additions & 0 deletions infra/modules/aws/code_bucket/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,18 @@ resource "aws_s3_bucket_ownership_controls" "lambda" {
object_ownership = "BucketOwnerEnforced"
}
}

resource "aws_s3_bucket_lifecycle_configuration" "delete_old_files" {
count = var.s3_expiration_days > 0 ? 1 : 0

bucket = aws_s3_bucket.lambda.id

rule {
id = "delete-expired-objects"
status = "Enabled"

expiration {
days = var.s3_expiration_days
}
}
}
9 changes: 9 additions & 0 deletions infra/modules/aws/code_bucket/variables.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
### start of static vars set in root.hcl ###
variable "lambda_bucket" {
description = "S3 bucket to host lambda code files"
type = string
}
### end of static vars set in root.hcl ###


variable "s3_expiration_days" {
description = "Number of days before objects are deleted (set to 0 to disable)"
type = number
default = 0
}
77 changes: 77 additions & 0 deletions infra/modules/aws/lambda/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,80 @@ data "aws_iam_policy_document" "assume_role" {
actions = ["sts:AssumeRole"]
}
}

data "aws_iam_policy_document" "code_deploy_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["codedeploy.amazonaws.com"]
}
}
}

data "aws_iam_policy_document" "codedeploy_lambda" {
statement {
sid = "LambdaControl"
effect = "Allow"
actions = [
"lambda:GetFunction",
"lambda:PublishVersion",
"lambda:GetAlias",
"lambda:CreateAlias",
"lambda:UpdateAlias",
"lambda:ListAliases",
"lambda:ListVersionsByFunction",
]
resources = [
aws_lambda_function.lambda.arn,
"${aws_lambda_function.lambda.arn}:*",
]
}

statement {
sid = "ReadArtifactObject"
effect = "Allow"
actions = ["s3:GetObject", "s3:GetObjectVersion"]
resources = [
"arn:aws:s3:::${data.aws_s3_bucket.lambda_code.bucket}/${var.lambda_version}/*"
]
}

# Allow listing the bucket for that prefix (some SDKs call this)
statement {
sid = "ListArtifactPrefix"
effect = "Allow"
actions = ["s3:ListBucket", "s3:GetBucketLocation"]
resources = ["arn:aws:s3:::${data.aws_s3_bucket.lambda_code.bucket}"]
condition {
test = "StringLike"
variable = "s3:prefix"
values = ["${var.lambda_version}/*"]
}
}

statement {
sid = "DescribeAlarms"
effect = "Allow"
actions = ["cloudwatch:DescribeAlarms"]
resources = ["*"]
}
}

data "aws_iam_policy_document" "lambda_iam_policy" {
statement {
sid = "AllowLambdaCloudwatchLogGroupPut"

actions = [
"logs:CreateLogStream",
"logs:PutLogEvents"
]

effect = "Allow"

resources = [
"${aws_cloudwatch_log_group.lambda_cloudwatch_group.arn}",
"${aws_cloudwatch_log_group.lambda_cloudwatch_group.arn}:*"
]
}
}
78 changes: 77 additions & 1 deletion infra/modules/aws/lambda/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,80 @@ resource "aws_lambda_function" "lambda" {

s3_bucket = data.aws_s3_bucket.lambda_code.bucket
s3_key = local.lambda_code_zip_key
}

# publish ONE immutable version so we can create an alias
publish = true

lifecycle {
# Do not update on changes to the initial s3 file version
ignore_changes = [
s3_bucket,
s3_key,
s3_object_version,
]
}
}

resource "aws_cloudwatch_log_group" "lambda_cloudwatch_group" {
name = "/aws/lambda/${local.lambda_name}"
retention_in_days = var.log_retention_days
}

resource "aws_lambda_alias" "live" {
name = var.environment
function_name = aws_lambda_function.lambda.arn
function_version = aws_lambda_function.lambda.version

# CodeDeploy will repoint this alias → ignore drift
lifecycle {
ignore_changes = [function_version, routing_config]
}
}

resource "aws_codedeploy_app" "app" {
name = "${local.lambda_name}-app"
compute_platform = "Lambda"
}

resource "aws_iam_role" "code_deploy_role" {
name = "${local.lambda_name}-codedeploy-role"
assume_role_policy = data.aws_iam_policy_document.code_deploy_assume.json
}

resource "aws_iam_role_policy" "cd_lambda" {
name = "${local.lambda_name}-codedeploy-lambda"
role = aws_iam_role.code_deploy_role.id
policy = data.aws_iam_policy_document.codedeploy_lambda.json
}

resource "aws_codedeploy_deployment_config" "lambda_deployment_config" {
# A custom Lambda deployment config that sends 50% traffic for 1 minute, then shifts to 100% (with your DG using it and auto-rollback on failure/alarms).
deployment_config_name = "${local.lambda_name}-deployment-config"
compute_platform = "Lambda"

traffic_routing_config {
type = "TimeBasedCanary"
time_based_canary {
percentage = 50
interval = 1
}
}
}

resource "aws_codedeploy_deployment_group" "dg" {
app_name = aws_codedeploy_app.app.name
deployment_group_name = "${local.lambda_name}-dg"
service_role_arn = aws_iam_role.code_deploy_role.arn

deployment_style {
deployment_type = "BLUE_GREEN"
deployment_option = "WITH_TRAFFIC_CONTROL"
}

deployment_config_name = aws_codedeploy_deployment_config.lambda_deployment_config.id

auto_rollback_configuration {
enabled = true
events = ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
}
}
Loading