Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
71f32bf
tests passing locally
Vlasis-Perdikidis Jul 27, 2026
2bd2e59
re-enable sandbox tests in pipeline
Vlasis-Perdikidis Jul 27, 2026
4c4e46f
correct SUPPLIER_API_URL_SANDBOX for pipeilne
Vlasis-Perdikidis Jul 28, 2026
2d0da5a
reference PR-927 from internal
Vlasis-Perdikidis Jul 29, 2026
a63f98b
deploy proxy
Vlasis-Perdikidis Jul 29, 2026
986e5a7
trigger build
Vlasis-Perdikidis Jul 29, 2026
888cc70
trigger another build
Vlasis-Perdikidis Jul 30, 2026
f745942
trigger another build
Vlasis-Perdikidis Jul 30, 2026
4a4bdd4
trigger another build
Vlasis-Perdikidis Jul 30, 2026
d842802
trigger another build
Vlasis-Perdikidis Aug 11, 2026
ccd3790
trigger another build
Vlasis-Perdikidis Aug 11, 2026
8f17205
commit local changes
Vlasis-Perdikidis Aug 12, 2026
6925401
trigger build
Vlasis-Perdikidis Aug 13, 2026
9fa5f4f
remove TODO comments
Vlasis-Perdikidis Aug 13, 2026
f2a3e76
sync package-lock.json
Vlasis-Perdikidis Aug 13, 2026
28c5a55
restore package-lock.json file from main
Vlasis-Perdikidis Aug 13, 2026
43f304b
trigger another build
Vlasis-Perdikidis Aug 14, 2026
73ab704
start sandbox server before running sandbox tests
Vlasis-Perdikidis Aug 19, 2026
e2e0fab
point to PR659 proxy
Vlasis-Perdikidis Aug 21, 2026
640a5b2
remove step that starts the container
Vlasis-Perdikidis Aug 24, 2026
3093564
remove lines for creating/starting the sandbox container
Vlasis-Perdikidis Aug 24, 2026
1b5db66
upload sandbox spec file
Vlasis-Perdikidis Aug 26, 2026
510910f
place artifacts into separate folders
Vlasis-Perdikidis Aug 27, 2026
1916caa
correct download sandbox artifact name
Vlasis-Perdikidis Aug 27, 2026
1a816ba
place sandbox spec to separate file instead of sub-folder
Vlasis-Perdikidis Aug 27, 2026
e68b067
Merge branch 'main' into fix/CCM-20834-fix_sandbox_tests
Vlasis-Perdikidis Aug 27, 2026
824552a
remove comments and add information on how to run sandbox tests
Vlasis-Perdikidis Aug 27, 2026
da528dc
commit the sandbox package-lock file
Vlasis-Perdikidis Aug 27, 2026
362135e
resolve peer dependency issues in sandbox dependencies
Vlasis-Perdikidis Aug 27, 2026
85d898c
resolve PR URL first for supplier_api_url_sandbox
Vlasis-Perdikidis Aug 27, 2026
49cc72a
modify the condition
Vlasis-Perdikidis Aug 28, 2026
1fb0a00
echo event_name
Vlasis-Perdikidis Aug 28, 2026
1958b68
set event_name=workflow_dispatch
Vlasis-Perdikidis Aug 28, 2026
8222c9c
separate sandbox workflow
Vlasis-Perdikidis Sep 1, 2026
8727f63
rename sandbox proxy file
Vlasis-Perdikidis Sep 2, 2026
39f9efb
correctly derive the sandbox URL
Vlasis-Perdikidis Sep 3, 2026
c836026
tidy up PR
Vlasis-Perdikidis Sep 3, 2026
8e778ca
Merge branch 'main' into fix/CCM-20834-fix_sandbox_tests
Vlasis-Perdikidis Sep 3, 2026
ce55384
remove incorrect SUPPLIER_API_URL_SANDBOX variable set
Vlasis-Perdikidis Sep 3, 2026
79b14a8
remove unused action inputs and increase stage-2-test timeout to 10 m…
Vlasis-Perdikidis Sep 3, 2026
68be8b2
rebase with main
Vlasis-Perdikidis Sep 7, 2026
686fa53
remove internalRef
Vlasis-Perdikidis Sep 7, 2026
2f8e180
remove note-to-self comments
Vlasis-Perdikidis Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/actions/acceptance-tests-components/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ runs:
run: |
echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT

- name: Set sandbox URL
if: ${{ inputs.testType == 'sandbox' }}
shell: bash
env:
TARGET_ENVIRONMENT: ${{ inputs.targetEnvironment }}
run: |
if [[ "$TARGET_ENVIRONMENT" == pr* ]]; then
echo "SUPPLIER_API_URL_SANDBOX=https://internal-dev-sandbox.api.service.nhs.uk/nhs-notify-supplier-PR-${TARGET_ENVIRONMENT#pr}" >> "$GITHUB_ENV"
else
echo "SUPPLIER_API_URL_SANDBOX=https://internal-dev-sandbox.api.service.nhs.uk/nhs-notify-supplier" >> "$GITHUB_ENV"
fi

- name: Run test - ${{ inputs.testType }}
shell: bash
env:
Expand Down
9 changes: 2 additions & 7 deletions .github/actions/build-proxies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ inputs:
runId:
description: "GitHub Actions run ID to fetch the OAS artifact from"
required: true
buildSandbox:
description: "Whether to build the sandbox OAS spec"
required: false
default: false
targetComponent:
description: "Name of the Component to deploy"
required: true
Expand Down Expand Up @@ -67,7 +63,7 @@ runs:
set -euo pipefail

ENV="${{ inputs.apimEnv }}"
if [[ "$ENV" == "internal-dev" || "$ENV" == "internal-dev-pr" || "$ENV" == "internal-dev-sandbox" ]]; then
if [[ "$ENV" == "internal-dev" || "$ENV" == "internal-dev-pr" ]]; then
echo "TARGET_DOMAIN=suppliers.dev.nhsnotify.national.nhs.uk" >> $GITHUB_ENV
elif [[ "$ENV" == "int" || "$ENV" == "ref" ]]; then
echo "TARGET_DOMAIN=suppliers.nonprod.nhsnotify.national.nhs.uk" >> $GITHUB_ENV
Expand Down Expand Up @@ -112,8 +108,7 @@ runs:
--targetWorkflow "proxy-deploy.yaml" \
--targetEnvironment "${{ inputs.environment }}" \
--runId "${{ inputs.runId }}" \
--buildSandbox ${{ inputs.buildSandbox }} \
--apimEnvironment "${{ env.APIM_ENV }}" \
--boundedContext "notify-supplier" \
--targetDomain "$TARGET_DOMAIN" \
--version "${{ inputs.version }}"
--version "${{ inputs.version }}" \
109 changes: 68 additions & 41 deletions .github/actions/build-sandbox/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,88 @@ description: "Build Sandbox"
inputs:
version:
description: "Version number"
required: false
releaseVersion:
description: "Release, tag, branch, or commit ID to be used for deployment"
required: true

NODE_AUTH_TOKEN:
description: "Token for access to github package registry"
isRelease:
description: "True if releaseVersion is a release tag (if set, downloads from release assets instead of workflow artifacts)"
required: false
default: false
environment:
description: "Deployment environment"
required: true
apimEnv:
description: |
OAS build configuration name (e.g. internal-dev-sandbox, int, prod).
Must match the apimEnv used to build the OAS artifact this action downloads.
The '-pr' suffix is stripped before dispatching to proxygen, which only knows
real APIM environments (internal-dev, internal-dev-sandbox, int, ref, prod).
required: true
runId:
description: "GitHub Actions run ID to fetch the OAS artifact from"
required: true
buildSandbox:
description: "Whether to build the sandbox OAS spec"
required: false
default: false
targetComponent:
description: "Name of the Component to deploy"
required: true
default: 'api'

runs:
using: composite

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- name: Download Sandbox OAS Spec artifact from workflow
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
node-version: 22
registry-url: 'https://npm.pkg.github.com'

- name: Npm install
working-directory: .
env:
NODE_AUTH_TOKEN: ${{ inputs.NODE_AUTH_TOKEN }}
run: npm ci
shell: bash
name: api-oas-specification-internal-dev-sandbox${{ inputs.version != '' && format('-{0}', inputs.version) || '' }}
path: ./build-sandbox

- name: Install Proxygen client
- name: Setup Proxy Name and target
shell: bash
run: |
# Install proxygen cli
pip install pipx
pipx install proxygen-cli
set -euo pipefail

# Setup proxygen auth and settings
mkdir -p ${HOME}/.proxygen
echo -n $PROXYGEN_PRIVATE_KEY | base64 --decode > ${HOME}/.proxygen/key
envsubst < ./.github/proxygen-credentials-template.yaml > ${HOME}/.proxygen/credentials.yaml
envsubst < ./.github/proxygen-credentials-template.yaml | cat
envsubst < ./.github/proxygen-settings.yaml > ${HOME}/.proxygen/settings.yaml
envsubst < ./.github/proxygen-settings.yaml | cat
ENV="${{ inputs.apimEnv }}"
if [[ "$ENV" == "internal-dev-sandbox" ]]; then
echo "TARGET_DOMAIN=suppliers.dev.nhsnotify.national.nhs.uk" >> $GITHUB_ENV
elif [[ "$ENV" == "int" || "$ENV" == "ref" ]]; then
echo "TARGET_DOMAIN=suppliers.nonprod.nhsnotify.national.nhs.uk" >> $GITHUB_ENV
elif [[ "$ENV" == "prod" ]]; then
echo "TARGET_DOMAIN=suppliers.prod.nhsnotify.national.nhs.uk" >> $GITHUB_ENV
else
echo "[ERROR] Unsupported apimEnv '$ENV'."
exit 1
fi

- name: Setup Sandbox tag
- name: Set APIM_ENV
shell: bash
run: |
if [ -z $PR_NUMBER ]
then
echo "SANDBOX_TAG=latest" >> $GITHUB_ENV
else
echo "SANDBOX_TAG=pr$PR_NUMBER" >> $GITHUB_ENV
fi
echo "APIM_ENV=${{ inputs.apimEnv }}" >> "$GITHUB_ENV"

- name: Build and publish sandbox Docker image
- name: Upload Sandbox OAS Spec
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ env.APIM_ENV }}-build-output-sandbox
path: ./build-sandbox

- name: Trigger deploy sandbox
env:
APP_CLIENT_ID: ${{ env.APP_CLIENT_ID }}
APP_PEM_FILE: ${{ env.APP_PEM_FILE }}
shell: bash
working-directory: ./sandbox
run: |
proxygen docker get-login | bash
docker build -t nhs-notify-supplier:$SANDBOX_TAG .
DOCKER_REGISTRY=$(proxygen docker registry | tail -1)
IMAGE_ID=$(docker images -q nhs-notify-supplier:$SANDBOX_TAG)
docker tag $IMAGE_ID $DOCKER_REGISTRY/nhs-notify-supplier:$SANDBOX_TAG
docker push $DOCKER_REGISTRY/nhs-notify-supplier:$SANDBOX_TAG
.github/scripts/dispatch_internal_repo_workflow.sh \
--infraRepoName "nhs-notify-supplier-api" \
--releaseVersion "${{ inputs.releaseVersion }}" \
--targetComponent "${{ inputs.targetComponent }}" \
--targetWorkflow "proxy-sandbox-deploy.yaml" \
--targetEnvironment "${{ inputs.environment }}" \
--runId "${{ inputs.runId }}" \
--apimEnvironment "${{ env.APIM_ENV }}" \
--boundedContext "notify-supplier" \
--targetDomain "$TARGET_DOMAIN" \
--version "${{ inputs.version }}" \
3 changes: 2 additions & 1 deletion .github/actions/test-types.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[
"component",
"e2e"
"e2e",
"sandbox"
]
15 changes: 5 additions & 10 deletions .github/workflows/stage-2-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
check-generated-dependencies:
name: "Check generated dependencies"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -65,7 +65,6 @@ jobs:
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate dependencies"
run: |
Expand All @@ -74,7 +73,7 @@ jobs:
test-unit:
name: "Unit tests"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
Expand All @@ -96,7 +95,6 @@ jobs:
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate dependencies"
run: |
Expand All @@ -119,7 +117,7 @@ jobs:
test-pact:
name: "Pact tests"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
Expand All @@ -139,7 +137,6 @@ jobs:
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate dependencies"
run: npm run generate-dependencies --workspaces --if-present
Expand All @@ -150,7 +147,7 @@ jobs:
test-lint:
name: "Linting"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
Expand All @@ -172,7 +169,6 @@ jobs:
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate dependencies"
run: |
Expand All @@ -183,7 +179,7 @@ jobs:
test-typecheck:
name: "Typecheck"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 10
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
Expand All @@ -205,7 +201,6 @@ jobs:
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate dependencies"
run: |
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/stage-3-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ jobs:
artefact-oas-spec:
name: "OAS spec ready"
runs-on: ubuntu-latest
needs: [artefact-oas-spec-pr, artefact-oas-spec-main]
needs: [artefact-oas-spec-pr, artefact-oas-spec-main, artefact-oas-spec-sandbox]
if: always() && !failure()
steps:
- run: echo "OAS spec build complete"
Expand Down Expand Up @@ -237,5 +237,12 @@ jobs:
environment: ${{ needs.create-dynamic-environment.outputs.environment_name }}
apimEnv: "${{ inputs.pr_number == '' && 'internal-dev' || 'internal-dev-pr' }}"
runId: "${{ github.run_id }}"
buildSandbox: true
releaseVersion: ${{ github.head_ref || github.ref_name }}
- name: "Build sandbox"
uses: ./.github/actions/build-sandbox
with:
version: "${{ inputs.version }}"
environment: ${{ needs.create-dynamic-environment.outputs.environment_name }}
apimEnv: "internal-dev-sandbox"
runId: "${{ github.run_id }}"
releaseVersion: ${{ github.head_ref || github.ref_name }}
2 changes: 1 addition & 1 deletion .github/workflows/stage-4-acceptance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ jobs:
--targetEnvironment "$ENVIRONMENT" \
--targetAccountGroup "nhs-notify-supplier-api-dev" \
--targetComponent "api" \
--extraSecretNames '["/dev/e2e/keys/apim/main","/dev/e2e/keys/apim/pr","/dev/e2e/keys/apim/pr/secondary","/dev/e2e/keys/apim/status","/dev/e2e/keys/private"]'
--extraSecretNames '["/dev/e2e/keys/apim/main","/dev/e2e/keys/apim/pr","/dev/e2e/keys/apim/pr/secondary","/dev/e2e/keys/apim/status","/dev/e2e/keys/private"]' \
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.22.0
7 changes: 6 additions & 1 deletion sandbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"eslint": "^9.27.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.17.2",
"mocha": "^11.8.0"
},
"overrides": {
"eslint-config-airbnb-base": {
"eslint": "^9.27.0"
}
},
"eslintConfig": {
"env": {
"node": true
Expand Down
13 changes: 5 additions & 8 deletions specification/api/components/schemas/apiGatewayError.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
type: object
description: API gateway error response
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: "Bad Gateway"
properties:
message:
type: string
example: Bad Gateway
7 changes: 6 additions & 1 deletion tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ Test suites that validate the supplier API beyond individual package unit tests.
2. In the root level create an `.env` file and setup the `GITHUB_TOKEN` and `TARGET_ENVIRONMENT` variables (use `.env.template` as a guide)
3. Source the env file by running `set -a` -> `source .env` -> `set +a`
4. Login to your AWS account by running `aws sso login` in the terminal
- **Sandbox tests** require a sandbox server.
- **Sandbox tests**: We need to start the sandbox server from the `/sandbox` folder in the root directory (read /sandbox/README.md for more information).
- Run locally:
1. from project's root directory `cd sandbox && npm install && npm start` to start the sandbox server
2. from project's root directory `make test-sandbox` or `cd tests && npm install && npm run test:sandbox` to run the tests
- Run in Pipeline:
1. You need to deploy the proxies in your Pull Request with the label `deploy-proxy`. This should then build the sandbox server, deploy the artifact and deploy the sandbox proxy via proxygen (you might need to re-run the acceptance tests stage in the pipeline, as the server might take some time to deploy and be unreachable from the tests).
- **Performance and E2E tests** require AWS credentials, deployed infrastructure, and seeded test data. See `scripts/test-data/` for test data generation and `tests/e2e-tests/README.md` for environment-specific setup.
1. Deploy a dynamic environment (can be achieved by creating a Pull Request). Take a note of the environment e.g. pr1234.
2. Build proxies in the dynamic environment by setting the label `deploy_proxy` (ask a member of the team if you need help)
Expand Down
3 changes: 2 additions & 1 deletion tests/constants/api-constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const SUPPLIER_LETTERS = "letters";
const DEFAULT_SUPPLIER_API_URL_SANDBOX = "http://127.0.0.1:9000";
export const SUPPLIER_API_URL_SANDBOX =
"https://internal-dev-sandbox.api.service.nhs.uk/nhs-notify-supplier";
process.env.SUPPLIER_API_URL_SANDBOX ?? DEFAULT_SUPPLIER_API_URL_SANDBOX;
export const AWS_REGION = "eu-west-2";
export const envName = process.env.TARGET_ENVIRONMENT ?? "main";
export const API_NAME = `nhs-${envName}-supapi`;
Expand Down
8 changes: 8 additions & 0 deletions tests/sandbox/testCases/get-letter-status-test-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type GetLetterData = {
attributes: {
specificationId: string;
groupId: string;
sha256Hash: string;
status: string;
};
};
Expand All @@ -39,6 +40,7 @@ type RejectedLetterData = {
attributes: {
specificationId: string;
groupId: string;
sha256Hash: string;
status: string;
reasonCode: string;
reasonText: string;
Expand Down Expand Up @@ -74,6 +76,8 @@ export const apiSandboxGetLetterStatusTestData: ApiSandboxGetLetterStatusTestCas
attributes: {
specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg",
groupId: "c5d93f917f5546d08beccf770a915d96",
sha256Hash:
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c8f2f1d2d1e4f6e8f7e6e8f7e6",
status: "ACCEPTED",
},
},
Expand All @@ -91,6 +95,8 @@ export const apiSandboxGetLetterStatusTestData: ApiSandboxGetLetterStatusTestCas
attributes: {
specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg",
groupId: "c5d93f917f5546d08beccf770a915d96",
sha256Hash:
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c8f2f1d2d1e4f6e8f7e6e8f7e6",
status: "REJECTED",
reasonCode: "R01",
reasonText: "failed validation",
Expand All @@ -110,6 +116,8 @@ export const apiSandboxGetLetterStatusTestData: ApiSandboxGetLetterStatusTestCas
attributes: {
specificationId: "2WL5eYSWGzCHlGmzNxuqVusPxDg",
groupId: "c5d93f917f5546d08beccf770a915d96",
sha256Hash:
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c8f2f1d2d1e4f6e8f7e6e8f7e6",
status: "CANCELLED",
reasonCode: "R01",
},
Expand Down
Loading
Loading