mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
deploy
This commit is contained in:
parent
c52cd37a74
commit
5db4d2cfbe
8 changed files with 124 additions and 93 deletions
27
.github/workflows/_build_image.yml
vendored
27
.github/workflows/_build_image.yml
vendored
|
|
@ -21,16 +21,20 @@ on:
|
|||
|
||||
outputs:
|
||||
image_digest:
|
||||
description: "Pushed image digest"
|
||||
description: "Pushed image digest (sha256:...)"
|
||||
value: ${{ jobs.build.outputs.image_digest }}
|
||||
|
||||
ecr_repo_url:
|
||||
description: "ECR repository URL (no tag, no digest)"
|
||||
value: ${{ jobs.build.outputs.ecr_repo_url }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
AWS_REGION:
|
||||
required: true
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -38,6 +42,7 @@ jobs:
|
|||
|
||||
outputs:
|
||||
image_digest: ${{ steps.digest.outputs.image_digest }}
|
||||
ecr_repo_url: ${{ steps.repo.outputs.ecr_repo_url }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -49,16 +54,20 @@ jobs:
|
|||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ secrets.AWS_REGION }}
|
||||
|
||||
- uses: aws-actions/amazon-ecr-login@v2
|
||||
- name: Login to ECR
|
||||
uses: aws-actions/amazon-ecr-login@v2
|
||||
|
||||
- name: Resolve ECR repo URL
|
||||
id: repo
|
||||
run: |
|
||||
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
ECR_REPO_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/${{ inputs.ecr_repo }}"
|
||||
echo "ecr_repo_url=$ECR_REPO_URL" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build & push image
|
||||
run: |
|
||||
IMAGE_TAG=${GITHUB_SHA}
|
||||
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
|
||||
IMAGE_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/${{ inputs.ecr_repo }}:${IMAGE_TAG}
|
||||
|
||||
echo "Using IMAGE_URI=$IMAGE_URI"
|
||||
IMAGE_URI="${{ steps.repo.outputs.ecr_repo_url }}:${IMAGE_TAG}"
|
||||
|
||||
docker build \
|
||||
-f ${{ inputs.dockerfile_path }} \
|
||||
|
|
@ -76,4 +85,4 @@ jobs:
|
|||
--query 'imageDetails[0].imageDigest' \
|
||||
--output text)
|
||||
|
||||
echo "image_digest=$DIGEST" >> $GITHUB_OUTPUT
|
||||
echo "image_digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
20
.github/workflows/_deploy_lambda.yml
vendored
20
.github/workflows/_deploy_lambda.yml
vendored
|
|
@ -6,13 +6,17 @@ on:
|
|||
lambda_name:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
lambda_path:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
stage:
|
||||
required: true
|
||||
type: string
|
||||
image_digest:
|
||||
|
||||
image_uri:
|
||||
description: "Full ECR image URI including digest"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
|
@ -22,8 +26,7 @@ on:
|
|||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
AWS_REGION:
|
||||
required: true
|
||||
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
|
|
@ -55,14 +58,11 @@ jobs:
|
|||
run: |
|
||||
terraform plan \
|
||||
-var="stage=${{ inputs.stage }}" \
|
||||
-var="image_digest=${{ inputs.image_digest }}" \
|
||||
-var="lambda_name=${{ inputs.lambda_name }}" \
|
||||
-var="image_uri=${{ inputs.image_uri }}" \
|
||||
-out=lambdaplan
|
||||
|
||||
# Uncomment when ready
|
||||
# - name: Terraform Apply
|
||||
# working-directory: ${{ inputs.lambda_path }}
|
||||
# run: |
|
||||
# terraform apply \
|
||||
# -auto-approve \
|
||||
# -var="stage=${{ inputs.stage }}" \
|
||||
# -var="image_digest=${{ inputs.image_digest }}" \
|
||||
# lambdaplan
|
||||
# run: terraform apply -auto-approve lambdaplan
|
||||
|
|
|
|||
38
.github/workflows/deploy_terraform.yml
vendored
38
.github/workflows/deploy_terraform.yml
vendored
|
|
@ -5,7 +5,6 @@ on:
|
|||
branches:
|
||||
- "**"
|
||||
|
||||
|
||||
jobs:
|
||||
determine_stage:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -27,9 +26,8 @@ jobs:
|
|||
echo "stage=dev" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
echo "Resolved STAGE=$BRANCH → $(cat $GITHUB_OUTPUT)"
|
||||
# ============================================================
|
||||
# 1️⃣ Shared Terraform (plan only for now)
|
||||
# 1️⃣ Shared Terraform (infra)
|
||||
# ============================================================
|
||||
shared_terraform:
|
||||
needs: determine_stage
|
||||
|
|
@ -38,39 +36,35 @@ jobs:
|
|||
STAGE: ${{ needs.determine_stage.outputs.stage }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
# This will need to be changed to env imports when we have different env to dynamically allocate prod, staging etc
|
||||
aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ secrets.DEV_AWS_REGION }}
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
|
||||
- name: Terraform Init (shared)
|
||||
- name: Terraform Init
|
||||
working-directory: infrastructure/terraform/shared
|
||||
run: terraform init -reconfigure
|
||||
|
||||
- name: Terraform Workspace (shared)
|
||||
- name: Terraform Workspace
|
||||
working-directory: infrastructure/terraform/shared
|
||||
run: terraform workspace select ${STAGE} || terraform workspace new ${STAGE}
|
||||
|
||||
- name: Terraform Plan (shared)
|
||||
- name: Terraform Plan
|
||||
working-directory: infrastructure/terraform/shared
|
||||
run: terraform plan -var-file=${STAGE}.tfvars -out=tfplan
|
||||
|
||||
- name: Terraform Apply (shared)
|
||||
- name: Terraform Apply
|
||||
if: env.STAGE == 'prod'
|
||||
working-directory: infrastructure/terraform/shared
|
||||
run: terraform apply -auto-approve -var-file=${STAGE}.tfvars tfplan
|
||||
run: terraform apply -auto-approve tfplan
|
||||
|
||||
# ============================================================
|
||||
# 2️⃣ Build Docker image (tag = GitHub SHA, digest resolved)
|
||||
# 2️⃣ Build image
|
||||
# ============================================================
|
||||
address2uprn_image:
|
||||
needs: [determine_stage, shared_terraform]
|
||||
|
|
@ -84,17 +78,17 @@ jobs:
|
|||
AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: ${{ secrets.DEV_AWS_REGION }}
|
||||
|
||||
# # ============================================================
|
||||
# # 3️⃣ Deploy Lambda (Terraform, immutable digest)
|
||||
# # ============================================================
|
||||
# ============================================================
|
||||
# 3️⃣ Deploy Lambda
|
||||
# ============================================================
|
||||
address2uprn_lambda:
|
||||
needs: [address2uprn_image, determine_stage]
|
||||
uses: ./.github/workflows/_deploy_lambda.yml
|
||||
with:
|
||||
lambda_name: address2UPRN
|
||||
lambda_path: infrastructure/terraform/lambda/address2UPRN
|
||||
lambda_name: address2uprn
|
||||
lambda_path: infrastructure/terraform/lambda/address2uprn
|
||||
stage: ${{ needs.determine_stage.outputs.stage }}
|
||||
image_digest: ${{ needs.image.outputs.image_digest }}
|
||||
image_uri: ${{ needs.address2uprn_image.outputs.ecr_repo_url }}@${{ needs.address2uprn_image.outputs.image_digest }}
|
||||
secrets:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,68 @@
|
|||
### Checklist for a new lambda
|
||||
## Checklist for adding a new Lambda
|
||||
|
||||
- [ ] Copy cp -r lambda/_template lambda/<name>
|
||||
- [ ] Add ECR repo in shared/main.tf
|
||||
- [ ] Set bucket name in provider.tf
|
||||
- [ ] Add shared output for repo name/url
|
||||
- [ ] Push to GitHub (CI will deploy)
|
||||
### 1. Create the Lambda scaffold
|
||||
- Copy the template:
|
||||
|
||||
cp -r lambda/_template lambda/<lambda_name>
|
||||
|
||||
Note: By default this does a sqs to lamba. Configure the terraform file for other connections between sqs->lambda
|
||||
- Update `variables.tf` if required
|
||||
- Ensure the Terraform module accepts:
|
||||
- `lambda_name`
|
||||
- `stage`
|
||||
- `image_uri`
|
||||
|
||||
---
|
||||
|
||||
### 2. Add infrastructure prerequisites (shared stack)
|
||||
- Add a new ECR repository in:
|
||||
|
||||
infrastructure/terraform/shared/main.tf
|
||||
|
||||
- Apply the shared stack (or let CI apply it on `prod`)
|
||||
- Verify the ECR repository exists in AWS
|
||||
|
||||
Note:
|
||||
No Terraform outputs are required for the ECR repo.
|
||||
The CI pipeline resolves the repository URL dynamically at build time.
|
||||
|
||||
---
|
||||
|
||||
### 3. Add Docker build configuration
|
||||
- Create a `Dockerfile` for the Lambda
|
||||
- Verify the Dockerfile path and build context
|
||||
- Add a new image build job in `deploy_terraform.yml` using `_build_image.yml`
|
||||
|
||||
---
|
||||
|
||||
### 4. Wire the Lambda deploy job (CI)
|
||||
- Add a deploy job using `_deploy_lambda.yml`
|
||||
- Pass the following inputs:
|
||||
- `lambda_name`
|
||||
- `lambda_path`
|
||||
- `stage`
|
||||
- `image_uri` (constructed as `repo@sha256:digest`)
|
||||
- Ensure the deploy job depends on the image build job
|
||||
|
||||
---
|
||||
|
||||
### 5. Deploy
|
||||
- Push changes to GitHub
|
||||
- CI will:
|
||||
1. Build and push the Docker image
|
||||
2. Resolve the image digest
|
||||
3. Deploy the Lambda using the immutable `image_uri`
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
- Terraform remote state is not used for image wiring
|
||||
- Image tags are not used; deployments are digest-based
|
||||
- By default, the template wires SQS → Lambda
|
||||
To change this, update the Terraform in `lambda/<lambda_name>`
|
||||
(e.g. EventBridge, API Gateway, direct invoke)
|
||||
|
||||
---
|
||||
|
||||
## Rule of thumb
|
||||
CI decides what image to deploy.
|
||||
Terraform only deploys it.
|
||||
|
|
|
|||
|
|
@ -1,19 +1,11 @@
|
|||
data "terraform_remote_state" "shared" {
|
||||
backend = "s3"
|
||||
config = {
|
||||
bucket = "assessment-model-terraform-state"
|
||||
key = "terraform.tfstate"
|
||||
region = "eu-west-2"
|
||||
}
|
||||
}
|
||||
|
||||
module "lambda" {
|
||||
source = "../modules/lambda_with_sqs"
|
||||
|
||||
name = REPLACE ME #"address2uprn" for example
|
||||
stage = var.stage
|
||||
|
||||
image_uri = "${data.terraform_remote_state.shared.outputs.REPLACE_ME_repository_url}@${var.image_digest}"
|
||||
image_uri = var.image_uri
|
||||
|
||||
|
||||
environment = {
|
||||
STAGE = var.stage
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
variable "region" {
|
||||
type = string
|
||||
default = "eu-west-2"
|
||||
variable "lambda_name" {
|
||||
type = string
|
||||
description = "Logical name of the lambda (e.g. address2uprn)"
|
||||
}
|
||||
|
||||
variable "stage" {
|
||||
type = string
|
||||
variable "image_uri" {
|
||||
type = string
|
||||
description = "Full ECR image URI including digest"
|
||||
}
|
||||
|
||||
variable "image_digest" {
|
||||
type = string
|
||||
}
|
||||
|
|
@ -1,26 +1,10 @@
|
|||
############################################
|
||||
# Read shared state to get outputs
|
||||
############################################
|
||||
data "terraform_remote_state" "shared" {
|
||||
backend = "s3"
|
||||
|
||||
config = {
|
||||
bucket = "assessment-model-terraform-state"
|
||||
key = "terraform.tfstate"
|
||||
region = "eu-west-2"
|
||||
}
|
||||
}
|
||||
|
||||
############################################
|
||||
# Address2UPRN Lambda (via reusable module)
|
||||
############################################
|
||||
module "address2uprn" {
|
||||
source = "../modules/lambda_with_sqs"
|
||||
|
||||
name = "address2uprn"
|
||||
stage = var.stage
|
||||
|
||||
image_uri = "${data.terraform_remote_state.shared.outputs.address2uprn_repository_url}@${var.image_digest}"
|
||||
image_uri = var.image_uri
|
||||
|
||||
environment = {
|
||||
STAGE = var.stage
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
variable "region" {
|
||||
type = string
|
||||
default = "eu-west-2"
|
||||
variable "lambda_name" {
|
||||
type = string
|
||||
description = "Logical name of the lambda (e.g. address2uprn)"
|
||||
}
|
||||
|
||||
variable "stage" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "image_digest" {
|
||||
type = string
|
||||
variable "image_uri" {
|
||||
type = string
|
||||
description = "Full ECR image URI including digest"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue