Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cc6d5c3
[GPCAPIM-275]: Remove duplicate lines.
davidhamill1-nhs Feb 5, 2026
4ebe273
[GPCAPIM-275]: Import modules consistently.
davidhamill1-nhs Feb 5, 2026
742f2fd
[GPCAPIM-275]: Enable other test modules to use a valid Bundle.
davidhamill1-nhs Feb 5, 2026
41437ac
[GPCAPIM-275]: Reduce mocking complexity. Move common required header…
davidhamill1-nhs Feb 5, 2026
dd8c318
[GPCAPIM-275]: Resolve spurious Sonar issue
davidhamill1-nhs Feb 5, 2026
4f1534d
[GPCAPIM-275]: Use single assertion in unit tests
davidhamill1-nhs Feb 5, 2026
3580a2b
[GPCAPIM-275]: Content-type header is a required header.
davidhamill1-nhs Feb 5, 2026
22adc40
[GPCAPIM-275]: Use static datetimes for unit tests.
davidhamill1-nhs Feb 5, 2026
4b9dbec
[GPCAPIM-275]: Move towards using a common error class
davidhamill1-nhs Feb 9, 2026
80a90ed
[GPCAPIM-275]: Move towards using a common error class.
davidhamill1-nhs Feb 9, 2026
72af28c
[GPCAPIM-275]: Rework unit tests to only assert once in a test method
davidhamill1-nhs Feb 9, 2026
a41f241
[GPCAPIM-275]: Have a "catch all" error within the common error class
davidhamill1-nhs Feb 9, 2026
701038b
[GPCAPIM-275]: Run request handling all in one try-except as exceptio…
davidhamill1-nhs Feb 9, 2026
5e55b85
[GPCAPIM-275]: Run request handling all in one try-except as exceptio…
davidhamill1-nhs Feb 9, 2026
5d924a8
[GPCAPIM-275]: Enable additional details to be passed to errors.
davidhamill1-nhs Feb 9, 2026
e5fecaa
[GPCAPIM-275]: We do not send the ODS code to PDS as an End User Org
davidhamill1-nhs Feb 9, 2026
8354daf
[GPCAPIM-275]: Given we are accessing PDS as an application, we do no…
davidhamill1-nhs Feb 9, 2026
36d9812
[GPCAPIM-275]: PDS sandbox can receive auth header.
davidhamill1-nhs Feb 9, 2026
ddd5b94
[GPCAPIM-275]: Move towards common error class
davidhamill1-nhs Feb 10, 2026
750e4d4
[GPCAPIM-275]: Use http client's status code definitions for clarity
davidhamill1-nhs Feb 10, 2026
7aa9fa2
[GPCAPIM-275]: Move towards common error class
davidhamill1-nhs Feb 10, 2026
5af0f0a
[GPCAPIM-275]: Remove unnecessary imports.
davidhamill1-nhs Feb 10, 2026
366f6d4
[GPCAPIM-275]: Move modules to their own directory
davidhamill1-nhs Feb 10, 2026
4169586
[GPCAPIM-275]: Add example Patient resource - taken from PDS FHIR's s…
davidhamill1-nhs Feb 10, 2026
be94937
[GPCAPIM-275]: Move modules to their own directory
davidhamill1-nhs Feb 10, 2026
0c3c8cd
[GPCAPIM-275]: Write a test to make number go up
davidhamill1-nhs Feb 10, 2026
30fdbaa
[GPCAPIM-275]: Behaviour being testted already covered by integration…
davidhamill1-nhs Feb 10, 2026
6dc0873
[GPCAPIM-275]: Module was moved, so test file has been moved. This is…
davidhamill1-nhs Feb 16, 2026
ebcb6e2
[GPCAPIM-275]: Use common FHIR classes
davidhamill1-nhs Feb 16, 2026
39096cb
[GPCAPIM-275]: Update terraform.
davidhamill1-nhs Feb 16, 2026
1879d55
[GPCAPIM-275]: Add debug flask app task
davidhamill1-nhs Feb 16, 2026
553e8a6
[GPCAPIM-275]: Move Conteroller.run() tests to integration test suite.
davidhamill1-nhs Feb 16, 2026
fef17b3
[GPCAPIM-275]: Reduce reliance on mocking in unit tests; move STUB PD…
davidhamill1-nhs Feb 17, 2026
847a65a
[GPCAPIM-275]: Add STUB PROVIDER to env vars
davidhamill1-nhs Feb 18, 2026
5a1c445
[GPCAPIM-275]: Tidying up
davidhamill1-nhs Feb 18, 2026
f4b026b
[GPCAPIM-275]: Add spell checker extension - flagging errors only; no…
davidhamill1-nhs Feb 18, 2026
33f0e81
[GPCAPIM-275]: None will not be returned from the Provider client.
davidhamill1-nhs Feb 18, 2026
332c64c
[GPCAPIM-275]: Reduce doc strings.
davidhamill1-nhs Feb 18, 2026
8af8423
[GPCAPIM-275]: Method does not return None and so will never raise th…
davidhamill1-nhs Feb 18, 2026
a2117e3
[GPCAPIM-275]: Make number go up - integration tests do cover this bu…
davidhamill1-nhs Feb 18, 2026
d85c426
[GPCAPIM-275]: Merge in changes from GPCAPIM-258
davidhamill1-nhs Feb 19, 2026
6ed656f
[GPCAPIM-275]: Pass stub env vars to 'integration' test.
davidhamill1-nhs Feb 19, 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
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"ms-python.vscode-python-envs",
"ms-python.mypy-type-checker",
"sonarsource.sonarlint-vscode",
"alexkrechik.cucumberautocomplete"
"alexkrechik.cucumberautocomplete",
"streetsidesoftware.code-spell-checker"
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're already using vale to provide some spell checking within the repository. Does this extension integrate with this?

],
"extensions.ignoreRecommendations": true,
"settings": {
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/stage-2-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: "Test stage"
env:
BASE_URL: "http://localhost:5000"
HOST: "localhost"
STUB_SDS: "true"
STUB_PDS: "true"
STUB_PROVIDER: "true"

on:
workflow_call:
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is for you! Please, updated to the versions agreed by your team.

terraform 1.14.0
terraform 1.14.5
pre-commit 3.6.0
gitleaks 8.18.4

Expand All @@ -15,7 +15,7 @@ gitleaks 8.18.4
# docker/ghcr.io/make-ops-tools/gocloc latest@sha256:6888e62e9ae693c4ebcfed9f1d86c70fd083868acb8815fe44b561b9a73b5032 # SEE: https://github.com/make-ops-tools/gocloc/pkgs/container/gocloc
# docker/ghcr.io/nhs-england-tools/github-runner-image 20230909-321fd1e-rt@sha256:ce4fd6035dc450a50d3cbafb4986d60e77cb49a71ab60a053bb1b9518139a646 # SEE: https://github.com/nhs-england-tools/github-runner-image/pkgs/container/github-runner-image
# docker/hadolint/hadolint 2.12.0-alpine@sha256:7dba9a9f1a0350f6d021fb2f6f88900998a4fb0aaf8e4330aa8c38544f04db42 # SEE: https://hub.docker.com/r/hadolint/hadolint/tags
# docker/hashicorp/terraform 1.12.2@sha256:b3d13c9037d2bd858fe10060999aa7ca56d30daafe067d7715b29b3d4f5b162f # SEE: https://hub.docker.com/r/hashicorp/terraform/tags
# docker/hashicorp/terraform 1.14.5@sha256:96d2bc440714bf2b2f2998ac730fd4612f30746df43fca6f0892b2e2035b11bc # SEE: https://hub.docker.com/r/hashicorp/terraform/tags
# docker/koalaman/shellcheck latest@sha256:e40388688bae0fcffdddb7e4dea49b900c18933b452add0930654b2dea3e7d5c # SEE: https://hub.docker.com/r/koalaman/shellcheck/tags
# docker/mstruebing/editorconfig-checker 2.7.1@sha256:dd3ca9ea50ef4518efe9be018d669ef9cf937f6bb5cfe2ef84ff2a620b5ddc24 # SEE: https://hub.docker.com/r/mstruebing/editorconfig-checker/tags
# docker/sonarsource/sonar-scanner-cli 10.0@sha256:0bc49076468d2955948867620b2d98d67f0d59c0fd4a5ef1f0afc55cf86f2079 # SEE: https://hub.docker.com/r/sonarsource/sonar-scanner-cli/tags
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

{
"name": "Run Gateway API",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/gateway-api/src/gateway_api/app.py",
"envFile": "${workspaceFolder}/.env",
"jinja": true,
"console": "integratedTerminal"
}
]
}
Comment on lines 1 to 18
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it make sense to add this? As I understand it we're about to be asked to drop Flask.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is quite a generic configuration (the name is arbitrary - but will change to make it a more specific to our project/this command); a move away from Flask will not affect this.

14 changes: 13 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,17 @@
"projectKey": "NHSDigital_clinical-data-gateway-api"
},
// Disabling automatic port forwarding as the devcontainer should already have access to any required ports.
"remote.autoForwardPorts": false
"remote.autoForwardPorts": false,

// Code spell checker configuration
"cSpell.language": "en-GB",
"cSpell.words": [
"asid",
"fhir",
"getstructuredrecord",
"gpconnect",
"usefixtures",
],
"python-envs.defaultEnvManager": "ms-python.python:system",
"python-envs.pythonProjects": [],
}
25 changes: 25 additions & 0 deletions gateway-api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,28 @@ paths:
diagnostics:
type: string
example: "Internal server error"

'502':
description: Received an error response from a downstream server
content:
application/fhir+json:
schema:
type: object
properties:
resourceType:
type: string
example: "OperationOutcome"
issue:
type: array
items:
type: object
properties:
severity:
type: string
example: "error"
code:
type: string
example: "exception"
diagnostics:
type: string
example: "PDS FHIR API request failed: Bad Gateway"
127 changes: 96 additions & 31 deletions gateway-api/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gateway-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dev = [
"schemathesis>=4.4.1",
"types-requests (>=2.32.4.20250913,<3.0.0.0)",
"types-pyyaml (>=6.0.12.20250915,<7.0.0.0)",
"pytest-mock (>=3.15.1,<4.0.0)",
]

[tool.mypy]
Expand Down
2 changes: 2 additions & 0 deletions gateway-api/src/fhir/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""FHIR data types and resources."""

from fhir.bundle import Bundle, BundleEntry
from fhir.general_practitioner import GeneralPractitioner
from fhir.human_name import HumanName
from fhir.identifier import Identifier
from fhir.operation_outcome import OperationOutcome, OperationOutcomeIssue
Expand All @@ -17,4 +18,5 @@
"Parameter",
"Parameters",
"Patient",
"GeneralPractitioner",
]
21 changes: 21 additions & 0 deletions gateway-api/src/fhir/general_practitioner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""FHIR GeneralPractitioner type."""

from typing import TypedDict

from fhir.period import Period


class GeneralPractitionerIdentifier(TypedDict):
"""Identifier for GeneralPractitioner with optional period."""

system: str
value: str
period: Period
Copy link
Contributor

Choose a reason for hiding this comment

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

Should Period be NotRequired if it's optional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AFAIK, period is not optional; however, period.end is for generalPractitioner (and most fields).



class GeneralPractitioner(TypedDict):
"""FHIR GeneralPractitioner reference."""

id: str
type: str
identifier: GeneralPractitionerIdentifier
3 changes: 3 additions & 0 deletions gateway-api/src/fhir/human_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

from typing import TypedDict

from fhir.period import Period


class HumanName(TypedDict):
use: str
family: str
given: list[str]
period: Period
4 changes: 3 additions & 1 deletion gateway-api/src/fhir/patient.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""FHIR Patient resource."""

from typing import TypedDict
from typing import NotRequired, TypedDict

from fhir.general_practitioner import GeneralPractitioner
from fhir.human_name import HumanName
from fhir.identifier import Identifier

Expand All @@ -13,3 +14,4 @@ class Patient(TypedDict):
name: list[HumanName]
gender: str
birthDate: str
generalPractitioner: NotRequired[list[GeneralPractitioner]]
Loading