Model/.github/workflows/_deploy_lambda.yml
Jun-te Kim adb1bf4b56 Log GITHUB_SHA on /health; move zip-size gate to its own PR workflow
/health already returned GITHUB_SHA in its response but never logged
it, and the fastapi lambda's Terraform environment never actually set
GITHUB_SHA — so every health check response contained "unknown" in
production. Wire var.github_sha through the fastapi lambda module
(default "unknown" for local/other invocations) via a new
TF_VAR_github_sha env var set from `github.sha` in
_deploy_lambda.yml's Terraform Plan step, and log it on every /health
call so a request in CloudWatch can be tied back to the deploy that
served it.

Also fix the zip-size gate added for PR #1469: putting it in
tests/test_lambda_zip_size.py (run via the Docker-based ddd_tests.yml
suite) broke CI, because Dockerfile.test's build context excludes
deployment/* (.dockerignore), so check_lambda_zip_size.py couldn't
find variables.tf to read zip_excludes from inside that container.
Move the check to its own lightweight workflow,
check_lambda_zip_size.yml, triggered on pull_request into main — a
plain checkout (no Docker build) has the full repo, so the check
works, runs fast, and still gates merges to main before a regression
can roll into the dev deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 13:43:36 +00:00

240 lines
9.1 KiB
YAML

name: Deploy Lambda (Terraform)
on:
workflow_call:
inputs:
lambda_name:
required: true
type: string
lambda_path:
required: true
type: string
stage:
required: true
type: string
ecr_repo:
required: false
type: string
default: ''
image_digest:
required: false
type: string
default: ''
terraform_apply:
required: false
type: string
default: 'false'
# can only be 'true' or 'false'
terraform_destroy:
required: false
type: string
default: 'false'
# can only be 'true' or 'false'
secrets:
AWS_ACCESS_KEY_ID:
required: true
AWS_SECRET_ACCESS_KEY:
required: true
AWS_REGION:
required: true
TF_VAR_db_host:
required: false
TF_VAR_db_name:
required: false
TF_VAR_db_port:
required: false
TF_VAR_api_key:
required: false
TF_VAR_secret_key:
required: false
TF_VAR_domain_name:
required: false
TF_VAR_epc_auth_token:
required: false
TF_VAR_google_solar_api_key:
required: false
TF_VAR_ordnance_survey_api_key:
required: false
TF_VAR_sharepoint_client_id:
required: false
TF_VAR_sharepoint_client_secret:
required: false
TF_VAR_sharepoint_tenant_id:
required: false
TF_VAR_domna_sharepoint_id:
required: false
TF_VAR_osmosis_acd_sharepoint_id:
required: false
TF_VAR_private_pay_sharepoint_id:
required: false
TF_VAR_social_housing_wave_3_sharepoint_id:
required: false
TF_VAR_eco_sharepoint_id:
required: false
TF_VAR_pashub_email:
required: false
TF_VAR_pashub_password:
required: false
TF_VAR_pashub_coordination_email:
required: false
TF_VAR_pashub_coordination_password:
required: false
TF_VAR_hubspot_api_key:
required: false
TF_VAR_magicplan_customer_id:
required: false
TF_VAR_magicplan_api_key:
required: false
TF_VAR_openai_api_key:
required: false
TF_VAR_open_epc_api_token:
required: false
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Debug inputs
run: |
echo "lambda_name=${{ inputs.lambda_name }}"
echo "lambda_path=${{ inputs.lambda_path }}"
echo "stage=${{ inputs.stage }}"
echo "ecr_repo_url=${{ inputs.ecr_repo_url }}"
echo "image_digest=${{ inputs.image_digest }}"
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- uses: hashicorp/setup-terraform@v3
- uses: aws-actions/amazon-ecr-login@v2
- name: Resolve ECR repo URL
id: repo
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
run: |
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_REPO_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${{ inputs.ecr_repo }}"
echo "ecr_repo_url=$ECR_REPO_URL" >> "$GITHUB_OUTPUT"
- name: Terraform Init
working-directory: ${{ inputs.lambda_path }}
run: terraform init -reconfigure
- name: Terraform Workspace
working-directory: ${{ inputs.lambda_path }}
run: |
terraform workspace select ${{ inputs.stage }} \
|| terraform workspace new ${{ inputs.stage }}
- name: Terraform Plan
working-directory: ${{ inputs.lambda_path }}
env:
TF_VAR_github_sha: ${{ github.sha }}
TF_VAR_db_host: ${{ secrets.TF_VAR_db_host }}
TF_VAR_db_name: ${{ secrets.TF_VAR_db_name }}
TF_VAR_db_port: ${{ secrets.TF_VAR_db_port }}
TF_VAR_api_key: ${{ secrets.TF_VAR_api_key }}
TF_VAR_secret_key: ${{ secrets.TF_VAR_secret_key }}
TF_VAR_domain_name: ${{ secrets.TF_VAR_domain_name }}
TF_VAR_epc_auth_token: ${{ secrets.TF_VAR_epc_auth_token }}
TF_VAR_google_solar_api_key: ${{ secrets.TF_VAR_google_solar_api_key }}
TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key }}
TF_VAR_sharepoint_client_id: ${{ secrets.TF_VAR_sharepoint_client_id }}
TF_VAR_sharepoint_client_secret: ${{ secrets.TF_VAR_sharepoint_client_secret }}
TF_VAR_sharepoint_tenant_id: ${{ secrets.TF_VAR_sharepoint_tenant_id }}
TF_VAR_domna_sharepoint_id: ${{ secrets.TF_VAR_domna_sharepoint_id }}
TF_VAR_osmosis_acd_sharepoint_id: ${{ secrets.TF_VAR_osmosis_acd_sharepoint_id }}
TF_VAR_private_pay_sharepoint_id: ${{ secrets.TF_VAR_private_pay_sharepoint_id }}
TF_VAR_social_housing_wave_3_sharepoint_id: ${{ secrets.TF_VAR_social_housing_wave_3_sharepoint_id }}
TF_VAR_eco_sharepoint_id: ${{ secrets.TF_VAR_eco_sharepoint_id }}
TF_VAR_pashub_email: ${{ secrets.TF_VAR_pashub_email }}
TF_VAR_pashub_password: ${{ secrets.TF_VAR_pashub_password }}
TF_VAR_pashub_coordination_email: ${{ secrets.TF_VAR_pashub_coordination_email }}
TF_VAR_pashub_coordination_password: ${{ secrets.TF_VAR_pashub_coordination_password }}
TF_VAR_hubspot_api_key: ${{ secrets.TF_VAR_hubspot_api_key }}
TF_VAR_magicplan_customer_id: ${{ secrets.TF_VAR_magicplan_customer_id }}
TF_VAR_magicplan_api_key: ${{ secrets.TF_VAR_magicplan_api_key }}
TF_VAR_openai_api_key: ${{ secrets.TF_VAR_openai_api_key }}
TF_VAR_open_epc_api_token: ${{ secrets.TF_VAR_open_epc_api_token }}
run: |
ECR_REPO_URL_VAR=""
if [[ -n "${{ inputs.ecr_repo }}" ]]; then
ECR_REPO_URL_VAR="-var=ecr_repo_url=${{ steps.repo.outputs.ecr_repo_url }}"
fi
IMAGE_DIGEST_VAR=""
if [[ -n "${{ inputs.ecr_repo }}" ]]; then
IMAGE_DIGEST_VAR="-var=image_digest=${{ inputs.image_digest }}"
fi
terraform plan \
-var="stage=${{ inputs.stage }}" \
-var="lambda_name=${{ inputs.lambda_name }}" \
$ECR_REPO_URL_VAR \
$IMAGE_DIGEST_VAR \
-out=lambdaplan
- name: Terraform Apply
if: inputs.terraform_apply == 'true' && inputs.terraform_destroy != 'true'
working-directory: ${{ inputs.lambda_path }}
run: terraform apply -auto-approve lambdaplan
- name: Terraform Destroy
if: inputs.terraform_destroy == 'true' && inputs.terraform_apply != 'true'
working-directory: ${{ inputs.lambda_path }}
env:
TF_VAR_db_host: ${{ secrets.TF_VAR_db_host }}
TF_VAR_db_name: ${{ secrets.TF_VAR_db_name }}
TF_VAR_db_port: ${{ secrets.TF_VAR_db_port }}
TF_VAR_api_key: ${{ secrets.TF_VAR_api_key }}
TF_VAR_secret_key: ${{ secrets.TF_VAR_secret_key }}
TF_VAR_domain_name: ${{ secrets.TF_VAR_domain_name }}
TF_VAR_epc_auth_token: ${{ secrets.TF_VAR_epc_auth_token }}
TF_VAR_google_solar_api_key: ${{ secrets.TF_VAR_google_solar_api_key }}
TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key }}
TF_VAR_sharepoint_client_id: ${{ secrets.TF_VAR_sharepoint_client_id }}
TF_VAR_sharepoint_client_secret: ${{ secrets.TF_VAR_sharepoint_client_secret }}
TF_VAR_sharepoint_tenant_id: ${{ secrets.TF_VAR_sharepoint_tenant_id }}
TF_VAR_domna_sharepoint_id: ${{ secrets.TF_VAR_domna_sharepoint_id }}
TF_VAR_osmosis_acd_sharepoint_id: ${{ secrets.TF_VAR_osmosis_acd_sharepoint_id }}
TF_VAR_private_pay_sharepoint_id: ${{ secrets.TF_VAR_private_pay_sharepoint_id }}
TF_VAR_social_housing_wave_3_sharepoint_id: ${{ secrets.TF_VAR_social_housing_wave_3_sharepoint_id }}
TF_VAR_eco_sharepoint_id: ${{ secrets.TF_VAR_eco_sharepoint_id }}
TF_VAR_pashub_email: ${{ secrets.TF_VAR_pashub_email }}
TF_VAR_pashub_password: ${{ secrets.TF_VAR_pashub_password }}
TF_VAR_pashub_coordination_email: ${{ secrets.TF_VAR_pashub_coordination_email }}
TF_VAR_pashub_coordination_password: ${{ secrets.TF_VAR_pashub_coordination_password }}
TF_VAR_hubspot_api_key: ${{ secrets.TF_VAR_hubspot_api_key }}
TF_VAR_magicplan_customer_id: ${{ secrets.TF_VAR_magicplan_customer_id }}
TF_VAR_magicplan_api_key: ${{ secrets.TF_VAR_magicplan_api_key }}
TF_VAR_openai_api_key: ${{ secrets.TF_VAR_openai_api_key }}
TF_VAR_open_epc_api_token: ${{ secrets.TF_VAR_open_epc_api_token }}
run: |
EXTRA_VARS=""
if [[ -n "${{ inputs.ecr_repo }}" ]]; then
EXTRA_VARS="-var=ecr_repo_url=${{ steps.repo.outputs.ecr_repo_url }} -var=image_digest=${{ inputs.image_digest }}"
fi
terraform destroy -auto-approve \
-var="stage=${{ inputs.stage }}" \
-var="lambda_name=${{ inputs.lambda_name }}" \
$EXTRA_VARS