diff --git a/.github/actions/acceptance-tests/action.yaml b/.github/actions/acceptance-tests/action.yaml index 3b76f9bb8..14f06ae9a 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" @@ -38,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 @@ -58,6 +76,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 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 } ) }') diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index 9309aec55..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" @@ -189,6 +190,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..1ab9a9cc1 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 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/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..0f3784b02 100644 --- a/infrastructure/terraform/components/dl/variables.tf +++ b/infrastructure/terraform/components/dl/variables.tf @@ -319,3 +319,15 @@ 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 +} + +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 61, default is 301." + default = 301 +} 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" 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, - }, - }); -});