Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
487acb6
CCM-16644: Fix request_item_plan_read_status_smsnudge dependencies
gareth-allan May 1, 2026
95bef46
CCM-16644: Add Firehose Stream
gareth-allan Apr 29, 2026
f13109c
CCM-16644: Add event staging table
gareth-allan Apr 30, 2026
d349f59
CCM-16644: Add SNS topic
gareth-allan May 1, 2026
cd56cc4
CCM-16644: Added transformation lambda
gareth-allan May 7, 2026
abc82d9
CCM-16644: Added TF for transformation lambda
gareth-allan May 7, 2026
559d326
CCM-16644: Made the CI workflow validate Typescript code
gareth-allan May 7, 2026
c60cc7e
CCM-16644: Add pre.sh to build lambda as part of deployment
gareth-allan May 7, 2026
6eee550
CCM-16644: Build fixes
gareth-allan May 7, 2026
d34d2a5
CCM-16644: Update .gitleaksignore
gareth-allan May 7, 2026
5088b5f
CCM-16644: Move event_staging table to its own DB
gareth-allan May 8, 2026
7a07941
CCM-16644: Add housekeeping step function for event_staging DB
gareth-allan May 8, 2026
4964159
CCM-16644: Sonar fixes
gareth-allan May 11, 2026
6db4eba
CCM-16644: Move S3 bucket to use shared module
gareth-allan May 11, 2026
083ce6b
CCM-16644: Updated the README to cover event-driven reporting
gareth-allan May 11, 2026
05916db
CCM-16644: Use kms shared module
gareth-allan May 11, 2026
edda81c
CCM-16644: Copilot review fixes
gareth-allan May 12, 2026
a841665
CCM-16644: Further Copilot review fixes
gareth-allan May 12, 2026
9f615c2
CCM-16644: Only allow shared event bus to publish to SNS topic
gareth-allan May 12, 2026
cad64ca
Revert "CCM-16644: Only allow shared event bus to publish to SNS topic"
gareth-allan May 12, 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
53 changes: 39 additions & 14 deletions .github/workflows/stage-2-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,39 +40,60 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: "Use Node.js"
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: '.tool-versions'
- name: "Install dependencies"
run: npm ci
- name: "Run unit test suite"
run: |
make test-unit
Comment thread
gareth-allan marked this conversation as resolved.
- name: "Save the result of fast test suite"
run: |
echo "Nothing to save"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: unit-tests
path: "**/.reports/unit"
include-hidden-files: true
if: always()
- name: "Save the result of code coverage"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: code-coverage-report
path: ".reports/lcov.info"
Comment thread
gareth-allan marked this conversation as resolved.
if: always()
test-lint:
name: "Linting"
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: "Use Node.js"
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: '.tool-versions'
- name: "Install dependencies"
run: npm ci
- name: "Run linting"
run: |
make test-lint
- name: "Save the linting result"
run: |
echo "Nothing to save"
test-coverage:
name: "Test coverage"
needs: [test-unit]
test-typecheck:
name: "Typecheck"
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: "Run test coverage check"
run: |
make test-coverage
- name: "Save the coverage check result"
- name: "Use Node.js"
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version-file: '.tool-versions'
- name: "Install dependencies"
run: npm ci
- name: "Run typecheck"
run: |
echo "Nothing to save"
make test-typecheck
perform-static-analysis:
name: "Perform static analysis"
needs: [test-unit]
Expand All @@ -86,8 +107,12 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0 # Full history is needed to improving relevancy of reporting
- name: "Download coverage report for SONAR"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: code-coverage-report
- name: "Perform static analysis"
uses: NHSDigital/nhs-notify-shared-modules/.github/actions/perform-static-analysis@3.1.4
uses: NHSDigital/nhs-notify-shared-modules/.github/actions/perform-static-analysis@740afa9b7c15fc8c44681f958ea8608062e77a25 # v3.1.4
with:
sonar_organisation_key: "${{ vars.SONAR_ORGANISATION_KEY }}"
sonar_project_key: "${{ vars.SONAR_PROJECT_KEY }}"
Expand Down
6 changes: 6 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@
39565cc5ab1245e4e6a6368c19fd0aa9a187733a:infrastructure/terraform/components/reporting/variables.tf:ipv4:109
ca243cb73d3804a14f3eeefa8073c96802420c52:infrastructure/terraform/etc/env_eu-west-2_int.tfvars:generic-api-key:29
ca243cb73d3804a14f3eeefa8073c96802420c52:infrastructure/terraform/etc/env_eu-west-2_prod.tfvars:generic-api-key:43
e4f41f458ca66d94f1fcebdff9579e2ce81d1d5e:infrastructure/terraform/etc/env_eu-west-2_int.tfvars:generic-api-key:29
e4f41f458ca66d94f1fcebdff9579e2ce81d1d5e:infrastructure/terraform/etc/env_eu-west-2_prod.tfvars:generic-api-key:43
eb98e30495f24e1c27b438da069bad7d938d1c02:infrastructure/terraform/components/reporting/README.md:ipv4:16
eb98e30495f24e1c27b438da069bad7d938d1c02:infrastructure/terraform/components/reporting/variables.tf:ipv4:109
b476ac7da6815b396a0b7bf338f211aec32553bf:infrastructure/terraform/components/powerbi-gateway/README.md:ipv4:14
b476ac7da6815b396a0b7bf338f211aec32553bf:infrastructure/terraform/components/powerbi-gateway/variables.tf:ipv4:77
3 changes: 2 additions & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ act 0.2.64
vale 3.6.0
gitleaks 8.18.4
jq 1.6
nodejs 18.18.2
nodejs 22.22.2
pre-commit 3.6.0
ruby 3.2.0
terraform 1.10.1
terraform-docs 0.19.0
# trivy 0.69.3
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ include scripts/init.mk
# Example CI/CD targets are: dependencies, build, publish, deploy, clean, etc.

dependencies: # Install dependencies needed to build and test the project @Pipeline
# TODO: Implement installation of your project dependencies
npm ci

build: # Build the project artefact @Pipeline
(cd docs && make build)
npm run build:archive

publish: # Publish the project artefact @Pipeline
# TODO: Implement the artefact publishing step
Expand All @@ -21,10 +22,12 @@ deploy: # Deploy the project artefact to the target environment @Pipeline

clean:: # Clean-up project resources (main) @Operations
rm -f .version
# TODO: Implement project resources clean-up step
rm -rf .reports
npm run clean

config:: _install-dependencies version # Configure development environment (main) @Configuration
(cd docs && make install)
mkdir -p .reports

version:
rm -f .version
Expand Down
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ The reporting domain provides an isolated environment for staging data used for

This allows appropriate views of data to be safely exposed without sharing the full contents of the underlying transactional database.

This domain does not contain any application code. The reporting domain is executed exclusively through AWS services. It incorporates the following technologies:
The reporting domain incorporates the following technologies:

- [HashiCorp Terraform](https://developer.hashicorp.com/terraform)
- [AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html)
- [AWS Glue](https://docs.aws.amazon.com/glue/latest/dg/what-is-glue.html)
- [AWS Athena](https://docs.aws.amazon.com/athena/latest/ug/what-is.html)
- [AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)
- [AWS Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)
- [AWS SNS](https://docs.aws.amazon.com/sns/latest/dg/welcome.html)
- [AWS Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html)
- [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html)
- [Apache Iceberg](https://iceberg.apache.org/)
- [Microsoft Power BI](https://learn.microsoft.com/en-us/power-bi/)

Expand Down Expand Up @@ -57,6 +60,12 @@ git clone https://github.com/NHSDigital/nhs-notify-reporting.git
cd nhs-notify-reporting
```

Configure your development environment (requires [ASDF](https://asdf-vm.com/) to be installed):

```shell
make config
```

## Prerequisites

In order to facilitate cross-account export of data, the reporting domain requires IAM permissions for read-only access to the Glue Catalogue and underlying S3 storage in the NHS Notify core account.
Expand Down Expand Up @@ -134,7 +143,7 @@ New columns should also be added to the underlying [table definition](/infrastru

## Testing

As there is no application code suited to unit testing, testing of step functions and queries is currently performed manually.
All tests for the repository can be run using the `make test` command. You will need to have run `make config` first to configure your development environment.

## Design

Expand Down Expand Up @@ -191,6 +200,18 @@ This means that it is possible to run an aggregation on a previously executed pr

This offers performance, scaling and cost benefits and also means that aggregation contents will be consistent with underlying projections.

### Event Driven Reporting

To allow reporting on data that originates in non-core domains, the following architecture has been implemented in addition to that described above:
![Reporting Architecture Overview](/docs/diagrams/event_driven_reporting.png)

Events are streamed into append-only storage using parquet, and then ingested periodically into reporting tables, effectively following the same approach as the current core ingestion.
The event staging table is partitioned by the event's `type` field, then year, month and day, allowing for easy querying of the relevant event type(s).

The event staging table's schema defines a column for each of the event envelope fields that are common across Notify domains, with the `data` column being defined as a string.
The transformation lambda transforms each event's `data` property into a JSON string, allowing the solution to handle events of any shape. Event-specific ingestion queries can then be produced,
with knowledge of the relevant event structures to transform them into the correct format and upsert them into a reporting table.

### Handling PID

Staging tables exposed to Power BI should not contain any PID.
Expand Down
Loading
Loading