Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 11 additions & 10 deletions .github/actions/init-mise/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,22 @@ runs:
cache: true
install: true

- name: Cache node_modules
- name: Get pnpm store directory
id: pnpm-store
shell: bash
run: echo "path=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Cache pnpm store
uses: actions/cache@v5
with:
path: |
node_modules
ui/node_modules
lambdas/node_modules
tests/node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.pnpm-store.outputs.path }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cache key hashes **/pnpm-lock.yaml, but the repository does not currently contain any pnpm-lock.yaml files, so the key will be effectively constant and the cache will be stale/ineffective.

Suggested fix: add the pnpm lockfile(s) as part of the migration, or key the cache off the existing package-lock.json files until pnpm lockfiles exist.

Suggested change
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

Copilot uses AI. Check for mistakes.
restore-keys: |
node-modules-${{ runner.os }}-
pnpm-store-${{ runner.os }}-

- name: Install npm dependencies
- name: Install pnpm dependencies
shell: bash
run: |
echo "::group::Install npm dependencies"
echo "::group::Install pnpm dependencies"
mise run install-npm
echo "::endgroup::"
4 changes: 2 additions & 2 deletions .github/actions/run-npm-tests/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: "Run NPM Tests"
description: "Run Jest tests with coverage reporting"
inputs:
working-directory:
description: "Directory containing the npm project (e.g., ui, lambdas)"
description: "Directory containing the project (e.g., ui, lambdas)"
required: true
nodejs-version:
description: "Node.js version to use"
Expand All @@ -27,7 +27,7 @@ runs:
steps:
- name: "Run test suite"
shell: bash
run: mise exec -- npm --prefix ${{ inputs.working-directory }} run test -- --ci
run: mise exec -- pnpm -C ${{ inputs.working-directory }} run test -- --ci
env:
FORCE_COLOR: true

Expand Down
28 changes: 14 additions & 14 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<!-- vale Vale.Terms = NO -->

`hometest-service` is an NHS England service that allows patients to order self-test HIV kits at home. It is a TypeScript monorepo with four independent packages. Each has its own `package.json` and is installed separately via `npm --prefix` — this is **not** an npm workspaces setup.
`hometest-service` is an NHS England service that allows patients to order self-test HIV kits at home. It is a TypeScript monorepo with four independent packages. Each has its own `package.json` and is installed separately via `pnpm -C` — this is **not** a pnpm workspaces setup.

<!-- vale Vale.Terms = YES -->

Expand Down Expand Up @@ -109,37 +109,37 @@ local-environment/ Docker Compose + LocalStack + Terraform for local dev

```bash
# Install all workspace dependencies (also installs ui/, lambdas/, tests/ via postinstall)
npm ci
pnpm install

# Build and package lambdas (required before first start or after lambda changes)
npm run build:lambdas
npm run package:lambdas
pnpm run build:lambdas
pnpm run package:lambdas

# Start the full local environment (Docker + LocalStack + Terraform deploy + UI)
npm start
pnpm start

# Stop the local environment and destroy Terraform state
npm run stop
pnpm run stop

# Restart the local environment
npm run local:restart
pnpm run local:restart

# Start only the backend (Docker + DB migration)
npm run local:backend:start
pnpm run local:backend:start

# Start only the frontend (Docker UI container)
npm run local:frontend:start
pnpm run local:frontend:start

# Run all unit tests (ui + lambdas)
npm test
pnpm test

# Run Playwright tests (reads URLs from Terraform outputs)
npm run test:playwright
pnpm run test:playwright

# Individual service controls
npm run local:service:db:start # start Postgres only
npm run local:service:db:migrate # run DB migrations
npm run local:service:localstack:start # start LocalStack only
pnpm run local:service:db:start # start Postgres only
pnpm run local:service:db:migrate # run DB migrations
pnpm run local:service:localstack:start # start LocalStack only
```

## Review Philosophy
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/playwright-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ jobs:

- name: "Install Playwright browsers"
working-directory: tests
run: npx playwright install --with-deps
run: pnpm exec playwright install --with-deps

- name: "Start the application"
run: |
npm run start
pnpm run local:start

- name: "Show application status"
run: |
Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:
FILTER="${{ inputs.test_filter }}"

# Build the command
CMD="npx playwright test"
CMD="pnpm exec playwright test"

# Add browser project
if [ "$BROWSER" != "all" ]; then
Expand Down
21 changes: 18 additions & 3 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
[settings]
locked = true
lockfile = true
install_before = "7d"

[settings.python]
compile = false

# Disable to avoid calling Github API
[settings.aqua]
cosign = false

[tools]
# Custom registries are not included in mise-versions
# https://mise-versions.jdx.dev/
Expand All @@ -28,7 +36,7 @@ terraform-docs = "0.22.0"
awscli = "2.34.26"

# https://devguide.python.org/versions/
python = "3.14.3"
python = "3.14.2"

## Security scanning

Expand All @@ -54,10 +62,17 @@ vale = "3.14.1"
# https://nodejs.org/en/download/releases
node = "24.14.1"

# https://github.com/pnpm/pnpm/releases
"npm:pnpm" = "10.33.0"

[tasks.pre-commit]
description = "Run pre-commit checks on all files"
run = "pre-commit run --all-files --show-diff-on-failure --color=always"

[tasks.pre-commit-main]
description = "Run pre-commit checks on all files comparing to main"
run = "pre-commit run --from-ref origin/main --to-ref HEAD --show-diff-on-failure --color=always"

[tasks.install-npm]
description = "Install npm dependencies"
run = "npm ci"
description = "Install pnpm dependencies"
run = "pnpm install --frozen-lockfile"
15 changes: 8 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,47 +32,47 @@ repos:

- id: prettier-formatting
name: prettier-formatting
entry: npm run format:pre-commit --
entry: pnpm run format:pre-commit --
language: system

- id: eslint-ui
name: ESLint (UI)
entry: npm --prefix ui run lint -- --fix
entry: pnpm -C ui run lint --fix
language: system
files: ^ui/.*\.(ts|tsx|js|jsx)$
pass_filenames: false

- id: eslint-lambdas
name: ESLint (Lambdas)
entry: npm --prefix lambdas run lint -- --fix
entry: pnpm -C lambdas run lint --fix
language: system
files: ^lambdas/.*\.(ts|js)$
pass_filenames: false

- id: eslint-tests
name: ESLint (Tests)
entry: npm --prefix tests run lint -- --fix
entry: pnpm -C tests run lint --fix
language: system
files: ^tests/.*\.(ts|js)$
pass_filenames: false

- id: check-typescript-ui
name: TypeScript (UI)
entry: npm --prefix ui run check-typescript
entry: pnpm -C ui run check-typescript
language: system
files: ^ui/.*\.(ts|tsx|js|jsx)$
pass_filenames: false

- id: check-typescript-lambdas
name: TypeScript (Lambdas)
entry: npm --prefix lambdas run check-typescript
entry: pnpm -C lambdas run check-typescript
language: system
files: ^lambdas/.*\.(ts|js)$
pass_filenames: false

- id: check-typescript-tests
name: TypeScript (Tests)
entry: npm --prefix tests run check-typescript
entry: pnpm -C tests run check-typescript
language: system
files: ^tests/.*\.(ts|js)$
pass_filenames: false
Expand All @@ -86,6 +86,7 @@ repos:
entry: yamllint
language: python
types: [file, yaml]
exclude: pnpm-lock.yaml

# Markdown linting
- repo: https://github.com/igorshubovych/markdownlint-cli
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Dependency directories
node_modules/
package-lock.json
pnpm-lock.yaml
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.prettierignore no longer ignores package-lock.json, but package-lock.json files still exist under ui/, lambdas/, and tests/, so Prettier/pre-commit may start reformatting them and create noisy diffs; consider keeping package-lock.json ignored until those files are removed.

Suggested change
pnpm-lock.yaml
pnpm-lock.yaml
package-lock.json

Copilot uses AI. Check for mistakes.

# Environment & runtime files
.env
Expand Down
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ infrastructure-as-code.
4. Install dependencies for the root, lambdas, and tests, start the local development environment

```shell
npm install && npm --prefix ./lambdas install
npm run start
pnpm install
pnpm run start
```

### Prerequisites
Expand Down Expand Up @@ -83,7 +83,7 @@ mise run pre-commit # Run the pre-commit task defined in .mise.toml
To spin up the entire local environment (LocalStack, Postgres, and the Next.js Frontend):

```shell
npm start
pnpm start
```

This command:
Expand All @@ -95,49 +95,49 @@ This command:
To stop the environment:

```shell
npm run stop
pnpm run stop
```

### Common local workflows

After running `npm start`, use targeted commands instead of restarting everything:
After running `pnpm start`, use targeted commands instead of restarting everything:

- **Lambda code changes** (build/package/deploy lambdas to LocalStack):

```shell
npm run local:deploy
pnpm run local:deploy
```

- **Database schema or seed changes** (rerun DB migration container, including goose migrations):

```shell
npm run local:service:db:migrate
pnpm run local:service:db:migrate
```

- **Terraform infrastructure changes** (apply infra updates to LocalStack without restarting containers):

```shell
npm run local:terraform:apply
pnpm run local:terraform:apply
```

This expects the backend containers, including LocalStack, to already be running. If they are not, start them first:

```shell
npm run local:backend:start
pnpm run local:backend:start
```

To switch local integrations between WireMock and real upstreams, pass Terraform variables when applying - some examples below.

To only use WireMock everywhere (default mode - only needed to switch over):

```shell
TF_VAR_local_service_mode=wiremock npm run local:terraform:apply # this is the default mode, only needed to switch over
TF_VAR_local_service_mode=wiremock pnpm run local:terraform:apply # this is the default mode, only needed to switch over
```

To not use WireMock anywhere (real downstream APIs):

```shell
TF_VAR_local_service_mode=real npm run local:terraform:apply
TF_VAR_local_service_mode=real pnpm run local:terraform:apply
```

To use WireMock except for specific services, pass only the overrides you need:
Expand All @@ -147,56 +147,56 @@ After running `npm start`, use targeted commands instead of restarting everythin
TF_VAR_local_supplier_service_url_override=https://supplier.example.com \
TF_VAR_local_use_ui_auth_url_override=https://auth.sandpit.signin.nhs.uk \
TF_VAR_local_postcode_lookup_base_url_override=https://api.os.uk/search/places/v1 \
npm run local:terraform:apply # npm run local:frontend:restart - if overriding UI auth
pnpm run local:terraform:apply # pnpm run local:frontend:restart - if overriding UI auth
```

If you change UI-facing auth settings, restart the frontend so it picks up the updated `ui/.env.local` values:

```shell
npm run local:frontend:restart
pnpm run local:frontend:restart
```

- **Restart backend containers only** (Postgres, LocalStack, WireMock, db-migrate):

```shell
npm run local:compose -- stop postgres-db localstack wiremock
npm run local:backend:start
pnpm run local:compose -- stop postgres-db localstack wiremock
pnpm run local:backend:start
```

- **Restart frontend only**:

```shell
npm run local:frontend:restart
pnpm run local:frontend:restart
```

- **Start/stop backend only**:

```shell
npm run local:backend:start
npm run local:compose -- stop postgres-db localstack wiremock
pnpm run local:backend:start
pnpm run local:compose -- stop postgres-db localstack wiremock
```

- **Start/stop frontend only**:

```shell
npm run local:frontend:start
npm run local:compose -- stop ui
pnpm run local:frontend:start
pnpm run local:compose -- stop ui
```

- **Start/stop specified lambda**

```shell
LAMBDA={lambda_name} npm run local:service:lambda:enable
LAMBDA={lambda_name} npm run local:service:lambda:disable
LAMBDA={lambda_name} pnpm run local:service:lambda:enable
LAMBDA={lambda_name} pnpm run local:service:lambda:disable
```

### Frontend

The frontend is a Next.js application located in the `/ui` directory.

1. cd to `/ui` directory.
2. Run `npm install`.
3. Run `npm run dev`.
2. Run `pnpm install`.
3. Run `pnpm run dev`.

- When creating a new page, use the PageLayout component found in `/ui/src/components`.
- To create a new route, create a directory with the name of your route in `/ui/src/app`, and add a `page.tsx` file within.
Expand Down
Loading
Loading