https://github.com/nhsdigital/vaccinations-app
VitA Team: Vaccinations in the NHS app
https://github.com/nhsdigital/vaccinations-app
Last synced: 6 days ago
JSON representation
VitA Team: Vaccinations in the NHS app
- Host: GitHub
- URL: https://github.com/nhsdigital/vaccinations-app
- Owner: NHSDigital
- License: mit
- Created: 2025-02-03T15:00:39.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2026-02-16T17:18:06.000Z (24 days ago)
- Last Synced: 2026-02-16T17:40:02.563Z (24 days ago)
- Language: TypeScript
- Size: 7.41 MB
- Stars: 5
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Codeowners: .github/CODEOWNERS
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# Vaccinations in the app
[](https://github.com/NHSDigital/vaccinations-app/actions/workflows/cicd-1-pull-request.yaml)
[](https://sonarcloud.io/summary/new_code?id=NHSDigital_vaccinations-app)
## Project Overview
Within the NHS app, vaccinations app will increase the rate of booking by:
- Informing individuals with personalised information about which vaccinations they still need to have and how to book
- Providing information on eligibility and how to book where eligibility is not available
- Providing personalised vaccination availability and booking journeys, based on local availability.
We will increase appointment attendance and reduce the number of 'did not attend' and therefore increase appointment availability by:
- Providing people with details of all their upcoming vaccination appointments, with simple, easy options to cancel or change.
## Developer Setup
### GitHub
- As per NHS guidelines, make your GitHub email private by going [here](https://github.com/settings/emails). There is a checkbox named "Keep my email addresses private". Note down your private email from this setting.
- Follow these [instructions](https://nhsd-confluence.digital.nhs.uk/display/Vacc/Developer+setup%3A+Github).
- Remember to use your private email, noted above, in GitHub config 'user.email'.
- When on the step to create personal access tokens, remember to also tick 'workflow'. This will allow developers to update workflows
- Get your NHS GitHub username added to the VitA team to gain access to the repository
### Prerequisites
Tools to install:
From NHS repository template:
- **Make and GNU tooling** - The version of GNU make available by default on macOS is earlier than 3.82. You will need to upgrade it or certain make tasks will fail.
On macOS, you will need Homebrew installed, then to install make, like so:
```shell
brew install make gnu-sed gawk coreutils binutils jmeter
```
Find out which homebrew path you have by using this command:
```shell
brew --prefix make
```
Based on the beginning of the path returned, select which HOMEBREW_PATH to export.
- Override default OSX tools with their GNU equivalents
- On M1 Macs and up:
```shell
echo 'export HOMEBREW_PATH="/opt/homebrew"' >> ~/.zshrc
```
- For Intel Macs:
```shell
echo 'export HOMEBREW_PATH="/usr/local"' >> ~/.zshrc
```
- Then:
```shell
echo 'export PATH="$HOMEBREW_PATH/opt/make/libexec/gnubin:$PATH"' >> ~/.zshrc
echo 'export PATH="$HOMEBREW_PATH/opt/gnu-sed/libexec/gnubin:$PATH"' >> ~/.zshrc
echo 'export PATH="$HOMEBREW_PATH/opt/gawk/libexec/gnubin:$PATH"' >> ~/.zshrc
echo 'export PATH="$HOMEBREW_PATH/opt/coreutils/libexec/gnubin:$PATH"' >> ~/.zshrc
echo 'export PATH="$HOMEBREW_PATH/opt/binutils/bin:$PATH"' >> ~/.zshrc
echo 'export LDFLAGS="-L$HOMEBREW_PATH/opt/binutils/lib"' >> ~/.zshrc
echo 'export CPPFLAGS="-I$HOMEBREW_PATH/opt/binutils/include"' >> ~/.zshrc
source ~/.zshrc
```
- **asdf** - version manager with support for multiple languages
- Install asdf and add to path
```shell
brew install asdf
echo 'export PATH="${HOME}/.asdf/shims:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
- Install nodejs plugin for asdf (and required dependencies)
```shell
brew install gpg gawk
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
```
- **Colima** - or any equivalent Docker container runtime, e.g. [Rancher Desktop](https://rancherdesktop.io/), etc.
- **Act** - tool to run GitHub actions locally. Usage guide is available [here](https://nektosact.com/usage/index.html)
```shell
brew install act
```
- symlink `/var/run/docker.sock` file to your chosen docker container tool's `docker.sock` file location. For e.g. `sudo ln -s /Users//.colima/default/docker.sock /var/run/docker.sock`
- after successful installation, when you run act for the first time, it will ask for the size of docker container. Choose 'medium'.
- to list all available jobs and workflows
```shell
act --list
```
- to run a specific job ID
```shell
act -j 'check-english-usage' --defaultbranch main
```
- to run all jobs in a workflow file
```shell
act -W .github/workflows/cicd-1-pull-request.yaml --defaultbranch main
```
- **Playwright** - Install browser drivers for running UI-driven acceptance tests
```shell
npx playwright install
```
- **AWS CLI** - Install AWS CLI for local deployments.
- For the following commands, use the settings from your [AWS access portal](https://d-9c67018f89.awsapps.com/start/#/?tab=accounts) "Access keys". Give the name 'vita-dev' to your new profile.
```shell
brew install awscli
aws configure sso
```
- Add the profile 'vita-dev' to your shell to avoid having to provide it repeatedly.
```shell
echo 'export AWS_PROFILE=vita-dev' >> ~/.zshrc
source ~/.zshrc
```
### Local Configuration
1. Copy .env.template file to .env.local. Add the necessary values which will be picked up by Next.js
2. Install toolchain dependencies and load .tool-versions into asdf
```shell
make config
```
3. Install and setup pre-commit hooks for this project
```shell
make githooks-config
make githooks-run
```
4. Set environment variable to disable telemetry collection in next.js: add the following to .zshrc
```shell
export NEXT_TELEMETRY_DISABLED=1
```
5. Install dependencies from package.json
```shell
npm install
```
## Usage
### Build
```shell
npm run build
```
### Run service locally
Serves web content from src folder, so make changes and refresh the browser to see changes immediately.
```shell
npm run dev
```
#### Simulating NHS Login SSO flow
Our project integrates with NHS Login. To simulate the SSO flow, clone this [repo](https://github.com/NHSDigital/vita-login-sso-client-express)
and follow the README to set it up.
RSA Private keys and Client IDs are required for this flow. Steps to enable it:
- Visit AWS Secrets Manager to get the private keys and Client IDs
- Values prefixed with 'vita/sso' are used in the fake client, and those prefixed with 'vita/app' are used in this project
- Set the Client ID values in the env files of this project and the Fake Client project respectively
- Store the private key values in pem files in your systems, preferably somewhere outside this repository (e.g. `vita_private_key.pem`, `vita_private_key_sso.pem`)
- Before running the application, export the VitA application private key as an environment variable:
```shell
export NHS_LOGIN_PRIVATE_KEY=`cat /vita_private_key.pem`
```
- Follow the steps in fake client repo README.md to set up the SSO private key there.
SSO flow is initiated from the fake client. Directly accessing the application will redirect you to an error page.
#### Enabling APIM Authentication
To generate a key pair you can follow this [guide](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation#step-3-generate-a-key-pair)
Then export the private key as an environment variable:
```shell
export APIM_PRIVATE_KEY=`cat /apim_private_key.pem`
```
#### Mocking API Responses with Wiremock
Our project utilizes Wiremock to provide mock responses for Eligibility API endpoints. To configure these responses:
- Place request-response mapping files (JSON) within the `wiremock/mappings` directory.
- Store the corresponding JSON response bodies in the `wiremock/__files` directory.
To run the Wiremock server locally:
```shell
npm run elid
```
### Run unit tests
```shell
npm run test
```
### Run UI driven tests
- make sure to build and run the Next.js app
```shell
npm run app
```
- run tests in headless mode
```shell
npm run e2e
```
- or with interactive developer UI
```shell
npm run e2e:ui
```
### Run pre-commit hooks manually
```shell
make githooks-run
```
(Note that this has also been configured as a pre-commit hook that will run automatically before each commit)
### Deploy your local changes to AWS dev environment
A detailed description of our infrastructure is outlined [here](infrastructure/README.md).
We use Terraform workspaces to distinguish each developer.
So make sure you use your own unique combination of initials, to set the workspace.
Use maximum 4 chars, otherwise you might not be able to deploy due to max limits on resource names.
Avoid 'gh' as it is reserved for GitHub.
- Make sure to build a zip artifact for the Vita app and the content-cache-hydrator lambda first using
```shell
npm run local-build-package
```
or to build the cache hydrator only
```shell
npm run local-build-package:hydrator
```
(reference: commands included in the local package tasks)
```shell
npm run build:opennext
npm run build:lambda
zip -j -r lambda.zip dist/
```
- (optional) Log into AWS if session has expired - run the following command, ignore the browser window that automatically opens and copy the URL output in terminal into browser for HSCIC profile
```shell
aws sso login
```
- In the `home` directory
```shell
TF_ENV=dev make terraform-init # initialises the modules
```
- In the environment `infrastructure/environments/dev` directory
```shell
terraform workspace new
```
- In the `home` directory
```shell
TF_ENV=dev make terraform-plan # compares local vs. remote state, and shows the plan
TF_ENV=dev make terraform-apply # applies the plan, asks for approval
```
- Once the deployment is successful, do these post-deployment steps: -
- Update the environment: the variables are accessible in [Systems Manager / Parameter Store](https://eu-west-2.console.aws.amazon.com/systems-manager/parameters/?region=eu-west-2&tab=Table)
- The app is accessible via the CDN URL printed after the deployment as an output.
#### Assuming a restricted IAM role
We follow a strict least privilege policy for our IAM roles. The IAM role used by the GitHub Actions workflows for
deployment is restricted, and there are times when we need to modify the permissions policy for the role (e.g. when
working on infrastructure changes).
To prevent failed deployment pipelines due to insufficient permissions, a restricted IAM role can be assumed in the
personal workspace of the developer. This restricted role mimics the permissions of the role used by the GitHub Actions
workflows.
Steps to create and assume the restricted role:
- (optional) Log into AWS if session has expired - run the following command, ignore the browser window that automatically opens and copy the URL output in terminal into browser for HSCIC profile
```shell
aws sso login
```
- In the `home` directory
```shell
TF_ENV=dev/iam make terraform-init # initialises the iam modules
```
- In the environment `infrastructure/environments/dev/iam` directory
```shell
terraform workspace new # use the same name as the workspace used for the main app
```
- In the `home` directory
```shell
TF_ENV=dev/iam make terraform-plan # compares local vs. remote state, and shows the plan
TF_ENV=dev/iam make terraform-apply # applies the plan, asks for approval
```
- Once the deployment is successful, visit the AWS IAM console and find arn of the restricted role. The role name will be prefixed with the workspace name.
- The following script can be used to easily assume and unset the role. For easier use, add the following to your `.zshrc` file:
```shell
# Assume the restricted role; If it shows an error, rerun.
iamvita() {
local credentials=$(aws sts assume-role --role-arn "" --role-session-name "" --output json)
export AWS_ACCESS_KEY_ID=$(echo $credentials | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $credentials | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $credentials | jq -r '.Credentials.SessionToken')
echo "Role assumed successfully."
}
# Unset IAM Role; use default admin role
iamunset() {
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
echo "AWS environment variables cleared."
}
```
- (Optional) To test the role assumption, run the following command:
```shell
aws sts get-caller-identity # will display current assumed role
```
#### Destroying and Re-deploying resources in AWS
To destroy resources in AWS, run the command:
```shell
TF_ENV=dev make terraform-destroy # deprovisions infrastructure, asks for approval
```
Note: AWS has been configured to ensure that server function log group is not deleted when destroy is run. When re-deploying from local, this means that developers will need to go into AWS and manually delete the log group before re-provisioning.
#### Accessing application logs in AWS
Logs are kept in AWS CloudWatch in a Log Group for the server
In AWS Console:
- CloudWatch > Log Groups > `/aws/lambda/{workspace}-main-vita-{accountid}-server-function`
Use the Logs Insights UI to query logs:
- CloudWatch > Log Insights
- Select the log group in the dropdown
- Sample query:
```aws-log-insights-QL
fields @timestamp, traceId, level, module, msg, @message
| filter level = "INFO" or level = "ERROR"
| sort @timestamp desc
| limit 10000
```
### Enable full debug logs in Node.js and OpenNext
- To enable debug logging in OpenNext, add `OPEN_NEXT_DEBUG=true` to [package.json](/package.json) `build:opennext` command:
```json
{
"build:opennext": "OPEN_NEXT_DEBUG=true npx --yes @opennextjs/aws@latest build"
}
```
- To enable debug logging in Node.js at runtime, add `NODE_DEBUG=` to the [list](/infrastructure/environments/dev/locals.tf) of lambda environment variables:
```text
NODE_DEBUG=*
```
## Creating Releases
Our release strategy is based on Semantic Versioning and utilizes tagged commits. To create a new release, please follow the steps outlined below:
1. **Write a commit, push and Synchronize with Remote:** After merging your changes into the `main` branch, ensure your local repository is synchronized with the remote. Execute the following commands:
```bash
git commit -m 'your commit message'
git push origin main
git pull --rebase origin main
```
- IMPORTANT: Wait for the continuous integration/build pipeline to complete successfully.
2. **Determine Release Type:** Assess the nature of the changes included in this release to determine the appropriate semantic version increment:
- **Major Change (Breaking):** Increment the major version (e.g., `v1.0.0` to `v2.0.0`).
- **Minor Change (New Feature):** Increment the minor version (e.g., `v0.1.0` to `v0.2.0`).
- **Patch/Fix (Bug Fixes, Minor Updates):** Increment the patch version (e.g., `v0.0.1` to `v0.0.2`).
3. **Identify the Previous Tag (Optional):** You can view existing tags to understand the current release version. Either visit the "Releases" or "Tags" section of the repository on GitHub, or run the following command locally:
```bash
git tag
```
4. **Tag Your Commit:** Create a new tag on your local `main` branch using the `git tag` command, following the `vx.y.z` format (replace `x`, `y`, and `z` with the incremented version numbers):
```bash
git tag vX.Y.Z
```
For example, if it's a minor release, you might use:
```bash
git tag v0.2.0
```
5. **Push the Tag to Remote:** Push the newly created tag to the `origin` remote repository. This action will automatically trigger the publish/release workflow:
```bash
git push origin tag vX.Y.Z
```
6. **Verify Release and Artifact:** Upon successful execution of the publish/release workflow, you should observe:
- A new tagged release in the "Releases" section of the GitHub repository.
- The corresponding build artifact within the `/tags` folder of the GitHub AWS S3 bucket.
**The branching and tagging strategy to fix broken deployed releases can be found [here](https://nhsd-confluence.digital.nhs.uk/spaces/Vacc/pages/989220238/Branching+and+release+strategy#Branchingandreleasestrategy-Fixingdeployedbrokenreleases).**
## Design
TODO
## Contacts
[Slack channel: #vaccs-in-the-app-devs](https://nhsdigitalcorporate.enterprise.slack.com/archives/C08BNCQH9FV)
## Licence
> The [LICENCE.md](./LICENCE.md) file will need to be updated with the correct year and owner
Unless stated otherwise, the codebase is released under the MIT License. This covers both the codebase and any sample code in the documentation.
Any HTML or Markdown documentation is [© Crown Copyright](https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/) and available under the terms of the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).