From 07aabb1e9db65c614d8a6988263182ef762b28b9 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 10:58:39 +0000 Subject: [PATCH 01/31] Implement deployment workflow for Recordprocessor and update backend deployment dependencies - Added a new GitHub Actions workflow for deploying the Recordprocessor batch processor. - Updated the continuous deployment workflow to include a dependency on the new Recordprocessor deployment. - Introduced a new variable for the Recordprocessor image tag in Terraform configuration. - Refactored ECS task definition to use the new image tag variable for the Recordprocessor container. --- .github/workflows/continuous-deployment.yml | 10 +- .github/workflows/deploy-recordprocessor.yml | 93 +++++++++++++++++++ .../instance/ecs_batch_processor_config.tf | 40 ++------ infrastructure/instance/variables.tf | 6 ++ 4 files changed, 115 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/deploy-recordprocessor.yml diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 1e2bebdfbd..276580e017 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -15,8 +15,16 @@ jobs: secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - deploy-internal-dev-backend: + deploy-internal-dev-recordprocessor: needs: [run-quality-checks] + uses: ./.github/workflows/deploy-recordprocessor.yml + with: + environment: dev + sub_environment: internal-dev + secrets: inherit + + deploy-internal-dev-backend: + needs: [run-quality-checks, deploy-internal-dev-recordprocessor] uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev diff --git a/.github/workflows/deploy-recordprocessor.yml b/.github/workflows/deploy-recordprocessor.yml new file mode 100644 index 0000000000..fee6c002c6 --- /dev/null +++ b/.github/workflows/deploy-recordprocessor.yml @@ -0,0 +1,93 @@ +name: Deploy Recordprocessor Batch Processor + +on: + workflow_call: + inputs: + environment: + description: "AWS environment (e.g. dev, preprod, prod)" + required: true + type: string + sub_environment: + description: "Sub-environment (e.g. internal-dev, internal-qa)" + required: true + type: string + +jobs: + build-and-push-recordprocessor: + name: Build and push recordprocessor image + runs-on: ubuntu-latest + outputs: + image_tag: ${{ steps.build-and-push.outputs.image_tag }} + + env: + AWS_REGION: eu-west-2 + + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Build and push Docker image + id: build-and-push + working-directory: lambdas/recordprocessor + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + SUB_ENVIRONMENT: ${{ inputs.sub_environment }} + run: | + IMAGE_TAG="${GITHUB_SHA}" + REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" + IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" + + docker build -t "${IMAGE_URI}" . + docker push "${IMAGE_URI}" + + echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + + terraform-deploy-recordprocessor: + name: Deploy recordprocessor infrastructure + needs: build-and-push-recordprocessor + runs-on: ubuntu-latest + + env: + AWS_REGION: eu-west-2 + ENVIRONMENT: ${{ inputs.environment }} + SUB_ENVIRONMENT: ${{ inputs.sub_environment }} + APIGEE_ENVIRONMENT: ${{ inputs.sub_environment }} + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} + + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} + aws-region: ${{ env.AWS_REGION }} + + - name: Terraform init + working-directory: infrastructure/instance + env: + AWS_PROFILE: "" + run: make init + + - name: Terraform plan + working-directory: infrastructure/instance + env: + AWS_PROFILE: "" + run: make plan-ci + + - name: Terraform apply + working-directory: infrastructure/instance + env: + AWS_PROFILE: "" + run: make apply-ci diff --git a/infrastructure/instance/ecs_batch_processor_config.tf b/infrastructure/instance/ecs_batch_processor_config.tf index 653b220a96..b2f8b54f7c 100644 --- a/infrastructure/instance/ecs_batch_processor_config.tf +++ b/infrastructure/instance/ecs_batch_processor_config.tf @@ -11,36 +11,18 @@ resource "aws_ecs_cluster" "ecs_cluster" { } } -# Locals for Lambda processing paths and hash -locals { - processing_lambda_dir = abspath("${path.root}/../../lambdas/recordprocessor") - processing_path_include = ["**"] - processing_path_exclude = ["**/__pycache__/**"] - processing_files_include = setunion([for f in local.processing_path_include : fileset(local.processing_lambda_dir, f)]...) - processing_files_exclude = setunion([for f in local.processing_path_exclude : fileset(local.processing_lambda_dir, f)]...) - processing_lambda_files = sort(setsubtract(local.processing_files_include, local.processing_files_exclude)) - processing_lambda_dir_sha = sha1(join("", [for f in local.processing_lambda_files : filesha1("${local.processing_lambda_dir}/${f}")])) - image_tag = "latest" -} - -# Create ECR Repository for processing. resource "aws_ecr_repository" "processing_repository" { image_scanning_configuration { scan_on_push = true } - name = "${local.short_prefix}-processing-repo" - force_delete = local.is_temp + image_tag_mutability = "IMMUTABLE" + name = "${local.short_prefix}-processing-repo" + force_delete = local.is_temp } -# Build and Push Docker Image to ECR (Reusing the existing module) -module "processing_docker_image" { - source = "terraform-aws-modules/lambda/aws//modules/docker-build" - version = "8.7.0" - - create_ecr_repo = false - docker_file_path = "./recordprocessor/Dockerfile" - ecr_repo = aws_ecr_repository.processing_repository.name - ecr_repo_lifecycle_policy = jsonencode({ +resource "aws_ecr_lifecycle_policy" "processing_repository_policy" { + repository = aws_ecr_repository.processing_repository.name + policy = jsonencode({ "rules" : [ { "rulePriority" : 1, @@ -56,14 +38,6 @@ module "processing_docker_image" { } ] }) - - platform = "linux/amd64" - use_image_tag = false - source_path = abspath("${path.root}/../../lambdas") - triggers = { - dir_sha = local.processing_lambda_dir_sha - shared_dir_sha = local.shared_dir_sha - } } # Define the IAM Role for ECS Task Execution @@ -197,7 +171,7 @@ resource "aws_ecs_task_definition" "ecs_task" { container_definitions = jsonencode([{ name = "${local.short_prefix}-process-records-container" - image = "${aws_ecr_repository.processing_repository.repository_url}:${local.image_tag}" + image = "${aws_ecr_repository.processing_repository.repository_url}:${var.recordprocessor_image_tag}" essential = true environment = [ { diff --git a/infrastructure/instance/variables.tf b/infrastructure/instance/variables.tf index af88630698..5d6d5932e8 100644 --- a/infrastructure/instance/variables.tf +++ b/infrastructure/instance/variables.tf @@ -99,6 +99,12 @@ variable "dynamodb_point_in_time_recovery_enabled" { default = false } +variable "recordprocessor_image_tag" { + description = "Tag of the recordprocessor (batch processor) container image in ECR" + type = string + default = "latest" +} + locals { prefix = "${var.project_name}-${var.service}-${var.sub_environment}" short_prefix = "${var.project_short_name}-${var.sub_environment}" From a93558575beb50f39ca68214c2df1b877034b8d9 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 11:13:36 +0000 Subject: [PATCH 02/31] Update AWS credentials configuration in deployment workflows - Explicitly set the AWS_INFRA_ROLE_ARN secret in the continuous deployment workflow. - Upgrade aws-actions/configure-aws-credentials and aws-actions/amazon-ecr-login to specific versions for improved stability. --- .github/workflows/continuous-deployment.yml | 3 ++- .github/workflows/deploy-recordprocessor.yml | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 276580e017..130e2dfd3f 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -21,7 +21,8 @@ jobs: with: environment: dev sub_environment: internal-dev - secrets: inherit + secrets: + AWS_INFRA_ROLE_ARN: ${{ secrets.AWS_INFRA_ROLE_ARN }} deploy-internal-dev-backend: needs: [run-quality-checks, deploy-internal-dev-recordprocessor] diff --git a/.github/workflows/deploy-recordprocessor.yml b/.github/workflows/deploy-recordprocessor.yml index fee6c002c6..f5ebfeccc1 100644 --- a/.github/workflows/deploy-recordprocessor.yml +++ b/.github/workflows/deploy-recordprocessor.yml @@ -27,14 +27,14 @@ jobs: uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a with: role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 + uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image id: build-and-push @@ -69,7 +69,7 @@ jobs: uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a with: role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} From 10f08fad613402c4e6b74a97f1d73e21c940bcc9 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 12:32:50 +0000 Subject: [PATCH 03/31] Refactor deployment workflows to streamline Recordprocessor integration - Removed the separate Recordprocessor deployment workflow and integrated its functionality into the backend deployment workflow. - Added a new input parameter `enable_recordprocessor` to conditionally build and push the Recordprocessor Docker image. - Updated dependencies in the backend deployment to ensure proper execution order and image tagging for the Recordprocessor. - Enhanced the continuous deployment workflow by simplifying dependencies and improving clarity. --- .github/workflows/continuous-deployment.yml | 12 +-- .github/workflows/deploy-backend.yml | 69 ++++++++++++++- .github/workflows/deploy-recordprocessor.yml | 93 -------------------- 3 files changed, 70 insertions(+), 104 deletions(-) delete mode 100644 .github/workflows/deploy-recordprocessor.yml diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 130e2dfd3f..6a1c32d212 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -15,20 +15,12 @@ jobs: secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - deploy-internal-dev-recordprocessor: - needs: [run-quality-checks] - uses: ./.github/workflows/deploy-recordprocessor.yml - with: - environment: dev - sub_environment: internal-dev - secrets: - AWS_INFRA_ROLE_ARN: ${{ secrets.AWS_INFRA_ROLE_ARN }} - deploy-internal-dev-backend: - needs: [run-quality-checks, deploy-internal-dev-recordprocessor] + needs: [run-quality-checks] uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev + enable_recordprocessor: true create_mns_subscription: true environment: dev sub_environment: internal-dev diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 9c742cdc11..58051b5451 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -6,6 +6,10 @@ on: apigee_environment: required: true type: string + enable_recordprocessor: + required: false + type: boolean + default: false create_mns_subscription: required: false type: boolean @@ -27,6 +31,11 @@ on: - int - ref - prod + enable_recordprocessor: + description: Enable deployment of the recordprocessor batch image via Terraform + required: false + type: boolean + default: false create_mns_subscription: description: Create an MNS Subscription programatically. Only available in AWS dev required: false @@ -51,11 +60,65 @@ env: # Sonarcloud - do not allow direct usage of untrusted data run-name: Deploy Backend - ${{ inputs.environment }} ${{ inputs.sub_environment }} jobs: + build-and-push-recordprocessor: + name: Build and push recordprocessor image + runs-on: ubuntu-latest + outputs: + image_tag: ${{ steps.build-and-push.outputs.image_tag }} + + env: + AWS_REGION: eu-west-2 + SUB_ENVIRONMENT: ${{ inputs.sub_environment }} + + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + + - name: Configure AWS credentials + if: ${{ inputs.enable_recordprocessor }} + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + with: + aws-region: ${{ env.AWS_REGION }} + role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops + role-session-name: github-actions + + - name: Login to Amazon ECR + if: ${{ inputs.enable_recordprocessor }} + id: login-ecr + uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 + + - name: Build and push Docker image + if: ${{ inputs.enable_recordprocessor }} + id: build-and-push + working-directory: lambdas/recordprocessor + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + SUB_ENVIRONMENT: ${{ env.SUB_ENVIRONMENT }} + run: | + IMAGE_TAG="${GITHUB_SHA}" + REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" + + if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then + echo "ECR repository ${REPOSITORY_NAME} does not exist; skipping recordprocessor image build and push." + echo "image_tag=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" + + docker build -t "${IMAGE_URI}" . + docker push "${IMAGE_URI}" + + echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + terraform-plan: permissions: id-token: write contents: read + needs: build-and-push-recordprocessor runs-on: ubuntu-latest + env: + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} environment: name: ${{ inputs.environment }} steps: @@ -94,8 +157,12 @@ jobs: permissions: id-token: write contents: read - needs: terraform-plan + needs: + - terraform-plan + - build-and-push-recordprocessor runs-on: ubuntu-latest + env: + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} environment: name: ${{ inputs.environment }} steps: diff --git a/.github/workflows/deploy-recordprocessor.yml b/.github/workflows/deploy-recordprocessor.yml deleted file mode 100644 index f5ebfeccc1..0000000000 --- a/.github/workflows/deploy-recordprocessor.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Deploy Recordprocessor Batch Processor - -on: - workflow_call: - inputs: - environment: - description: "AWS environment (e.g. dev, preprod, prod)" - required: true - type: string - sub_environment: - description: "Sub-environment (e.g. internal-dev, internal-qa)" - required: true - type: string - -jobs: - build-and-push-recordprocessor: - name: Build and push recordprocessor image - runs-on: ubuntu-latest - outputs: - image_tag: ${{ steps.build-and-push.outputs.image_tag }} - - env: - AWS_REGION: eu-west-2 - - steps: - - name: Checkout - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a - with: - role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} - aws-region: ${{ env.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - - - name: Build and push Docker image - id: build-and-push - working-directory: lambdas/recordprocessor - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - SUB_ENVIRONMENT: ${{ inputs.sub_environment }} - run: | - IMAGE_TAG="${GITHUB_SHA}" - REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" - IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - - docker build -t "${IMAGE_URI}" . - docker push "${IMAGE_URI}" - - echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" - - terraform-deploy-recordprocessor: - name: Deploy recordprocessor infrastructure - needs: build-and-push-recordprocessor - runs-on: ubuntu-latest - - env: - AWS_REGION: eu-west-2 - ENVIRONMENT: ${{ inputs.environment }} - SUB_ENVIRONMENT: ${{ inputs.sub_environment }} - APIGEE_ENVIRONMENT: ${{ inputs.sub_environment }} - TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} - - steps: - - name: Checkout - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a - with: - role-to-assume: ${{ secrets.AWS_INFRA_ROLE_ARN }} - aws-region: ${{ env.AWS_REGION }} - - - name: Terraform init - working-directory: infrastructure/instance - env: - AWS_PROFILE: "" - run: make init - - - name: Terraform plan - working-directory: infrastructure/instance - env: - AWS_PROFILE: "" - run: make plan-ci - - - name: Terraform apply - working-directory: infrastructure/instance - env: - AWS_PROFILE: "" - run: make apply-ci From d1230ac1eea8820c103a78ef94b15b68a44bebb9 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 12:38:53 +0000 Subject: [PATCH 04/31] Update ECR repository check in deployment workflow to fail on missing repository - Changed the behavior of the ECR repository check to fail the build-and-push-recordprocessor job if the repository does not exist, instead of skipping the image build and push. This ensures that the deployment process is more robust and provides clearer feedback on repository availability. --- .github/workflows/deploy-backend.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 58051b5451..ec98fcd3a4 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -99,9 +99,8 @@ jobs: REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then - echo "ECR repository ${REPOSITORY_NAME} does not exist; skipping recordprocessor image build and push." - echo "image_tag=" >> "$GITHUB_OUTPUT" - exit 0 + echo "ECR repository ${REPOSITORY_NAME} does not exist; failing build-and-push-recordprocessor job." + exit 1 fi IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" From 57fcfbf9e32dc8e765ccab2a3e0854a7a4527297 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 13:34:41 +0000 Subject: [PATCH 05/31] Update image tag resolution in backend deployment workflow - Modified the backend deployment workflow to include a new step for resolving the image tag based on the `enable_recordprocessor` input. This change ensures that the image tag is set to the output of the build-and-push step if the Recordprocessor is enabled, otherwise defaults to "latest". This enhances the clarity and reliability of the image tagging process during deployment. --- .github/workflows/deploy-backend.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index ec98fcd3a4..cea4cc509c 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -64,7 +64,7 @@ jobs: name: Build and push recordprocessor image runs-on: ubuntu-latest outputs: - image_tag: ${{ steps.build-and-push.outputs.image_tag }} + image_tag: ${{ steps.resolve-image-tag.outputs.image_tag }} env: AWS_REGION: eu-west-2 @@ -110,6 +110,15 @@ jobs: echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + - name: Resolve image tag + id: resolve-image-tag + run: | + if [ "${{ inputs.enable_recordprocessor }}" = "true" ] && [ -n "${{ steps.build-and-push.outputs.image_tag }}" ]; then + echo "image_tag=${{ steps.build-and-push.outputs.image_tag }}" >> "$GITHUB_OUTPUT" + else + echo "image_tag=latest" >> "$GITHUB_OUTPUT" + fi + terraform-plan: permissions: id-token: write From 219aea8799e520094869b973619e0ef32b31b164 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 15:29:40 +0000 Subject: [PATCH 06/31] change rollback --- .github/workflows/deploy-backend.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index cea4cc509c..ec98fcd3a4 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -64,7 +64,7 @@ jobs: name: Build and push recordprocessor image runs-on: ubuntu-latest outputs: - image_tag: ${{ steps.resolve-image-tag.outputs.image_tag }} + image_tag: ${{ steps.build-and-push.outputs.image_tag }} env: AWS_REGION: eu-west-2 @@ -110,15 +110,6 @@ jobs: echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" - - name: Resolve image tag - id: resolve-image-tag - run: | - if [ "${{ inputs.enable_recordprocessor }}" = "true" ] && [ -n "${{ steps.build-and-push.outputs.image_tag }}" ]; then - echo "image_tag=${{ steps.build-and-push.outputs.image_tag }}" >> "$GITHUB_OUTPUT" - else - echo "image_tag=latest" >> "$GITHUB_OUTPUT" - fi - terraform-plan: permissions: id-token: write From f2f8854ad700b6fd56c46845806a29391f3bf728 Mon Sep 17 00:00:00 2001 From: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:43:04 +0000 Subject: [PATCH 07/31] Rollback enable_recordprocessor variable and create ECR repo if it doesn't exist --- .github/workflows/deploy-backend.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index ec98fcd3a4..fee61840f2 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -6,10 +6,6 @@ on: apigee_environment: required: true type: string - enable_recordprocessor: - required: false - type: boolean - default: false create_mns_subscription: required: false type: boolean @@ -31,11 +27,6 @@ on: - int - ref - prod - enable_recordprocessor: - description: Enable deployment of the recordprocessor batch image via Terraform - required: false - type: boolean - default: false create_mns_subscription: description: Create an MNS Subscription programatically. Only available in AWS dev required: false @@ -75,7 +66,6 @@ jobs: uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - name: Configure AWS credentials - if: ${{ inputs.enable_recordprocessor }} uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 with: aws-region: ${{ env.AWS_REGION }} @@ -83,12 +73,10 @@ jobs: role-session-name: github-actions - name: Login to Amazon ECR - if: ${{ inputs.enable_recordprocessor }} id: login-ecr uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image - if: ${{ inputs.enable_recordprocessor }} id: build-and-push working-directory: lambdas/recordprocessor env: @@ -99,8 +87,8 @@ jobs: REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then - echo "ECR repository ${REPOSITORY_NAME} does not exist; failing build-and-push-recordprocessor job." - exit 1 + echo "ECR repository ${REPOSITORY_NAME} does not exist; creating now..." + aws ecr create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" fi IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" From 0e639368f8866181d7ceecc3f4e903f1b052cc58 Mon Sep 17 00:00:00 2001 From: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:58:42 +0000 Subject: [PATCH 08/31] Add permissions to build-and-push job --- .github/workflows/deploy-backend.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index fee61840f2..7bd541f432 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -52,6 +52,9 @@ run-name: Deploy Backend - ${{ inputs.environment }} ${{ inputs.sub_environment jobs: build-and-push-recordprocessor: + permissions: + id-token: write + contents: read name: Build and push recordprocessor image runs-on: ubuntu-latest outputs: From 6b7f4d1f4b6e11c730b2fec548ba85bc7cb8296a Mon Sep 17 00:00:00 2001 From: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:21:51 +0000 Subject: [PATCH 09/31] Update AWS connection --- .github/workflows/deploy-backend.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 7bd541f432..6c97d5b6fa 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -68,10 +68,10 @@ jobs: - name: Checkout uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - - name: Configure AWS credentials + - name: Connect to AWS uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 with: - aws-region: ${{ env.AWS_REGION }} + aws-region: eu-west-2 role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops role-session-name: github-actions From 4ea668ad893c916714352dcf52d399e69bce8acf Mon Sep 17 00:00:00 2001 From: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:32:32 +0000 Subject: [PATCH 10/31] Add environment inputs --- .github/workflows/deploy-backend.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 6c97d5b6fa..c85950d528 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -60,6 +60,9 @@ jobs: outputs: image_tag: ${{ steps.build-and-push.outputs.image_tag }} + environment: + name: ${{ inputs.environment }} + env: AWS_REGION: eu-west-2 SUB_ENVIRONMENT: ${{ inputs.sub_environment }} From 142de410cd6b378563d5f1ee4988a4cb3404a787 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 16:48:34 +0000 Subject: [PATCH 11/31] Refactor Dockerfile paths and update deployment workflow - Adjusted the Dockerfile to use correct paths for Poetry files and source code within the `lambdas/recordprocessor` directory. - Updated the deployment workflow to specify the Dockerfile location during the build process, ensuring proper image creation for the Recordprocessor. --- .github/workflows/deploy-backend.yml | 3 +-- lambdas/recordprocessor/Dockerfile | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index c85950d528..51cd32c08e 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -84,7 +84,6 @@ jobs: - name: Build and push Docker image id: build-and-push - working-directory: lambdas/recordprocessor env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} SUB_ENVIRONMENT: ${{ env.SUB_ENVIRONMENT }} @@ -99,7 +98,7 @@ jobs: IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - docker build -t "${IMAGE_URI}" . + docker build -f lambdas/recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" diff --git a/lambdas/recordprocessor/Dockerfile b/lambdas/recordprocessor/Dockerfile index 00557b8210..645874da8f 100644 --- a/lambdas/recordprocessor/Dockerfile +++ b/lambdas/recordprocessor/Dockerfile @@ -7,7 +7,7 @@ RUN mkdir -p /home/appuser && \ chown -R 1001:1001 /home/appuser && pip install "poetry~=2.1.4" # Copy recordprocessor Poetry files -COPY ./recordprocessor/poetry.lock ./recordprocessor/pyproject.toml ./ +COPY ./lambdas/recordprocessor/poetry.lock ./lambdas/recordprocessor/pyproject.toml ./ # Install dependencies WORKDIR /var/task @@ -17,10 +17,10 @@ RUN poetry config virtualenvs.create false && poetry install --no-interaction -- FROM base AS build # Copy shared source code -COPY ./shared/src/common ./common +COPY ./lambdas/shared/src/common ./common # Copy recordprocessor source code -COPY ./recordprocessor/src . +COPY ./lambdas/recordprocessor/src . # Set correct permissions RUN chmod 644 $(find . -type f) && chmod 755 $(find . -type d) From aad14d8260178edafc357ce85f03c45ddfaebdd9 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 17:51:38 +0000 Subject: [PATCH 12/31] Fix Dockerfile paths and streamline deployment workflow - Updated paths in the Dockerfile to correctly reference the `recordprocessor` directory for Poetry files and source code. - Adjusted the deployment workflow to ensure the Docker build command points to the correct location of the Dockerfile, enhancing the image build process. --- .github/workflows/deploy-backend.yml | 4 ++-- lambdas/recordprocessor/Dockerfile | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 51cd32c08e..f20bd7808b 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -93,12 +93,12 @@ jobs: if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then echo "ECR repository ${REPOSITORY_NAME} does not exist; creating now..." - aws ecr create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" + aws ecr.create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" fi IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - docker build -f lambdas/recordprocessor/Dockerfile -t "${IMAGE_URI}" . + docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" lambdas docker push "${IMAGE_URI}" echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" diff --git a/lambdas/recordprocessor/Dockerfile b/lambdas/recordprocessor/Dockerfile index 645874da8f..00557b8210 100644 --- a/lambdas/recordprocessor/Dockerfile +++ b/lambdas/recordprocessor/Dockerfile @@ -7,7 +7,7 @@ RUN mkdir -p /home/appuser && \ chown -R 1001:1001 /home/appuser && pip install "poetry~=2.1.4" # Copy recordprocessor Poetry files -COPY ./lambdas/recordprocessor/poetry.lock ./lambdas/recordprocessor/pyproject.toml ./ +COPY ./recordprocessor/poetry.lock ./recordprocessor/pyproject.toml ./ # Install dependencies WORKDIR /var/task @@ -17,10 +17,10 @@ RUN poetry config virtualenvs.create false && poetry install --no-interaction -- FROM base AS build # Copy shared source code -COPY ./lambdas/shared/src/common ./common +COPY ./shared/src/common ./common # Copy recordprocessor source code -COPY ./lambdas/recordprocessor/src . +COPY ./recordprocessor/src . # Set correct permissions RUN chmod 644 $(find . -type f) && chmod 755 $(find . -type d) From b7fe96afc201f872e8041f0819a0eaf078185130 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 18:14:06 +0000 Subject: [PATCH 13/31] Update Docker build context in deployment workflow - Changed the working directory for the Docker build command to the root of the repository, ensuring that all necessary files are included during the image build process. - Adjusted the command to create the ECR repository to ensure it is correctly formatted, enhancing the reliability of the deployment workflow. --- .github/workflows/deploy-backend.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index f20bd7808b..6447f615b6 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -87,18 +87,19 @@ jobs: env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} SUB_ENVIRONMENT: ${{ env.SUB_ENVIRONMENT }} + working-directory: lambdas run: | IMAGE_TAG="${GITHUB_SHA}" REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then echo "ECR repository ${REPOSITORY_NAME} does not exist; creating now..." - aws ecr.create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" + aws ecr create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" fi IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" lambdas + docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" From e0538c43fcaa568ecef2f04e7792f8880fa3f5cc Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 18:56:02 +0000 Subject: [PATCH 14/31] Refactor Docker image build process in deployment workflow - Removed the `enable_recordprocessor` input from the continuous deployment workflow. - Added a conditional check in the backend deployment workflow to skip the Docker build and push if the image already exists in ECR, improving efficiency and reducing unnecessary builds. --- .github/workflows/continuous-deployment.yml | 1 - .github/workflows/deploy-backend.yml | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 6a1c32d212..1e2bebdfbd 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -20,7 +20,6 @@ jobs: uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev - enable_recordprocessor: true create_mns_subscription: true environment: dev sub_environment: internal-dev diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 6447f615b6..c1e5bbb2ef 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -99,8 +99,12 @@ jobs: IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . - docker push "${IMAGE_URI}" + if aws ecr describe-images --repository-name "${REPOSITORY_NAME}" --image-ids imageTag="${IMAGE_TAG}" --region "${AWS_REGION}" >/dev/null 2>&1; then + echo "Image ${IMAGE_TAG} already exists in ECR, skipping build and push" + else + docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . + docker push "${IMAGE_URI}" + fi echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" From a96ae2d249ce059042f232e9edbe343e0516abea Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 19:32:41 +0000 Subject: [PATCH 15/31] Enhance deployment workflow with Terraform planning step - Introduced a new `terraform-plan` job in the deployment workflow to manage infrastructure changes before applying them. - Added steps for AWS connection, Terraform initialization, and planning, ensuring a structured approach to infrastructure management. - Updated the `build-and-push-recordprocessor` job to depend on the `terraform-apply` job, streamlining the deployment process. - Removed redundant image tag output handling, simplifying the workflow logic. --- .github/workflows/deploy-backend.yml | 102 ++++++++++++--------------- 1 file changed, 44 insertions(+), 58 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index c1e5bbb2ef..afb9642e86 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -51,14 +51,54 @@ env: # Sonarcloud - do not allow direct usage of untrusted data run-name: Deploy Backend - ${{ inputs.environment }} ${{ inputs.sub_environment }} jobs: + terraform-plan: + permissions: + id-token: write + contents: read + runs-on: ubuntu-latest + env: + TF_VAR_recordprocessor_image_tag: ${{ github.sha }} + environment: + name: ${{ inputs.environment }} + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + + - name: Connect to AWS + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + with: + aws-region: eu-west-2 + role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops + role-session-name: github-actions + + - uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 + with: + terraform_version: "1.12.2" + + - name: Terraform Init + working-directory: infrastructure/instance + run: make init + + - name: Terraform Plan + # Ignore cancellations to prevent Terraform from being killed while it holds a state lock + # A stuck process can still be killed with the force-cancel API operation + if: ${{ !failure() }} + working-directory: infrastructure/instance + run: make plan-ci + + - name: Save Terraform Plan + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f + with: + name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-tfplan + path: infrastructure/instance/tfplan + build-and-push-recordprocessor: permissions: id-token: write contents: read name: Build and push recordprocessor image + needs: terraform-apply runs-on: ubuntu-latest - outputs: - image_tag: ${{ steps.build-and-push.outputs.image_tag }} environment: name: ${{ inputs.environment }} @@ -83,20 +123,12 @@ jobs: uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image - id: build-and-push env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - SUB_ENVIRONMENT: ${{ env.SUB_ENVIRONMENT }} working-directory: lambdas run: | IMAGE_TAG="${GITHUB_SHA}" REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" - - if ! aws ecr describe-repositories --repository-names "${REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then - echo "ECR repository ${REPOSITORY_NAME} does not exist; creating now..." - aws ecr create-repository --repository-name "${REPOSITORY_NAME}" --region "${AWS_REGION}" - fi - IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" if aws ecr describe-images --repository-name "${REPOSITORY_NAME}" --image-ids imageTag="${IMAGE_TAG}" --region "${AWS_REGION}" >/dev/null 2>&1; then @@ -106,60 +138,14 @@ jobs: docker push "${IMAGE_URI}" fi - echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" - - terraform-plan: - permissions: - id-token: write - contents: read - needs: build-and-push-recordprocessor - runs-on: ubuntu-latest - env: - TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} - environment: - name: ${{ inputs.environment }} - steps: - - name: Checkout - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - - - name: Connect to AWS - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 - with: - aws-region: eu-west-2 - role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops - role-session-name: github-actions - - - uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 - with: - terraform_version: "1.12.2" - - - name: Terraform Init - working-directory: infrastructure/instance - run: make init - - - name: Terraform Plan - # Ignore cancellations to prevent Terraform from being killed while it holds a state lock - # A stuck process can still be killed with the force-cancel API operation - if: ${{ !failure() }} - working-directory: infrastructure/instance - run: make plan-ci - - - name: Save Terraform Plan - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f - with: - name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-tfplan - path: infrastructure/instance/tfplan - terraform-apply: permissions: id-token: write contents: read - needs: - - terraform-plan - - build-and-push-recordprocessor + needs: terraform-plan runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.image_tag }} + TF_VAR_recordprocessor_image_tag: ${{ github.sha }} environment: name: ${{ inputs.environment }} steps: From b79796b958ba629f1f2c5c4bb830eaf9e615e0c7 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Tue, 10 Mar 2026 20:18:01 +0000 Subject: [PATCH 16/31] Add ECR repository import step to deployment workflow - Introduced a new step to import the ECR repository into Terraform state if it exists, enhancing the deployment process. - This addition ensures that the workflow can manage existing resources more effectively, preventing potential conflicts during deployment. --- .github/workflows/deploy-backend.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index afb9642e86..57147569c5 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -79,6 +79,18 @@ jobs: working-directory: infrastructure/instance run: make init + - name: Import ECR repository if it exists outside Terraform state + if: ${{ !failure() }} + working-directory: infrastructure/instance + env: + AWS_REGION: eu-west-2 + run: | + REPO_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" + if aws ecr describe-repositories --repository-names "${REPO_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then + echo "ECR repository ${REPO_NAME} exists in AWS, importing into Terraform state if needed..." + terraform import aws_ecr_repository.processing_repository "${REPO_NAME}" || true + fi + - name: Terraform Plan # Ignore cancellations to prevent Terraform from being killed while it holds a state lock # A stuck process can still be killed with the force-cancel API operation From 9fabfd677e2a43d9bae163a0a50a5a0104e2f2fe Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Wed, 11 Mar 2026 08:32:35 +0000 Subject: [PATCH 17/31] Remove ECR repository import step from deployment workflow - Eliminated the step that imported the ECR repository into Terraform state, streamlining the deployment process. - This change simplifies the workflow by removing unnecessary checks for existing resources, focusing on a more straightforward deployment approach. --- .github/workflows/deploy-backend.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 57147569c5..afb9642e86 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -79,18 +79,6 @@ jobs: working-directory: infrastructure/instance run: make init - - name: Import ECR repository if it exists outside Terraform state - if: ${{ !failure() }} - working-directory: infrastructure/instance - env: - AWS_REGION: eu-west-2 - run: | - REPO_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" - if aws ecr describe-repositories --repository-names "${REPO_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then - echo "ECR repository ${REPO_NAME} exists in AWS, importing into Terraform state if needed..." - terraform import aws_ecr_repository.processing_repository "${REPO_NAME}" || true - fi - - name: Terraform Plan # Ignore cancellations to prevent Terraform from being killed while it holds a state lock # A stuck process can still be killed with the force-cancel API operation From 0ab3ae765ccd4713b86f629c8b4ea6d71021b261 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Wed, 11 Mar 2026 10:58:10 +0000 Subject: [PATCH 18/31] Refactor deployment workflow and ECR repository configuration - Updated the deployment workflow to use a new naming convention for the Docker image tag and repository. - Removed the conditional check for existing images in ECR, ensuring a build and push occurs every time. - Introduced a new ECR repository resource for the record processor, enhancing image management. - Adjusted IAM policies and ECS task definitions to reference the new repository configuration. --- .github/workflows/deploy-backend.yml | 12 +++---- .../account/recordprocessor_ecr_repo.tf | 9 +++++ .../instance/ecs_batch_processor_config.tf | 34 +++---------------- 3 files changed, 17 insertions(+), 38 deletions(-) create mode 100644 infrastructure/account/recordprocessor_ecr_repo.tf diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index afb9642e86..c39439c64c 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -127,16 +127,12 @@ jobs: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} working-directory: lambdas run: | - IMAGE_TAG="${GITHUB_SHA}" - REPOSITORY_NAME="imms-${SUB_ENVIRONMENT}-processing-repo" + IMAGE_TAG="${SUB_ENVIRONMENT}-${GITHUB_SHA}" + REPOSITORY_NAME="imms-recordprocessor-repo" IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - if aws ecr describe-images --repository-name "${REPOSITORY_NAME}" --image-ids imageTag="${IMAGE_TAG}" --region "${AWS_REGION}" >/dev/null 2>&1; then - echo "Image ${IMAGE_TAG} already exists in ECR, skipping build and push" - else - docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . - docker push "${IMAGE_URI}" - fi + docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . + docker push "${IMAGE_URI}" terraform-apply: permissions: diff --git a/infrastructure/account/recordprocessor_ecr_repo.tf b/infrastructure/account/recordprocessor_ecr_repo.tf new file mode 100644 index 0000000000..2ef4a8141f --- /dev/null +++ b/infrastructure/account/recordprocessor_ecr_repo.tf @@ -0,0 +1,9 @@ +resource "aws_ecr_repository" "processing_repository" { + image_scanning_configuration { + scan_on_push = true + } + image_tag_mutability = "IMMUTABLE" + name = "${local.short_prefix}-recordprocessor-repo" +} + +#TODO add lifecycle policy to manage images \ No newline at end of file diff --git a/infrastructure/instance/ecs_batch_processor_config.tf b/infrastructure/instance/ecs_batch_processor_config.tf index b2f8b54f7c..84bef68a57 100644 --- a/infrastructure/instance/ecs_batch_processor_config.tf +++ b/infrastructure/instance/ecs_batch_processor_config.tf @@ -1,4 +1,3 @@ -# Define the ECS Cluster resource "aws_ecs_cluster" "ecs_cluster" { name = "${local.short_prefix}-ecs-cluster" @@ -11,33 +10,8 @@ resource "aws_ecs_cluster" "ecs_cluster" { } } -resource "aws_ecr_repository" "processing_repository" { - image_scanning_configuration { - scan_on_push = true - } - image_tag_mutability = "IMMUTABLE" - name = "${local.short_prefix}-processing-repo" - force_delete = local.is_temp -} - -resource "aws_ecr_lifecycle_policy" "processing_repository_policy" { - repository = aws_ecr_repository.processing_repository.name - policy = jsonencode({ - "rules" : [ - { - "rulePriority" : 1, - "description" : "Keep only the last 2 images", - "selection" : { - "tagStatus" : "any", - "countType" : "imageCountMoreThan", - "countNumber" : 2 - }, - "action" : { - "type" : "expire" - } - } - ] - }) +data "aws_ecr_repository" "recordprocessor_repository" { + name = "${local.short_prefix}-recordprocessor-repo" } # Define the IAM Role for ECS Task Execution @@ -131,7 +105,7 @@ resource "aws_iam_policy" "ecs_task_exec_policy" { Action = [ "ecr:GetAuthorizationToken" ], - Resource = "arn:aws:ecr:${var.aws_region}:${var.immunisation_account_id}:repository/${local.short_prefix}-processing-repo" + Resource = "arn:aws:ecr:${var.aws_region}:${var.immunisation_account_id}:repository/${data.aws_ecr_repository_recordprocessor_repository.name}" }, { "Effect" : "Allow", @@ -171,7 +145,7 @@ resource "aws_ecs_task_definition" "ecs_task" { container_definitions = jsonencode([{ name = "${local.short_prefix}-process-records-container" - image = "${aws_ecr_repository.processing_repository.repository_url}:${var.recordprocessor_image_tag}" + image = "${data.aws_ecr_repository.recordprocessor_repository.repository_url}:${var.recordprocessor_image_tag}" essential = true environment = [ { From 8820337650850b0a31140811c80f493911164c3d Mon Sep 17 00:00:00 2001 From: Thomas-Boyle <45789537+Thomas-Boyle@users.noreply.github.com> Date: Wed, 11 Mar 2026 11:34:36 +0000 Subject: [PATCH 19/31] Update infrastructure/instance/ecs_batch_processor_config.tf Co-authored-by: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> --- infrastructure/instance/ecs_batch_processor_config.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/instance/ecs_batch_processor_config.tf b/infrastructure/instance/ecs_batch_processor_config.tf index 84bef68a57..f93b0424af 100644 --- a/infrastructure/instance/ecs_batch_processor_config.tf +++ b/infrastructure/instance/ecs_batch_processor_config.tf @@ -105,7 +105,7 @@ resource "aws_iam_policy" "ecs_task_exec_policy" { Action = [ "ecr:GetAuthorizationToken" ], - Resource = "arn:aws:ecr:${var.aws_region}:${var.immunisation_account_id}:repository/${data.aws_ecr_repository_recordprocessor_repository.name}" + Resource = "arn:aws:ecr:${var.aws_region}:${var.immunisation_account_id}:repository/${data.aws_ecr_repository.recordprocessor_repository.name}" }, { "Effect" : "Allow", From b0a0fe613a760db516edc1ede0487f22591cc668 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle <45789537+Thomas-Boyle@users.noreply.github.com> Date: Wed, 11 Mar 2026 11:34:59 +0000 Subject: [PATCH 20/31] Update infrastructure/account/recordprocessor_ecr_repo.tf Co-authored-by: Ed Hall <239591530+edhall-nhs@users.noreply.github.com> --- infrastructure/account/recordprocessor_ecr_repo.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/account/recordprocessor_ecr_repo.tf b/infrastructure/account/recordprocessor_ecr_repo.tf index 2ef4a8141f..3c890ff11c 100644 --- a/infrastructure/account/recordprocessor_ecr_repo.tf +++ b/infrastructure/account/recordprocessor_ecr_repo.tf @@ -3,7 +3,7 @@ resource "aws_ecr_repository" "processing_repository" { scan_on_push = true } image_tag_mutability = "IMMUTABLE" - name = "${local.short_prefix}-recordprocessor-repo" + name = "imms-recordprocessor-repo" } #TODO add lifecycle policy to manage images \ No newline at end of file From a4162b7143d714358af48dfd21e4542fdeaa8668 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Wed, 11 Mar 2026 11:42:01 +0000 Subject: [PATCH 21/31] Refactor deployment workflow to reorder jobs and enhance Terraform planning - Moved the `terraform-plan` job to depend on the `build-and-push-recordprocessor` job, ensuring a more logical sequence in the deployment process. - Retained the steps for AWS connection, Terraform initialization, and planning within the `terraform-plan` job, maintaining infrastructure management integrity. - Removed the previous `terraform-plan` job definition to streamline the workflow. --- .github/workflows/deploy-backend.yml | 84 ++++++++++++++-------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index c39439c64c..264b3905b2 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -51,53 +51,11 @@ env: # Sonarcloud - do not allow direct usage of untrusted data run-name: Deploy Backend - ${{ inputs.environment }} ${{ inputs.sub_environment }} jobs: - terraform-plan: - permissions: - id-token: write - contents: read - runs-on: ubuntu-latest - env: - TF_VAR_recordprocessor_image_tag: ${{ github.sha }} - environment: - name: ${{ inputs.environment }} - steps: - - name: Checkout - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - - - name: Connect to AWS - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 - with: - aws-region: eu-west-2 - role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops - role-session-name: github-actions - - - uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 - with: - terraform_version: "1.12.2" - - - name: Terraform Init - working-directory: infrastructure/instance - run: make init - - - name: Terraform Plan - # Ignore cancellations to prevent Terraform from being killed while it holds a state lock - # A stuck process can still be killed with the force-cancel API operation - if: ${{ !failure() }} - working-directory: infrastructure/instance - run: make plan-ci - - - name: Save Terraform Plan - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f - with: - name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-tfplan - path: infrastructure/instance/tfplan - build-and-push-recordprocessor: permissions: id-token: write contents: read name: Build and push recordprocessor image - needs: terraform-apply runs-on: ubuntu-latest environment: @@ -134,6 +92,48 @@ jobs: docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" + terraform-plan: + permissions: + id-token: write + contents: read + needs: build-and-push-recordprocessor + runs-on: ubuntu-latest + env: + TF_VAR_recordprocessor_image_tag: ${{ github.sha }} + environment: + name: ${{ inputs.environment }} + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + + - name: Connect to AWS + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + with: + aws-region: eu-west-2 + role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops + role-session-name: github-actions + + - uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 + with: + terraform_version: "1.12.2" + + - name: Terraform Init + working-directory: infrastructure/instance + run: make init + + - name: Terraform Plan + # Ignore cancellations to prevent Terraform from being killed while it holds a state lock + # A stuck process can still be killed with the force-cancel API operation + if: ${{ !failure() }} + working-directory: infrastructure/instance + run: make plan-ci + + - name: Save Terraform Plan + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f + with: + name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-tfplan + path: infrastructure/instance/tfplan + terraform-apply: permissions: id-token: write From 9a90419061dbb977229b634841736b33dda5e0bb Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Wed, 11 Mar 2026 12:03:10 +0000 Subject: [PATCH 22/31] Update ECS batch processor configuration to use project short name for ECR repository --- infrastructure/instance/ecs_batch_processor_config.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/instance/ecs_batch_processor_config.tf b/infrastructure/instance/ecs_batch_processor_config.tf index f93b0424af..c3ef792a0e 100644 --- a/infrastructure/instance/ecs_batch_processor_config.tf +++ b/infrastructure/instance/ecs_batch_processor_config.tf @@ -11,7 +11,7 @@ resource "aws_ecs_cluster" "ecs_cluster" { } data "aws_ecr_repository" "recordprocessor_repository" { - name = "${local.short_prefix}-recordprocessor-repo" + name = "${var.project_short_name}-recordprocessor-repo" } # Define the IAM Role for ECS Task Execution From 94c502a86413a276e37cb319fe94df1ec62fa24a Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Wed, 11 Mar 2026 13:00:21 +0000 Subject: [PATCH 23/31] Add support for conditional recordprocessor image builds in deployment workflows - Introduced a new input parameter `build_recordprocessor_image` in the deployment workflows to control the building of the recordprocessor Docker image. - Updated the `deploy-backend.yml` to include logic for building the image based on changes detected in the PR. - Added a new job in `pr-deploy-and-test.yml` to detect changes in the recordprocessor directory, influencing the deployment process. - Enhanced the handling of image tags to default to 'latest' if no build is triggered, improving deployment flexibility. --- .github/workflows/continuous-deployment.yml | 2 ++ .github/workflows/deploy-backend.yml | 20 +++++++++++++++-- .github/workflows/pr-deploy-and-test.yml | 24 ++++++++++++++++++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 1e2bebdfbd..d8570708c8 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -20,6 +20,7 @@ jobs: uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev + build_recordprocessor_image: true create_mns_subscription: true environment: dev sub_environment: internal-dev @@ -82,6 +83,7 @@ jobs: uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: ${{ matrix.sub_environment_name }} + build_recordprocessor_image: true create_mns_subscription: true environment: dev sub_environment: ${{ matrix.sub_environment_name }} diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 264b3905b2..5674659d4e 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -6,6 +6,10 @@ on: apigee_environment: required: true type: string + build_recordprocessor_image: + required: false + type: boolean + default: false create_mns_subscription: required: false type: boolean @@ -39,6 +43,11 @@ on: - dev - preprod - prod + build_recordprocessor_image: + description: Build and push a new recordprocessor image for this deployment + required: false + type: boolean + default: false sub_environment: type: string description: Set the sub environment name e.g. pr-xxx, or green/blue in higher environments @@ -70,6 +79,7 @@ jobs: uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - name: Connect to AWS + if: ${{ inputs.build_recordprocessor_image }} uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 with: aws-region: eu-west-2 @@ -77,10 +87,12 @@ jobs: role-session-name: github-actions - name: Login to Amazon ECR + if: ${{ inputs.build_recordprocessor_image }} id: login-ecr uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image + if: ${{ inputs.build_recordprocessor_image }} env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} working-directory: lambdas @@ -92,6 +104,10 @@ jobs: docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" + - name: Skip image build + if: ${{ !inputs.build_recordprocessor_image }} + run: echo "No recordprocessor changes detected and no manual override provided. Skipping image build." + terraform-plan: permissions: id-token: write @@ -99,7 +115,7 @@ jobs: needs: build-and-push-recordprocessor runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ github.sha }} + TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && github.sha || 'latest' }} environment: name: ${{ inputs.environment }} steps: @@ -141,7 +157,7 @@ jobs: needs: terraform-plan runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ github.sha }} + TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && github.sha || 'latest' }} environment: name: ${{ inputs.environment }} steps: diff --git a/.github/workflows/pr-deploy-and-test.yml b/.github/workflows/pr-deploy-and-test.yml index 76db9846d7..5aab3f00a2 100644 --- a/.github/workflows/pr-deploy-and-test.yml +++ b/.github/workflows/pr-deploy-and-test.yml @@ -9,16 +9,38 @@ concurrency: cancel-in-progress: true jobs: + detect-recordprocessor-changes: + runs-on: ubuntu-latest + outputs: + has_changes: ${{ steps.detect.outputs.has_changes }} + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + with: + fetch-depth: 0 + + - name: Detect recordprocessor changes in PR + id: detect + run: | + git fetch origin "${{ github.event.pull_request.base.ref }}" + + if git diff --name-only "origin/${{ github.event.pull_request.base.ref }}" "${{ github.sha }}" | grep -q '^lambdas/recordprocessor/'; then + echo "has_changes=true" >> "$GITHUB_OUTPUT" + else + echo "has_changes=false" >> "$GITHUB_OUTPUT" + fi + run-quality-checks: uses: ./.github/workflows/quality-checks.yml secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} deploy-pr-backend: - needs: [run-quality-checks] + needs: [run-quality-checks, detect-recordprocessor-changes] uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev + build_recordprocessor_image: ${{ github.event.action == 'opened' || needs.detect-recordprocessor-changes.outputs.has_changes == 'true' }} create_mns_subscription: true environment: dev sub_environment: pr-${{github.event.pull_request.number}} From dc8d0216bc1a744c6306c63ac3194425ed761146 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 09:34:30 +0000 Subject: [PATCH 24/31] Enhance deployment workflows with recordprocessor change detection - Added a new job to detect changes in the recordprocessor directory, influencing the build process for the Docker image. - Updated the deployment workflows to conditionally build the recordprocessor image based on detected changes. - Improved tagging of Docker images to include a 'latest' tag alongside the versioned tag for better image management. - Adjusted dependencies in the deployment jobs to ensure proper sequencing and execution based on change detection. --- .github/workflows/continuous-deployment.yml | 27 ++++++++++++++++++--- .github/workflows/deploy-backend.yml | 3 +++ .github/workflows/pr-deploy-and-test.yml | 4 ++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index d8570708c8..0cd93a6307 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -15,12 +15,31 @@ jobs: secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + detect-recordprocessor-changes: + runs-on: ubuntu-latest + outputs: + has_changes: ${{ steps.detect.outputs.has_changes }} + steps: + - name: Checkout + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + with: + fetch-depth: 0 + + - name: Detect recordprocessor changes compared to master + id: detect + run: | + if git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" | grep -q '^lambdas/recordprocessor/'; then + echo "has_changes=true" >> "$GITHUB_OUTPUT" + else + echo "has_changes=false" >> "$GITHUB_OUTPUT" + fi + deploy-internal-dev-backend: - needs: [run-quality-checks] + needs: [run-quality-checks, detect-recordprocessor-changes] uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev - build_recordprocessor_image: true + build_recordprocessor_image: ${{needs.detect-recordprocessor-changes.outputs.has_changes == 'true'}} create_mns_subscription: true environment: dev sub_environment: internal-dev @@ -76,14 +95,14 @@ jobs: STATUS_API_KEY: ${{ secrets.STATUS_API_KEY }} deploy-higher-dev-envs: - needs: [run-internal-dev-tests] + needs: [run-internal-dev-tests, detect-recordprocessor-changes] strategy: matrix: sub_environment_name: [ref, internal-qa] uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: ${{ matrix.sub_environment_name }} - build_recordprocessor_image: true + build_recordprocessor_image: ${{needs.detect-recordprocessor-changes.outputs.has_changes == 'true'}} create_mns_subscription: true environment: dev sub_environment: ${{ matrix.sub_environment_name }} diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 5674659d4e..f0a087e3e0 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -100,9 +100,12 @@ jobs: IMAGE_TAG="${SUB_ENVIRONMENT}-${GITHUB_SHA}" REPOSITORY_NAME="imms-recordprocessor-repo" IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" + LATEST_IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:latest" docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" + docker tag "${IMAGE_URI}" "${LATEST_IMAGE_URI}" + docker push "${LATEST_IMAGE_URI}" - name: Skip image build if: ${{ !inputs.build_recordprocessor_image }} diff --git a/.github/workflows/pr-deploy-and-test.yml b/.github/workflows/pr-deploy-and-test.yml index 5aab3f00a2..3c325f37ad 100644 --- a/.github/workflows/pr-deploy-and-test.yml +++ b/.github/workflows/pr-deploy-and-test.yml @@ -11,6 +11,7 @@ concurrency: jobs: detect-recordprocessor-changes: runs-on: ubuntu-latest + if: github.event.action == 'synchronize' outputs: has_changes: ${{ steps.detect.outputs.has_changes }} steps: @@ -37,10 +38,11 @@ jobs: deploy-pr-backend: needs: [run-quality-checks, detect-recordprocessor-changes] + if: ${{ always() && !failure() && !cancelled() }} uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev - build_recordprocessor_image: ${{ github.event.action == 'opened' || needs.detect-recordprocessor-changes.outputs.has_changes == 'true' }} + build_recordprocessor_image: ${{ github.event.action == 'opened' || github.event.action == 'reopened' || needs.detect-recordprocessor-changes.outputs.has_changes == 'true' }} create_mns_subscription: true environment: dev sub_environment: pr-${{github.event.pull_request.number}} From fa9376ec06d6099611267d79b1686f5948d3082b Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 09:38:50 +0000 Subject: [PATCH 25/31] Update deployment workflows to enhance recordprocessor image tagging - Modified the logic for setting the `TF_VAR_recordprocessor_image_tag` environment variable to include the `sub_environment` in the image tag format. - This change improves the clarity and traceability of Docker image versions during deployment. --- .github/workflows/deploy-backend.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index f0a087e3e0..5c90d5e736 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -118,7 +118,7 @@ jobs: needs: build-and-push-recordprocessor runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && github.sha || 'latest' }} + TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && format('{0}-{1}', inputs.sub_environment, github.sha) || 'latest' }} environment: name: ${{ inputs.environment }} steps: @@ -160,7 +160,7 @@ jobs: needs: terraform-plan runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && github.sha || 'latest' }} + TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && format('{0}-{1}', inputs.sub_environment, github.sha) || 'latest' }} environment: name: ${{ inputs.environment }} steps: From 2848c611fa331664312a1943e41a16fc6c5eb2c0 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 10:01:01 +0000 Subject: [PATCH 26/31] temp commit to rebuild image --- .github/workflows/pr-deploy-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-deploy-and-test.yml b/.github/workflows/pr-deploy-and-test.yml index 3c325f37ad..b59e68c9fb 100644 --- a/.github/workflows/pr-deploy-and-test.yml +++ b/.github/workflows/pr-deploy-and-test.yml @@ -42,7 +42,7 @@ jobs: uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev - build_recordprocessor_image: ${{ github.event.action == 'opened' || github.event.action == 'reopened' || needs.detect-recordprocessor-changes.outputs.has_changes == 'true' }} + build_recordprocessor_image: ${{ github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' }} create_mns_subscription: true environment: dev sub_environment: pr-${{github.event.pull_request.number}} From 0f42ea0a51e21861465adf9e5117c0fd50848873 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 10:09:24 +0000 Subject: [PATCH 27/31] Enhance deployment workflows for recordprocessor image management - Added output for `recordprocessor_image_tag` in `deploy-backend.yml` to streamline image tagging. - Updated logic in `pr-deploy-and-test.yml` to conditionally build the recordprocessor image based on detected changes, improving deployment efficiency. - Refined steps for resolving existing image tags, ensuring proper handling when no new image is built. --- .github/workflows/deploy-backend.yml | 40 +++++++++++++++++++----- .github/workflows/pr-deploy-and-test.yml | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 5c90d5e736..7d1735767d 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -64,6 +64,8 @@ jobs: permissions: id-token: write contents: read + outputs: + recordprocessor_image_tag: ${{ steps.build-image.outputs.recordprocessor_image_tag || steps.resolve-image-tag.outputs.recordprocessor_image_tag }} name: Build and push recordprocessor image runs-on: ubuntu-latest @@ -79,7 +81,6 @@ jobs: uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 - name: Connect to AWS - if: ${{ inputs.build_recordprocessor_image }} uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 with: aws-region: eu-west-2 @@ -92,6 +93,7 @@ jobs: uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image + id: build-image if: ${{ inputs.build_recordprocessor_image }} env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} @@ -100,16 +102,38 @@ jobs: IMAGE_TAG="${SUB_ENVIRONMENT}-${GITHUB_SHA}" REPOSITORY_NAME="imms-recordprocessor-repo" IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:${IMAGE_TAG}" - LATEST_IMAGE_URI="${ECR_REGISTRY}/${REPOSITORY_NAME}:latest" docker build -f recordprocessor/Dockerfile -t "${IMAGE_URI}" . docker push "${IMAGE_URI}" - docker tag "${IMAGE_URI}" "${LATEST_IMAGE_URI}" - docker push "${LATEST_IMAGE_URI}" + echo "recordprocessor_image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" - - name: Skip image build + - name: Resolve latest matching recordprocessor image tag + id: resolve-image-tag if: ${{ !inputs.build_recordprocessor_image }} - run: echo "No recordprocessor changes detected and no manual override provided. Skipping image build." + env: + REPOSITORY_NAME: imms-recordprocessor-repo + TAG_PREFIX: ${{ inputs.sub_environment }}- + run: | + IMAGE_TAG=$( + aws ecr describe-images \ + --repository-name "${REPOSITORY_NAME}" \ + --region "${AWS_REGION}" \ + --filter tagStatus=TAGGED \ + --query 'sort_by(imageDetails,&imagePushedAt)[*].imageTags[*]' \ + --output text \ + | tr '\t' '\n' \ + | grep "^${TAG_PREFIX}" \ + | tail -n1 || true + ) + + if [ -z "${IMAGE_TAG}" ]; then + echo "No existing recordprocessor image found for prefix '${TAG_PREFIX}'." + echo "Trigger a run with build_recordprocessor_image=true to build one." + exit 1 + fi + + echo "Using existing recordprocessor image tag: ${IMAGE_TAG}" + echo "recordprocessor_image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" terraform-plan: permissions: @@ -118,7 +142,7 @@ jobs: needs: build-and-push-recordprocessor runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && format('{0}-{1}', inputs.sub_environment, github.sha) || 'latest' }} + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag }} environment: name: ${{ inputs.environment }} steps: @@ -160,7 +184,7 @@ jobs: needs: terraform-plan runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ inputs.build_recordprocessor_image && format('{0}-{1}', inputs.sub_environment, github.sha) || 'latest' }} + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag }} environment: name: ${{ inputs.environment }} steps: diff --git a/.github/workflows/pr-deploy-and-test.yml b/.github/workflows/pr-deploy-and-test.yml index b59e68c9fb..3c325f37ad 100644 --- a/.github/workflows/pr-deploy-and-test.yml +++ b/.github/workflows/pr-deploy-and-test.yml @@ -42,7 +42,7 @@ jobs: uses: ./.github/workflows/deploy-backend.yml with: apigee_environment: internal-dev - build_recordprocessor_image: ${{ github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' }} + build_recordprocessor_image: ${{ github.event.action == 'opened' || github.event.action == 'reopened' || needs.detect-recordprocessor-changes.outputs.has_changes == 'true' }} create_mns_subscription: true environment: dev sub_environment: pr-${{github.event.pull_request.number}} From 1450b4f255ac304f84764e7b5f10eda4cb693f47 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 10:21:48 +0000 Subject: [PATCH 28/31] chore: ado build kickstart EmptyCommit: From fe43be306d2dc29b89ea034fea30a419f2492607 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 10:31:06 +0000 Subject: [PATCH 29/31] Enhance deployment workflow for recordprocessor image management - Added a new job to resolve existing recordprocessor image tags when not building a new image, improving flexibility in deployment. - Updated job dependencies to ensure proper sequencing between building and resolving image tags. - Refined output handling for `recordprocessor_image_tag` to accommodate both build and resolve scenarios, enhancing clarity in image management. --- .github/workflows/deploy-backend.yml | 38 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 7d1735767d..6e475f3321 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -61,11 +61,12 @@ run-name: Deploy Backend - ${{ inputs.environment }} ${{ inputs.sub_environment jobs: build-and-push-recordprocessor: + if: ${{ inputs.build_recordprocessor_image }} permissions: id-token: write contents: read outputs: - recordprocessor_image_tag: ${{ steps.build-image.outputs.recordprocessor_image_tag || steps.resolve-image-tag.outputs.recordprocessor_image_tag }} + recordprocessor_image_tag: ${{ steps.build-image.outputs.recordprocessor_image_tag }} name: Build and push recordprocessor image runs-on: ubuntu-latest @@ -88,13 +89,11 @@ jobs: role-session-name: github-actions - name: Login to Amazon ECR - if: ${{ inputs.build_recordprocessor_image }} id: login-ecr uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 - name: Build and push Docker image id: build-image - if: ${{ inputs.build_recordprocessor_image }} env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} working-directory: lambdas @@ -107,9 +106,29 @@ jobs: docker push "${IMAGE_URI}" echo "recordprocessor_image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + resolve-recordprocessor-image-tag: + if: ${{ !inputs.build_recordprocessor_image }} + permissions: + id-token: write + contents: read + outputs: + recordprocessor_image_tag: ${{ steps.resolve-image-tag.outputs.recordprocessor_image_tag }} + name: Resolve existing recordprocessor image tag + runs-on: ubuntu-latest + environment: + name: ${{ inputs.environment }} + env: + AWS_REGION: eu-west-2 + steps: + - name: Connect to AWS + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 + with: + aws-region: eu-west-2 + role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops + role-session-name: github-actions + - name: Resolve latest matching recordprocessor image tag id: resolve-image-tag - if: ${{ !inputs.build_recordprocessor_image }} env: REPOSITORY_NAME: imms-recordprocessor-repo TAG_PREFIX: ${{ inputs.sub_environment }}- @@ -139,10 +158,15 @@ jobs: permissions: id-token: write contents: read - needs: build-and-push-recordprocessor + needs: + - build-and-push-recordprocessor + - resolve-recordprocessor-image-tag + if: ${{ !cancelled() && (needs.build-and-push-recordprocessor.result == 'success' || needs.resolve-recordprocessor-image-tag.result == 'success') }} + outputs: + recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag || needs.resolve-recordprocessor-image-tag.outputs.recordprocessor_image_tag }} runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag }} + TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag || needs.resolve-recordprocessor-image-tag.outputs.recordprocessor_image_tag }} environment: name: ${{ inputs.environment }} steps: @@ -184,7 +208,7 @@ jobs: needs: terraform-plan runs-on: ubuntu-latest env: - TF_VAR_recordprocessor_image_tag: ${{ needs.build-and-push-recordprocessor.outputs.recordprocessor_image_tag }} + TF_VAR_recordprocessor_image_tag: ${{ needs.terraform-plan.outputs.recordprocessor_image_tag }} environment: name: ${{ inputs.environment }} steps: From c5b5dba08fac8881c76aa053e3d21ee28dd8a618 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 11:49:01 +0000 Subject: [PATCH 30/31] chore: ado build kickstart EmptyCommit: From 4ead26b730ec1789a892ac9e7e561cfb6b378680 Mon Sep 17 00:00:00 2001 From: Thomas-Boyle Date: Thu, 12 Mar 2026 12:19:59 +0000 Subject: [PATCH 31/31] - Added a conditional check to the deployment job to ensure it only runs if the previous terraform plan was successful and not cancelled, improving workflow reliability. --- .github/workflows/deploy-backend.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml index 6e475f3321..5ad490df93 100644 --- a/.github/workflows/deploy-backend.yml +++ b/.github/workflows/deploy-backend.yml @@ -206,6 +206,7 @@ jobs: id-token: write contents: read needs: terraform-plan + if: ${{ !cancelled() && needs.terraform-plan.result == 'success' }} runs-on: ubuntu-latest env: TF_VAR_recordprocessor_image_tag: ${{ needs.terraform-plan.outputs.recordprocessor_image_tag }}