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 diff --git a/.github/workflows/test_deployment.yml b/.github/workflows/test_deployment.yml new file mode 100644 index 0000000..2dcaa46 --- /dev/null +++ b/.github/workflows/test_deployment.yml @@ -0,0 +1,48 @@ + +# 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 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: + node-version-file: 'deployment/.nvmrc' + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + - run: npm ci + - run: npm test 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" diff --git a/deployment/.env.example b/deployment/.env.example new file mode 100644 index 0000000..c8a526e --- /dev/null +++ b/deployment/.env.example @@ -0,0 +1 @@ +URL= \ No newline at end of file diff --git a/deployment/.gitignore b/deployment/.gitignore new file mode 100644 index 0000000..6665269 --- /dev/null +++ b/deployment/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +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..849ded2 --- /dev/null +++ b/deployment/deployment.test.js @@ -0,0 +1,32 @@ +import { test, expect } from '@playwright/test' +import 'dotenv/config' + +test('smoke check: JWKS endpoint returns a valid JWK Set', async ({ request }) => { + 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() + + 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 +})