From bf33c5a8cf9fee55cd2525abf037a47ac2d4cdfb Mon Sep 17 00:00:00 2001 From: christopherjohnson Date: Fri, 26 Jun 2026 15:40:21 +0100 Subject: [PATCH 1/6] AB#127298 add Playwright smoke tests for deployment checks --- .github/workflows/test_deployment.yml | 49 ++++++++++++++ deployment/.env.example | 2 + deployment/.gitignore | 3 + deployment/.nvmrc | 1 + deployment/README.md | 16 +++++ deployment/deployment.test.js | 30 +++++++++ deployment/package-lock.json | 92 +++++++++++++++++++++++++++ deployment/package.json | 17 +++++ deployment/playwright.config.js | 6 ++ 9 files changed, 216 insertions(+) create mode 100644 .github/workflows/test_deployment.yml create mode 100644 deployment/.env.example create mode 100644 deployment/.gitignore create mode 100644 deployment/.nvmrc create mode 100644 deployment/README.md create mode 100644 deployment/deployment.test.js create mode 100644 deployment/package-lock.json create mode 100644 deployment/package.json create mode 100644 deployment/playwright.config.js diff --git a/.github/workflows/test_deployment.yml b/.github/workflows/test_deployment.yml new file mode 100644 index 0000000..d60eac6 --- /dev/null +++ b/.github/workflows/test_deployment.yml @@ -0,0 +1,49 @@ + +# This waits for the backend to be available and then performs the deployment tests. +# The deployment tests are available in the 'deployment' folder in the root of the project. + +name: Test Deployment +run-name: "Test deployment for the ${{ inputs.execution-environment }} environment" + +on: + workflow_call: + inputs: + execution-environment: + description: "Environment" + required: true + type: string + workflow_dispatch: + inputs: + execution-environment: + type: choice + description: "Environment" + required: true + default: 'BETA' + options: + - BETA + - PROD + +jobs: + deployment-tests: + # Only run the checks when on the default or release branch + if: github.ref_name == 'master' || github.ref_name == 'release' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-22.04 + timeout-minutes: 5 + environment: ${{ inputs.execution-environment }} + env: + URL: ${{ vars.URL }} + defaults: + run: + working-directory: deployment + steps: + - uses: actions/checkout@v6 + - name: Wait the backend to startup up and serve the index + run: curl -I --show-error --silent --retry 10 --retry-connrefused --retry-delay 10 ${{ env.URL }} + - uses: actions/setup-node@v6 + with: + node-version-file: 'deployment/.nvmrc' + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + - run: npm ci + - run: npm run install-browsers + - run: npm test diff --git a/deployment/.env.example b/deployment/.env.example new file mode 100644 index 0000000..d11d83a --- /dev/null +++ b/deployment/.env.example @@ -0,0 +1,2 @@ +URL= +JWKS_URL= \ No newline at end of file diff --git a/deployment/.gitignore b/deployment/.gitignore new file mode 100644 index 0000000..945fcd0 --- /dev/null +++ b/deployment/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +playwright-report/ +test-results/ diff --git a/deployment/.nvmrc b/deployment/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/deployment/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/deployment/README.md b/deployment/README.md new file mode 100644 index 0000000..29d7692 --- /dev/null +++ b/deployment/README.md @@ -0,0 +1,16 @@ +# Deployment Playwright Tests + +This directory contains Playwright smoke tests for deployment checks. + +## Install + +```bash +cd deployment +npm install +``` + +## Run + +```bash +npm test +``` diff --git a/deployment/deployment.test.js b/deployment/deployment.test.js new file mode 100644 index 0000000..20197e1 --- /dev/null +++ b/deployment/deployment.test.js @@ -0,0 +1,30 @@ +import { test, expect } from '@playwright/test' +import 'dotenv/config' + +test('smoke check: JWKS endpoint returns a valid JWK Set', async ({ request }) => { + const jwksUrl = process.env.JWKS_URL + if (!jwksUrl) { + throw new Error("JWKS_URL not configured.") + } + + const response = await request.get(jwksUrl) + expect(response.ok()).toBeTruthy() + + const body = await response.json() + expect(body).toEqual(expect.objectContaining({ keys: expect.any(Array) })) + expect(body.keys.length).toBeGreaterThan(0) + + for (const key of body.keys) { + expect(key).toEqual(expect.objectContaining({ + kty: 'RSA', + kid: expect.any(String), + use: 'sig', + alg: 'RS256', + n: expect.any(String), + e: expect.any(String), + })) + + expect(key.n).toEqual(expect.any(String)) + expect(key.e).toEqual(expect.any(String)) + } +}) diff --git a/deployment/package-lock.json b/deployment/package-lock.json new file mode 100644 index 0000000..78ea15a --- /dev/null +++ b/deployment/package-lock.json @@ -0,0 +1,92 @@ +{ + "name": "tool-support-deployment-tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tool-support-deployment-tests", + "version": "1.0.0", + "devDependencies": { + "@playwright/test": "^1.60.0", + "dotenv": "^17.4.2" + } + }, + "node_modules/@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + } + } +} diff --git a/deployment/package.json b/deployment/package.json new file mode 100644 index 0000000..f177fad --- /dev/null +++ b/deployment/package.json @@ -0,0 +1,17 @@ +{ + "name": "tool-support-deployment-tests", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Playwright smoke tests for deployed tool-support endpoints", + "scripts": { + "install-browsers": "npx playwright install --with-deps chromium", + "test": "playwright test", + "test:ci": "CI=true npm test", + "test:report": "npx playwright show-report" + }, + "devDependencies": { + "@playwright/test": "^1.60.0", + "dotenv": "^17.4.2" + } +} diff --git a/deployment/playwright.config.js b/deployment/playwright.config.js new file mode 100644 index 0000000..ac23602 --- /dev/null +++ b/deployment/playwright.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from '@playwright/test' + +export default defineConfig({ + timeout: 60000, + retries: 2 +}) From aaa50dcbfebe392d9b76ebe74b76351b4dbbfc06 Mon Sep 17 00:00:00 2001 From: sebastianchristopher <40264653+sebastianchristopher@users.noreply.github.com> Date: Fri, 26 Jun 2026 15:50:17 +0100 Subject: [PATCH 2/6] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/test_deployment.yml | 5 ++--- deployment/.gitignore | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_deployment.yml b/.github/workflows/test_deployment.yml index d60eac6..2dcaa46 100644 --- a/.github/workflows/test_deployment.yml +++ b/.github/workflows/test_deployment.yml @@ -3,7 +3,7 @@ # The deployment tests are available in the 'deployment' folder in the root of the project. name: Test Deployment -run-name: "Test deployment for the ${{ inputs.execution-environment }} environment" +run-name: "Test deployment for the ${{ inputs.execution-environment }} environment" on: workflow_call: @@ -37,7 +37,7 @@ jobs: working-directory: deployment steps: - uses: actions/checkout@v6 - - name: Wait the backend to startup up and serve the index + - name: Wait for the backend to start up and serve the index run: curl -I --show-error --silent --retry 10 --retry-connrefused --retry-delay 10 ${{ env.URL }} - uses: actions/setup-node@v6 with: @@ -45,5 +45,4 @@ jobs: cache: 'npm' cache-dependency-path: '**/package-lock.json' - run: npm ci - - run: npm run install-browsers - run: npm test diff --git a/deployment/.gitignore b/deployment/.gitignore index 945fcd0..6665269 100644 --- a/deployment/.gitignore +++ b/deployment/.gitignore @@ -1,3 +1,4 @@ node_modules/ +.env playwright-report/ test-results/ From 59a1903613c0e8c1cf8730ce505e95733cea27ed Mon Sep 17 00:00:00 2001 From: christopherjohnson Date: Fri, 26 Jun 2026 15:53:19 +0100 Subject: [PATCH 3/6] AB#127298 add Playwright smoke tests for deployment checks * construct JWKS url from base url --- deployment/deployment.test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/deployment/deployment.test.js b/deployment/deployment.test.js index 20197e1..849ded2 100644 --- a/deployment/deployment.test.js +++ b/deployment/deployment.test.js @@ -2,11 +2,13 @@ import { test, expect } from '@playwright/test' import 'dotenv/config' test('smoke check: JWKS endpoint returns a valid JWK Set', async ({ request }) => { - const jwksUrl = process.env.JWKS_URL - if (!jwksUrl) { - throw new Error("JWKS_URL not configured.") + const url = process.env.URL + if (!url) { + throw new Error("URL not configured.") } + const jwksUrl = new URL('/.well-known/jwks.json', url).toString() + const response = await request.get(jwksUrl) expect(response.ok()).toBeTruthy() From feb98b8878c78a99c5882d4f7b765e67b43f0325 Mon Sep 17 00:00:00 2001 From: christopherjohnson Date: Fri, 26 Jun 2026 15:53:43 +0100 Subject: [PATCH 4/6] AB#127298 add Playwright smoke tests for deployment checks * construct JWKS url from base url --- deployment/.env.example | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deployment/.env.example b/deployment/.env.example index d11d83a..c8a526e 100644 --- a/deployment/.env.example +++ b/deployment/.env.example @@ -1,2 +1 @@ -URL= -JWKS_URL= \ No newline at end of file +URL= \ No newline at end of file From 66f9e87e7d8236511547abe98b698afe6b6d38ea Mon Sep 17 00:00:00 2001 From: christopherjohnson Date: Tue, 30 Jun 2026 10:47:24 +0100 Subject: [PATCH 5/6] add deployment tests workflow to build and deploy process --- .github/workflows/build_and_deploy.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 4232c66..2d57d5f 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -190,4 +190,11 @@ jobs: - run: echo VERSION_REF=$(aws cloudformation list-exports --query "Exports[?Name=='${{ inputs.app_name }}-${{ inputs.env_type }}-${{ inputs.account_type }}-backend-version'].Value" --output text) | tee -a $GITHUB_ENV - run: echo RUNNING_VERSION_REF=$(aws elasticbeanstalk describe-environments | jq -r '.Environments | map(select(.EnvironmentName == "${{ inputs.app_name }}-${{ inputs.env_type }}")) | .[] | .VersionLabel') | tee -a $GITHUB_ENV - if: env.VERSION_REF != env.RUNNING_VERSION_REF - run: echo "current version does not match deployed version"; exit 1 \ No newline at end of file + run: echo "current version does not match deployed version"; exit 1 + + call-deployment-tests: + needs: [ deploy ] + uses: ./.github/workflows/test_deployment.yml + with: + execution-environment: ${{ inputs.env_type }} + secrets: inherit \ No newline at end of file From 5dc602fa0ab023382ebe7f12472fd1f7b7ce362e Mon Sep 17 00:00:00 2001 From: Matthew Buckett Date: Thu, 2 Jul 2026 09:01:53 +0100 Subject: [PATCH 6/6] AB#113343 Drop the ssh access This isn't needed any more as we can use AWS SSM to access the instance if needed and it's creating warnings in AWS Trust Advisor about unrestricted ports. --- aws/eb-env.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/aws/eb-env.yaml b/aws/eb-env.yaml index f645196..5123e1a 100644 --- a/aws/eb-env.yaml +++ b/aws/eb-env.yaml @@ -319,9 +319,6 @@ Resources: - Namespace: "aws:autoscaling:launchconfiguration" OptionName: "InstanceType" Value: !Ref instanceSize - - Namespace: "aws:autoscaling:launchconfiguration" - OptionName: "SSHSourceRestriction" - Value: "tcp,22,22,0.0.0.0/0" - ResourceName: "AWSEBEC2LaunchTemplate" Namespace: "aws:autoscaling:launchconfiguration" OptionName: "SecurityGroups" @@ -357,10 +354,6 @@ Resources: - Namespace: "aws:elasticbeanstalk:command" OptionName: "DeploymentPolicy" Value: !If [isProd, "Immutable", "AllAtOnce"] - - Namespace: "aws:elasticbeanstalk:control" - OptionName: "DefaultSSHPort" - Value: "22" - # Fn::ImportValue: !Sub "${orgName}-${accountType}-ssh-port" ## LOad Balancer bits - Namespace: "aws:elasticbeanstalk:environment" OptionName: "EnvironmentType"