From 34f6bc64b203f9f5644323482308698a1ae11b9b Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 09:03:17 +0100 Subject: [PATCH 1/6] Shard component tests --- .github/workflows/cicd-1-pull-request.yaml | 1 + .github/workflows/stage-4-acceptance.yaml | 8 ++++++- .../terraform/components/dl/README.md | 2 ++ ...irehose_delivery_stream_to_s3_reporting.tf | 4 ++-- .../terraform/components/dl/variables.tf | 17 +++++++++++++++ .../config/component/component.config.ts | 11 +--------- .../config/component/firehose.setup.ts | 21 ------------------- .../config/component/firehose.teardown.ts | 21 ------------------- 8 files changed, 30 insertions(+), 55 deletions(-) delete mode 100644 tests/playwright/config/component/firehose.setup.ts delete mode 100644 tests/playwright/config/component/firehose.teardown.ts diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index 9309aec55..78ee48627 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -189,6 +189,7 @@ jobs: with: target_environment: "pr${{ needs.metadata.outputs.pr_number }}" target_account_group: nhs-notify-digital-letters-dev + internal_ref: "feature/enable-component-test-sharding" secrets: APP_PEM_FILE: ${{ secrets.APP_PEM_FILE }} APP_CLIENT_ID: ${{ secrets.APP_CLIENT_ID }} diff --git a/.github/workflows/stage-4-acceptance.yaml b/.github/workflows/stage-4-acceptance.yaml index cbd3b1551..9942e4450 100644 --- a/.github/workflows/stage-4-acceptance.yaml +++ b/.github/workflows/stage-4-acceptance.yaml @@ -20,6 +20,10 @@ on: description: "Account for the environment being tested" required: true type: string + internal_ref: + description: "Branch or ref to use in nhs-notify-internal (defaults to main)" + required: false + type: string jobs: test-security: @@ -84,7 +88,9 @@ jobs: --targetWorkflow "dispatch-contextual-tests-dynamic-env.yaml" \ --targetEnvironment "$TARGET_ENVIRONMENT" \ --targetAccountGroup "$TARGET_ACCOUNT_GROUP" \ - --targetComponent "dl" + --targetComponent "dl" \ + --internalRef "${{ inputs.internal_ref || 'main' }}" \ + --enableSharding "true" test-accessibility: name: "Accessibility test" runs-on: ubuntu-latest diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 9e4fe840b..6bdc47e2f 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -34,6 +34,8 @@ No requirements. | [event\_anomaly\_period](#input\_event\_anomaly\_period) | The period in seconds over which the specified statistic is applied for anomaly detection. Minimum 300 seconds (5 minutes). Recommended: 300-600. | `number` | `300` | no | | [eventpub\_control\_plane\_bus\_arn](#input\_eventpub\_control\_plane\_bus\_arn) | Event publisher control plane | `string` | n/a | yes | | [eventpub\_data\_plane\_bus\_arn](#input\_eventpub\_data\_plane\_bus\_arn) | Event publisher data plane | `string` | n/a | yes | +| [firehose\_destination\_buffer\_interval](#input\_firehose\_destination\_buffer\_interval) | The Firehose destination buffer interval in seconds. Lower values reduce latency for tests but increase costs. Minimum is 60, default (Terraform) is 300. | `number` | `300` | no | +| [firehose\_processor\_buffer\_interval](#input\_firehose\_processor\_buffer\_interval) | The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose\_destination\_buffer\_interval. Minimum is 0, default is 301. | `number` | `301` | no | | [force\_destroy](#input\_force\_destroy) | Flag to force deletion of S3 buckets | `bool` | `false` | no | | [force\_lambda\_code\_deploy](#input\_force\_lambda\_code\_deploy) | If the lambda package in s3 has the same commit id tag as the terraform build branch, the lambda will not update automatically. Set to True if making changes to Lambda code from on the same commit for example during development | `bool` | `false` | no | | [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | n/a | yes | diff --git a/infrastructure/terraform/components/dl/kinesis_firehose_delivery_stream_to_s3_reporting.tf b/infrastructure/terraform/components/dl/kinesis_firehose_delivery_stream_to_s3_reporting.tf index 86efee7f4..0be07006e 100644 --- a/infrastructure/terraform/components/dl/kinesis_firehose_delivery_stream_to_s3_reporting.tf +++ b/infrastructure/terraform/components/dl/kinesis_firehose_delivery_stream_to_s3_reporting.tf @@ -11,7 +11,7 @@ resource "aws_kinesis_firehose_delivery_stream" "to_s3_reporting" { error_output_prefix = "${local.firehose_output_path_prefix}/errors/!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}-!{timestamp:HH}/!{firehose:error-output-type}/" buffering_size = 128 - buffering_interval = 300 + buffering_interval = var.firehose_destination_buffer_interval dynamic_partitioning_configuration { enabled = true @@ -37,7 +37,7 @@ resource "aws_kinesis_firehose_delivery_stream" "to_s3_reporting" { } parameters { parameter_name = "BufferIntervalInSeconds" - parameter_value = 301 + parameter_value = var.firehose_processor_buffer_interval } } } diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 2f9406c3d..581ced9b4 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -319,3 +319,20 @@ variable "event_anomaly_band_width" { error_message = "Band width must be between 2 and 10" } } + +variable "firehose_destination_buffer_interval" { + type = number + description = "The Firehose destination buffer interval in seconds. Lower values reduce latency for tests but increase costs. Minimum is 60, default (Terraform) is 300." + default = 300 + + validation { + condition = var.firehose_destination_buffer_interval >= 60 && var.firehose_destination_buffer_interval <= 900 + error_message = "Buffer interval must be between 60 and 900 seconds." + } +} + +variable "firehose_processor_buffer_interval" { + type = number + description = "The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose_destination_buffer_interval. Minimum is 0, default is 301." + default = 301 +} diff --git a/tests/playwright/config/component/component.config.ts b/tests/playwright/config/component/component.config.ts index 87ca74faa..340e7bb3a 100644 --- a/tests/playwright/config/component/component.config.ts +++ b/tests/playwright/config/component/component.config.ts @@ -13,19 +13,10 @@ export default defineConfig({ name: 'senders:setup', testMatch: 'senders.setup.ts', }, - { - name: 'firehose:setup', - testMatch: 'firehose.setup.ts', - teardown: 'firehose:teardown', - }, - { - name: 'firehose:teardown', - testMatch: 'firehose.teardown.ts', - }, { name: 'component', testMatch: '*.component.spec.ts', - dependencies: ['senders:setup', 'firehose:setup'], + dependencies: ['senders:setup'], teardown: 'component:teardown', }, { diff --git a/tests/playwright/config/component/firehose.setup.ts b/tests/playwright/config/component/firehose.setup.ts deleted file mode 100644 index f7ecf537e..000000000 --- a/tests/playwright/config/component/firehose.setup.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { test as setup } from '@playwright/test'; -import { - MINIMUM_DESTINATION_BUFFER_INTERVAL, - MINIMUM_PROCESSOR_BUFFER_INTERVAL, - TERRAFORM_DESTINATION_BUFFER_INTERVAL, - TERRAFORM_PROCESSOR_BUFFER_INTERVAL, -} from 'constants/backend-constants'; -import { alterFirehoseBufferIntervals } from 'helpers/data-firehose-helpers'; - -setup('Reduce Firehose buffer intervals', async () => { - await alterFirehoseBufferIntervals({ - expected: { - destination: TERRAFORM_DESTINATION_BUFFER_INTERVAL, - processor: TERRAFORM_PROCESSOR_BUFFER_INTERVAL, - }, - update: { - destination: MINIMUM_DESTINATION_BUFFER_INTERVAL, - processor: MINIMUM_PROCESSOR_BUFFER_INTERVAL, - }, - }); -}); diff --git a/tests/playwright/config/component/firehose.teardown.ts b/tests/playwright/config/component/firehose.teardown.ts deleted file mode 100644 index 11844458c..000000000 --- a/tests/playwright/config/component/firehose.teardown.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { test as teardown } from '@playwright/test'; -import { - MINIMUM_DESTINATION_BUFFER_INTERVAL, - MINIMUM_PROCESSOR_BUFFER_INTERVAL, - TERRAFORM_DESTINATION_BUFFER_INTERVAL, - TERRAFORM_PROCESSOR_BUFFER_INTERVAL, -} from 'constants/backend-constants'; -import { alterFirehoseBufferIntervals } from 'helpers/data-firehose-helpers'; - -teardown('Restore Firehose buffer intervals', async () => { - await alterFirehoseBufferIntervals({ - expected: { - destination: MINIMUM_DESTINATION_BUFFER_INTERVAL, - processor: MINIMUM_PROCESSOR_BUFFER_INTERVAL, - }, - update: { - destination: TERRAFORM_DESTINATION_BUFFER_INTERVAL, - processor: TERRAFORM_PROCESSOR_BUFFER_INTERVAL, - }, - }); -}); From aa419e2b296ce54f8df0499eb627e7a6694623a3 Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 10:26:02 +0100 Subject: [PATCH 2/6] Test --- .github/scripts/dispatch_internal_repo_workflow.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/scripts/dispatch_internal_repo_workflow.sh b/.github/scripts/dispatch_internal_repo_workflow.sh index a52c1bbee..21b78a5e7 100755 --- a/.github/scripts/dispatch_internal_repo_workflow.sh +++ b/.github/scripts/dispatch_internal_repo_workflow.sh @@ -80,6 +80,10 @@ while [[ $# -gt 0 ]]; do overrideRoleName="$2" shift 2 ;; + --enableSharding) # Enable test sharding across 4 parallel jobs (optional) + enableSharding="$2" + shift 2 + ;; *) echo "[ERROR] Unknown argument: $1" exit 1 @@ -167,6 +171,7 @@ echo " overrides: $overrides" echo " overrideProjectName: $overrideProjectName" echo " overrideRoleName: $overrideRoleName" echo " targetProject: $targetProject" +echo " enableSharding: ${enableSharding:-}" DISPATCH_EVENT=$(jq -ncM \ --arg infraRepoName "$infraRepoName" \ @@ -180,6 +185,7 @@ DISPATCH_EVENT=$(jq -ncM \ --arg overrideProjectName "$overrideProjectName" \ --arg overrideRoleName "$overrideRoleName" \ --arg targetProject "$targetProject" \ + --argjson enableSharding "${enableSharding:-false}" \ '{ "ref": "'"$internalRef"'", "inputs": ( @@ -188,12 +194,13 @@ DISPATCH_EVENT=$(jq -ncM \ (if $overrideProjectName != "" then { "overrideProjectName": $overrideProjectName } else {} end) + (if $overrideRoleName != "" then { "overrideRoleName": $overrideRoleName } else {} end) + (if $targetProject != "" then { "targetProject": $targetProject } else {} end) + + (if $enableSharding then { "enableSharding": $enableSharding } else {} end) + { "releaseVersion": $releaseVersion, "targetEnvironment": $targetEnvironment, "targetAccountGroup": $targetAccountGroup, "targetComponent": $targetComponent, - "overrides": $overrides, + "overrides": $overrides } ) }') From d0547c43da5f0288d7a71e613de2a8ff1b02fe58 Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 11:13:20 +0100 Subject: [PATCH 3/6] Test --- scripts/tests/integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests/integration.sh b/scripts/tests/integration.sh index 893c4efc2..f583f0b54 100755 --- a/scripts/tests/integration.sh +++ b/scripts/tests/integration.sh @@ -9,4 +9,4 @@ npx playwright install --with-deps > /dev/null cd tests/playwright -npm run test:component +npm run test:component -- --shard="$PLAYWRIGHT_SHARD" From a976b8b248369ab8454ceebbfd324d293bcb38d3 Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 12:02:14 +0100 Subject: [PATCH 4/6] Test --- .github/actions/acceptance-tests/action.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/actions/acceptance-tests/action.yaml b/.github/actions/acceptance-tests/action.yaml index 3b76f9bb8..cccce8d4e 100644 --- a/.github/actions/acceptance-tests/action.yaml +++ b/.github/actions/acceptance-tests/action.yaml @@ -21,6 +21,11 @@ inputs: description: Name of the component under test default: dl + shard: + description: "Playwright shard in format index/total (e.g. 1/4). If empty, runs all tests." + required: false + default: "" + runs: using: "composite" @@ -58,6 +63,7 @@ runs: env: TEST_TYPE: ${{ inputs.testType }} ENVIRONMENT: ${{ inputs.targetEnvironment }} + PLAYWRIGHT_SHARD: ${{ inputs.shard }} - name: Archive integration test results if: ${{ inputs.testType == 'integration' }} uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 From d03093c1d95b532cd6d3aac2eed980ee2abf307a Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 14:26:35 +0100 Subject: [PATCH 5/6] Test --- .github/workflows/cicd-1-pull-request.yaml | 1 + infrastructure/terraform/components/dl/README.md | 2 +- infrastructure/terraform/components/dl/variables.tf | 7 +------ 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index 78ee48627..7e2c7faef 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -180,6 +180,7 @@ jobs: --terraformAction "apply" \ --overrideProjectName "nhs" \ --overrideRoleName "nhs-main-acct-digital-letters-github-deploy" \ + --internalRef "feature/enable-component-test-sharding" \ --overrides "branch_name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" acceptance-stage: # Recommended maximum execution time is 10 minutes name: "Acceptance stage" diff --git a/infrastructure/terraform/components/dl/README.md b/infrastructure/terraform/components/dl/README.md index 6bdc47e2f..1ab9a9cc1 100644 --- a/infrastructure/terraform/components/dl/README.md +++ b/infrastructure/terraform/components/dl/README.md @@ -35,7 +35,7 @@ No requirements. | [eventpub\_control\_plane\_bus\_arn](#input\_eventpub\_control\_plane\_bus\_arn) | Event publisher control plane | `string` | n/a | yes | | [eventpub\_data\_plane\_bus\_arn](#input\_eventpub\_data\_plane\_bus\_arn) | Event publisher data plane | `string` | n/a | yes | | [firehose\_destination\_buffer\_interval](#input\_firehose\_destination\_buffer\_interval) | The Firehose destination buffer interval in seconds. Lower values reduce latency for tests but increase costs. Minimum is 60, default (Terraform) is 300. | `number` | `300` | no | -| [firehose\_processor\_buffer\_interval](#input\_firehose\_processor\_buffer\_interval) | The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose\_destination\_buffer\_interval. Minimum is 0, default is 301. | `number` | `301` | no | +| [firehose\_processor\_buffer\_interval](#input\_firehose\_processor\_buffer\_interval) | The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose\_destination\_buffer\_interval. Minimum is 61, default is 301. | `number` | `301` | no | | [force\_destroy](#input\_force\_destroy) | Flag to force deletion of S3 buckets | `bool` | `false` | no | | [force\_lambda\_code\_deploy](#input\_force\_lambda\_code\_deploy) | If the lambda package in s3 has the same commit id tag as the terraform build branch, the lambda will not update automatically. Set to True if making changes to Lambda code from on the same commit for example during development | `bool` | `false` | no | | [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | n/a | yes | diff --git a/infrastructure/terraform/components/dl/variables.tf b/infrastructure/terraform/components/dl/variables.tf index 581ced9b4..0f3784b02 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -324,15 +324,10 @@ variable "firehose_destination_buffer_interval" { type = number description = "The Firehose destination buffer interval in seconds. Lower values reduce latency for tests but increase costs. Minimum is 60, default (Terraform) is 300." default = 300 - - validation { - condition = var.firehose_destination_buffer_interval >= 60 && var.firehose_destination_buffer_interval <= 900 - error_message = "Buffer interval must be between 60 and 900 seconds." - } } variable "firehose_processor_buffer_interval" { type = number - description = "The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose_destination_buffer_interval. Minimum is 0, default is 301." + description = "The Firehose Lambda processor buffer interval in seconds. Should be greater than firehose_destination_buffer_interval. Minimum is 61, default is 301." default = 301 } From 54f6830a9ec7c9a8abfc8bdcd76e9b948c934d8e Mon Sep 17 00:00:00 2001 From: lapenna-bjss Date: Mon, 27 Apr 2026 15:30:37 +0100 Subject: [PATCH 6/6] Add cache for Generate dependencies step --- .github/actions/acceptance-tests/action.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/actions/acceptance-tests/action.yaml b/.github/actions/acceptance-tests/action.yaml index cccce8d4e..14f06ae9a 100644 --- a/.github/actions/acceptance-tests/action.yaml +++ b/.github/actions/acceptance-tests/action.yaml @@ -43,7 +43,20 @@ runs: shell: bash run: | npm ci + - name: Cache generated dependencies + id: cache-generated + uses: actions/cache@v4 + with: + path: | + schemas/digital-letters/ + output/digital-letters/ + src/digital-letters-events/types/ + src/digital-letters-events/validators/ + src/digital-letters-events/guard-functions/ + src/digital-letters-events/digital_letters_events/models/ + key: generated-deps-${{ hashFiles('src/cloudevents/**') }} - name: "Generate dependencies" + if: steps.cache-generated.outputs.cache-hit != 'true' shell: bash run: | npm run generate-dependencies