From e3b474929e4bc1b69ee56f1d9a4bfdd2401fdfdc Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Mon, 5 Jan 2026 12:07:29 +0000 Subject: [PATCH 01/17] Enable the pgAudit plugin for the HRM db --- .../20260105104900-pg_audit_plugin_enable.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 hrm-domain/hrm-service/migrations/20260105104900-pg_audit_plugin_enable.js diff --git a/hrm-domain/hrm-service/migrations/20260105104900-pg_audit_plugin_enable.js b/hrm-domain/hrm-service/migrations/20260105104900-pg_audit_plugin_enable.js new file mode 100644 index 000000000..0d07fae9f --- /dev/null +++ b/hrm-domain/hrm-service/migrations/20260105104900-pg_audit_plugin_enable.js @@ -0,0 +1,32 @@ +/** + * Copyright (C) 2021-2023 Technology Matters + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + up: async queryInterface => { + await queryInterface.sequelize.query(` + CREATE EXTENSION IF NOT EXISTS pgaudit; + `); + console.log('"label" column set to type TEXT'); + }, + down: async queryInterface => { + await queryInterface.sequelize.query(` + DROP EXTENSION pgaudit; + `); + console.log('"label" column set to type TEXT'); + }, +}; From b913d609eeaa7e7832f6656b7c717c9b14619592 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 6 Jan 2026 15:52:04 +0000 Subject: [PATCH 02/17] Fix service tests to install pgaudit extension --- .../hrm-service/docker-database/Dockerfile | 23 +++++++++++++++++++ .../docker-compose-persistent.yml | 2 +- .../docker-database/docker-compose.yml | 2 +- .../hrm-service/docker-database/hrmdb.sql | 6 ++--- test-support/db-init/dump.sql | 2 +- test-support/docker-compose-service-test.yml | 4 ++-- 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 hrm-domain/hrm-service/docker-database/Dockerfile diff --git a/hrm-domain/hrm-service/docker-database/Dockerfile b/hrm-domain/hrm-service/docker-database/Dockerfile new file mode 100644 index 000000000..43a0308ec --- /dev/null +++ b/hrm-domain/hrm-service/docker-database/Dockerfile @@ -0,0 +1,23 @@ +# Copyright (C) 2021-2023 Technology Matters +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see https://www.gnu.org/licenses/. + +FROM library/postgres:16.8 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends postgresql-16-pgaudit \ + && rm -rf /var/lib/apt/lists/* + +EXPOSE 5432 + +CMD ["postgres", "-c", "shared_preload_libraries=pgaudit"] \ No newline at end of file diff --git a/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml b/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml index 0b57e4edb..da1b01a35 100644 --- a/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml +++ b/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml @@ -14,7 +14,7 @@ services: db: - image: library/postgres:16.8 + build: . environment: POSTGRES_USER: rdsadmin diff --git a/hrm-domain/hrm-service/docker-database/docker-compose.yml b/hrm-domain/hrm-service/docker-database/docker-compose.yml index ed6c5c31d..0be248a54 100644 --- a/hrm-domain/hrm-service/docker-database/docker-compose.yml +++ b/hrm-domain/hrm-service/docker-database/docker-compose.yml @@ -14,7 +14,7 @@ services: db: - image: library/postgres:16.8 + build: . environment: POSTGRES_USER: rdsadmin diff --git a/hrm-domain/hrm-service/docker-database/hrmdb.sql b/hrm-domain/hrm-service/docker-database/hrmdb.sql index 8050cddb5..346f26c68 100644 --- a/hrm-domain/hrm-service/docker-database/hrmdb.sql +++ b/hrm-domain/hrm-service/docker-database/hrmdb.sql @@ -39,7 +39,7 @@ SET default_with_oids = false; -- CREATE ROLE hrm; -ALTER ROLE hrm WITH NOSUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; +ALTER ROLE hrm WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; CREATE ROLE rds_ad; ALTER ROLE rds_ad WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS; CREATE ROLE rds_iam; @@ -49,14 +49,14 @@ ALTER ROLE rds_password WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN CREATE ROLE rds_replication; ALTER ROLE rds_replication WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS; CREATE ROLE rds_superuser; -ALTER ROLE rds_superuser WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS; +ALTER ROLE rds_superuser WITH SUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS; ALTER ROLE rdsadmin WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN REPLICATION BYPASSRLS VALID UNTIL 'infinity'; CREATE ROLE rdsrepladmin; ALTER ROLE rdsrepladmin WITH NOSUPERUSER NOINHERIT NOCREATEROLE NOCREATEDB NOLOGIN REPLICATION NOBYPASSRLS; CREATE ROLE read_only_user; ALTER ROLE read_only_user WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION NOBYPASSRLS; CREATE ROLE resources; -ALTER ROLE resources WITH NOSUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; +ALTER ROLE resources WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; -- -- User Configurations -- diff --git a/test-support/db-init/dump.sql b/test-support/db-init/dump.sql index 9cbceef15..bbfa48222 100644 --- a/test-support/db-init/dump.sql +++ b/test-support/db-init/dump.sql @@ -58,7 +58,7 @@ BEGIN END $do$; -ALTER ROLE hrm WITH NOSUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; +ALTER ROLE hrm WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL 'infinity'; CREATE ROLE rds_ad; ALTER ROLE rds_ad WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS; CREATE ROLE rds_iam; diff --git a/test-support/docker-compose-service-test.yml b/test-support/docker-compose-service-test.yml index 7d58b2aca..7bc0295a7 100644 --- a/test-support/docker-compose-service-test.yml +++ b/test-support/docker-compose-service-test.yml @@ -14,7 +14,7 @@ services: db: - image: library/postgres:16.8 + build: ../hrm-domain/hrm-service/docker-database environment: POSTGRES_USER: rdsadmin @@ -24,7 +24,7 @@ services: volumes: - ./db-init/dump.sql:/docker-entrypoint-initdb.d/dump.sql - command: ['postgres', '-c', 'log_statement=all'] + command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - '5433:5432' From b1deb941717c87d32e04f4bb89e477e6fa30214a Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 09:27:51 +0000 Subject: [PATCH 03/17] Use docker compose to run service tests in CI --- .github/workflows/hrm-ci.yml | 24 +----------------------- hrm-domain/hrm-service/package.json | 4 ++-- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/.github/workflows/hrm-ci.yml b/.github/workflows/hrm-ci.yml index ab56530bf..1346fbe34 100644 --- a/.github/workflows/hrm-ci.yml +++ b/.github/workflows/hrm-ci.yml @@ -1,4 +1,4 @@ -# Copyright (C) 2021-2023 Technology Matters + # Copyright (C) 2021-2023 Technology Matters # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or @@ -149,28 +149,6 @@ jobs: - name: Build run: npm run build - - name: Build Service Docker Image - uses: docker/build-push-action@v6 - with: - context: ./ - file: ./hrm-domain/hrm-service/Dockerfile - push: false - tags: hrm-service - - - name: Setup database tables - uses: m4nu56/postgresql-action@1.0 - with: - # Version of PostgreSQL to use - postgresql version: 16.3 - # POSTGRES_DB - name for the default database that is created - postgresql db: hrmdb - # POSTGRES_USER - create the specified user with superuser power - postgresql user: rdsadmin - # POSTGRES_PASSWORD - superuser password - postgresql password: postgres - # POSTGRES_INIT_SCRIPTS - directory containing DB init scripts - postgresql init scripts: test-support/db-init - - name: Run Service Tests run: npm run test:service:ci diff --git a/hrm-domain/hrm-service/package.json b/hrm-domain/hrm-service/package.json index d6b5e728b..6a09793b1 100644 --- a/hrm-domain/hrm-service/package.json +++ b/hrm-domain/hrm-service/package.json @@ -19,8 +19,8 @@ "test": "run-s test:service", "test:run:watch": "cross-env AWS_REGION=us-east-1 CI=true TWILIO_ACCOUNT_SID=ACxxx TWILIO_AUTH_TOKEN=xxxxxx RDS_PASSWORD=postgres jest --maxWorkers=1 --forceExit --watch", "test:service": "cross-env POSTGRES_PORT=5433 run-s -c docker:compose:test:up test:service:ci:migrate test:service:run docker:compose:test:down", - "test:service:run": "cross-env AWS_REGION=us-east-1 SSM_ENDPOINT=http://mock-ssm/ SNS_ENDPOINT=http://mock-sns/ jest --verbose --maxWorkers=1 --forceExit service-tests", - "test:service:ci": "run-s test:service:ci:migrate test:service:ci:run", + "test:service:run": "cross-env AWS_REGION=us-east-1 SSM_ENDPOINT=http://mock-ssm/ SNS_ENDPOINT=http://mock-sns/ jest --verbose --maxWorkers=1 --forceExit --coverage service-tests", + "test:service:ci": "run-s test:service", "test:service:ci:migrate": "cross-env CI=true RDS_PASSWORD=postgres node ./db-migrate", "test:service:ci:run": "cross-env AWS_REGION=us-east-1 SSM_ENDPOINT=http://mock-ssm/ SNS_ENDPOINT=http://mock-sns/ CI=true TWILIO_ACCOUNT_SID=ACxxx TWILIO_AUTH_TOKEN=xxxxxx RDS_PASSWORD=postgres jest --verbose --maxWorkers=1 --forceExit --coverage service-tests", "test:coverage": "run-s docker:compose:test:up test:service:ci:migrate test:coverage:run docker:compose:test:down", From 6b6805ed721f84c537b5a8b5ab20859b163c5d51 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 09:41:21 +0000 Subject: [PATCH 04/17] Build hrm-service --- .github/workflows/hrm-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/hrm-ci.yml b/.github/workflows/hrm-ci.yml index 1346fbe34..50044f595 100644 --- a/.github/workflows/hrm-ci.yml +++ b/.github/workflows/hrm-ci.yml @@ -149,6 +149,14 @@ jobs: - name: Build run: npm run build + - name: Build Service Docker Image + uses: docker/build-push-action@v6 + with: + context: ./ + file: ./hrm-domain/hrm-service/Dockerfile + push: false + tags: hrm-service + - name: Run Service Tests run: npm run test:service:ci From dd9a53af19c7a98df102335c793cdbc411dda975 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 10:19:18 +0000 Subject: [PATCH 05/17] Fix resources CI service tests --- resources-domain/resources-service/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/resources-service/package.json b/resources-domain/resources-service/package.json index 3a6de5f94..7d4c3c84f 100644 --- a/resources-domain/resources-service/package.json +++ b/resources-domain/resources-service/package.json @@ -30,7 +30,7 @@ "test:run:watch": "cross-env AWS_REGION=us-east-1 CI=true TWILIO_ACCOUNT_SID=ACxxx TWILIO_AUTH_TOKEN=xxxxxx RDS_PASSWORD=postgres RESOURCES_PASSWORD=resources-password jest --maxWorkers=1 --forceExit --watch", "test:unit": "jest tests/unit", "test:service": "cross-env POSTGRES_PORT=5433 RDS_USERNAME=hrm RDS_PASSWORD=postgres RESOURCES_PASSWORD=resources-password run-s -c docker:compose:test:up db:create:schema test:service:ci:migrate test:service:ci:run docker:compose:test:down", - "test:service:ci": "RDS_USERNAME=rdsadmin RDS_PASSWORD=postgres RESOURCES_PASSWORD=resources-password run-s db:create:schema test:service:ci:migrate test:service:ci:run", + "test:service:ci": "run-s test:service", "test:service:ci:migrate": "node ./db-migrate", "test:service:ci:run": "cross-env AWS_REGION=us-east-1 CI=true TWILIO_ACCOUNT_SID=ACxxx TWILIO_AUTH_TOKEN=xxxxxx SSM_ENDPOINT=http://mock-ssm/ jest --verbose --maxWorkers=1 --forceExit --coverage tests/service", "test:coverage": "run-s docker:compose:test:up test:service:migrate test:coverage:run docker:compose:test:down", From 751db25d01a6a5ded98df0fa9bc1553ae930fbe4 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 10:40:07 +0000 Subject: [PATCH 06/17] Fix error output for retrying DB upgrades --- hrm-domain/hrm-service/db-migrate.js | 14 ++++++++++---- resources-domain/resources-service/db-migrate.js | 16 +++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/hrm-domain/hrm-service/db-migrate.js b/hrm-domain/hrm-service/db-migrate.js index 7327e1cbd..951934f95 100644 --- a/hrm-domain/hrm-service/db-migrate.js +++ b/hrm-domain/hrm-service/db-migrate.js @@ -82,10 +82,16 @@ async function migrate() { console.log('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - console.log('Migration failed. Retrying...', err); - // eslint-disable-next-line @typescript-eslint/no-loop-func - await new Promise(resolve => setTimeout(resolve, 250)); - lastErr = err; + if (err.message?.includes('ECONNRESET')) { + console.debug( + "Migration failed to connect to DB, assuming it's not ready yet & retrying...", + ); + // eslint-disable-next-line @typescript-eslint/no-loop-func + await new Promise(resolve => setTimeout(resolve, 250)); + lastErr = err; + } else { + throw err; + } } } if (ret) { diff --git a/resources-domain/resources-service/db-migrate.js b/resources-domain/resources-service/db-migrate.js index 97279e8b5..06929dfbe 100644 --- a/resources-domain/resources-service/db-migrate.js +++ b/resources-domain/resources-service/db-migrate.js @@ -79,13 +79,19 @@ async function migrate() { try { // eslint-disable-next-line no-await-in-loop ret = await umzug.up(); - console.log('Migration complete.', JSON.stringify(ret)); + console.info('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - console.log('Migration failed. Retrying...', err); - // eslint-disable-next-line @typescript-eslint/no-loop-func - await new Promise(resolve => setTimeout(resolve, 250)); - lastErr = err; + if (err.message?.includes('ECONNRESET')) { + console.debug( + "Migration failed to connect to DB, assuming it's not ready yet & retrying...", + ); + // eslint-disable-next-line @typescript-eslint/no-loop-func + await new Promise(resolve => setTimeout(resolve, 250)); + lastErr = err; + } else { + throw err; + } } } if (ret) { From f76a0338eec0f7494421cd999598ea99789edb15 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 10:47:18 +0000 Subject: [PATCH 07/17] Fix error output for retrying DB upgrades --- hrm-domain/hrm-service/db-migrate.js | 2 +- resources-domain/resources-service/db-migrate.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hrm-domain/hrm-service/db-migrate.js b/hrm-domain/hrm-service/db-migrate.js index 951934f95..91273a390 100644 --- a/hrm-domain/hrm-service/db-migrate.js +++ b/hrm-domain/hrm-service/db-migrate.js @@ -82,7 +82,7 @@ async function migrate() { console.log('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - if (err.message?.includes('ECONNRESET')) { + if (err.message?.includes('ConnectionRefusedError')) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", ); diff --git a/resources-domain/resources-service/db-migrate.js b/resources-domain/resources-service/db-migrate.js index 06929dfbe..2755cbf9b 100644 --- a/resources-domain/resources-service/db-migrate.js +++ b/resources-domain/resources-service/db-migrate.js @@ -82,7 +82,7 @@ async function migrate() { console.info('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - if (err.message?.includes('ECONNRESET')) { + if (err.message?.includes('ConnectionRefusedError')) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", ); From b30995534ebf62afae846977cb0846edadf8a4cf Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 10:49:55 +0000 Subject: [PATCH 08/17] Fix error output for retrying DB upgrades --- hrm-domain/hrm-service/db-migrate.js | 5 ++++- resources-domain/resources-service/db-migrate.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hrm-domain/hrm-service/db-migrate.js b/hrm-domain/hrm-service/db-migrate.js index 91273a390..9464dca40 100644 --- a/hrm-domain/hrm-service/db-migrate.js +++ b/hrm-domain/hrm-service/db-migrate.js @@ -82,7 +82,10 @@ async function migrate() { console.log('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - if (err.message?.includes('ConnectionRefusedError')) { + if ( + err.message?.includes('ConnectionRefusedError') || + err.message?.includes('SequelizeConnectionError') + ) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", ); diff --git a/resources-domain/resources-service/db-migrate.js b/resources-domain/resources-service/db-migrate.js index 2755cbf9b..90aeb4d85 100644 --- a/resources-domain/resources-service/db-migrate.js +++ b/resources-domain/resources-service/db-migrate.js @@ -82,7 +82,10 @@ async function migrate() { console.info('Migration complete.', JSON.stringify(ret)); break; } catch (err) { - if (err.message?.includes('ConnectionRefusedError')) { + if ( + err.message?.includes('ConnectionRefusedError') || + err.message?.includes('SequelizeConnectionError') + ) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", ); From 0b5f8113104c36043df0e352706ed8a54892a6cd Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 11:03:10 +0000 Subject: [PATCH 09/17] Fix error output for retrying DB upgrades --- hrm-domain/hrm-service/db-migrate.js | 3 +-- resources-domain/resources-service/db-migrate.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hrm-domain/hrm-service/db-migrate.js b/hrm-domain/hrm-service/db-migrate.js index 9464dca40..4ca3e59ea 100644 --- a/hrm-domain/hrm-service/db-migrate.js +++ b/hrm-domain/hrm-service/db-migrate.js @@ -83,8 +83,7 @@ async function migrate() { break; } catch (err) { if ( - err.message?.includes('ConnectionRefusedError') || - err.message?.includes('SequelizeConnectionError') + ['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name) ) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", diff --git a/resources-domain/resources-service/db-migrate.js b/resources-domain/resources-service/db-migrate.js index 90aeb4d85..529097086 100644 --- a/resources-domain/resources-service/db-migrate.js +++ b/resources-domain/resources-service/db-migrate.js @@ -83,8 +83,7 @@ async function migrate() { break; } catch (err) { if ( - err.message?.includes('ConnectionRefusedError') || - err.message?.includes('SequelizeConnectionError') + ['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name) ) { console.debug( "Migration failed to connect to DB, assuming it's not ready yet & retrying...", From 6bf37a5985955306000acc154d1f1e22f96a6e2a Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 11:48:35 +0000 Subject: [PATCH 10/17] Fix error output for retrying DB creates. Fix beacon poller service tests --- .../uscr-beacon-poller/package.json | 2 +- .../tests/service/docker-compose.yml | 2 +- resources-domain/resources-service/create-db.js | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json index 8e428b4fb..1855d7249 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json @@ -27,6 +27,6 @@ "test:service:run": "jest --verbose --maxWorkers=1 --forceExit tests/service", "test:unit": "jest --verbose tests/unit", "test:service": "cd ./tests/service && docker compose up -d && cd ../../../../../hrm-service && cross-env POSTGRES_PORT=5433 npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && cross-env HRM_DATABASE_PORT=5433 npm run test:service:run && cd ./tests/service && docker compose down", - "test:service:ci": "cd ./tests/service && docker compose -f docker-compose-ci.yml up -d && cd ../../../../../hrm-service && npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && npm run test:service:run; cd ./tests/service && docker compose -f docker-compose-ci.yml down" + "test:service:ci": "run-s test:service" } } diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml index cdd19ee0e..7d222f6d5 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml @@ -16,7 +16,7 @@ version: '3' services: db: - image: library/postgres:16.3 + build: ../../../../../hrm-service/docker-database environment: POSTGRES_USER: rdsadmin diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index dedb924b0..793bfaec4 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -64,10 +64,18 @@ async function create() { lastErr = undefined; break; } catch (err) { - console.log('Creation failed. Retrying...', err); - // eslint-disable-next-line @typescript-eslint/no-loop-func - await new Promise(resolve => setTimeout(resolve, 250)); - lastErr = err; + if ( + ['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name) + ) { + console.debug( + "Creation failed to connect to DB, assuming it's not ready yet & retrying...", + ); + // eslint-disable-next-line @typescript-eslint/no-loop-func + await new Promise(resolve => setTimeout(resolve, 250)); + lastErr = err; + } else { + throw err; + } } } From cc2ee4b3c7aafce2fc60416eb683e00c07019fcd Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 12:24:36 +0000 Subject: [PATCH 11/17] Fix error output for retrying DB creates. Fix beacon poller service tests --- .github/workflows/hrm-ci.yml | 3 +++ hrm-domain/hrm-core/profile/profileDataAccess.ts | 2 +- .../sql/{profile-update.sql.ts => profileUpdate.sql.ts} | 0 .../hrm-service/docker-database/docker-compose-persistent.yml | 2 +- hrm-domain/hrm-service/docker-database/docker-compose.yml | 2 +- .../integration-tests/docker-compose-integration-tests.yml | 4 ++-- .../uscr-beacon-poller/tests/service/docker-compose.yml | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) rename hrm-domain/hrm-core/profile/sql/{profile-update.sql.ts => profileUpdate.sql.ts} (100%) diff --git a/.github/workflows/hrm-ci.yml b/.github/workflows/hrm-ci.yml index 50044f595..c9e81b9ae 100644 --- a/.github/workflows/hrm-ci.yml +++ b/.github/workflows/hrm-ci.yml @@ -149,6 +149,9 @@ jobs: - name: Build run: npm run build + - name: Build + run: npm run build + - name: Build Service Docker Image uses: docker/build-push-action@v6 with: diff --git a/hrm-domain/hrm-core/profile/profileDataAccess.ts b/hrm-domain/hrm-core/profile/profileDataAccess.ts index 545ea2a0a..d7ad9b5f1 100644 --- a/hrm-domain/hrm-core/profile/profileDataAccess.ts +++ b/hrm-domain/hrm-core/profile/profileDataAccess.ts @@ -51,7 +51,7 @@ import { listProfilesSql, } from './sql/profile-list-sql'; import { getPaginationElements } from '../search'; -import { TOUCH_PROFILE_SQL, updateProfileByIdSql } from './sql/profile-update.sql'; +import { TOUCH_PROFILE_SQL, updateProfileByIdSql } from './sql/profileUpdate.sql'; import { ensureRejection, newErr, diff --git a/hrm-domain/hrm-core/profile/sql/profile-update.sql.ts b/hrm-domain/hrm-core/profile/sql/profileUpdate.sql.ts similarity index 100% rename from hrm-domain/hrm-core/profile/sql/profile-update.sql.ts rename to hrm-domain/hrm-core/profile/sql/profileUpdate.sql.ts diff --git a/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml b/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml index da1b01a35..ed6a76739 100644 --- a/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml +++ b/hrm-domain/hrm-service/docker-database/docker-compose-persistent.yml @@ -25,7 +25,7 @@ services: - ./hrmdb.sql:/docker-entrypoint-initdb.d/hrmdb.sql - hrm_postgres_volume:/var/lib/postgresql - command: ['postgres', '-c', 'log_statement=all'] + command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - '5432:5432' diff --git a/hrm-domain/hrm-service/docker-database/docker-compose.yml b/hrm-domain/hrm-service/docker-database/docker-compose.yml index 0be248a54..a7900262c 100644 --- a/hrm-domain/hrm-service/docker-database/docker-compose.yml +++ b/hrm-domain/hrm-service/docker-database/docker-compose.yml @@ -24,7 +24,7 @@ services: volumes: - ./hrmdb.sql:/docker-entrypoint-initdb.d/hrmdb.sql - command: ['postgres', '-c', 'log_statement=all'] + command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - '5432:5432' diff --git a/hrm-domain/integration-tests/docker-compose-integration-tests.yml b/hrm-domain/integration-tests/docker-compose-integration-tests.yml index 21534732a..7457e8e30 100644 --- a/hrm-domain/integration-tests/docker-compose-integration-tests.yml +++ b/hrm-domain/integration-tests/docker-compose-integration-tests.yml @@ -16,7 +16,7 @@ version: '3' services: db: - image: library/postgres:16.8 + build: ../hrm-service/docker-database environment: POSTGRES_USER: rdsadmin @@ -26,7 +26,7 @@ services: volumes: - ./db-init/dump.sql:/docker-entrypoint-initdb.d/dump.sql - command: ['postgres', '-c', 'log_statement=all'] + command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - '5433:5432' diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml index 7d222f6d5..45efc50e5 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml @@ -26,7 +26,7 @@ services: volumes: - ../../../../../../test-support/db-init/dump.sql:/docker-entrypoint-initdb.d/dump.sql - command: ['postgres', '-c', 'log_statement=all'] + command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - '127.0.0.1:5433:5432' From fcd7f1ab189f1eebaf3474ee238165d8389610b9 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 12:27:03 +0000 Subject: [PATCH 12/17] Run beacon poller service tests on port 5434 --- .../lambdas/custom-integrations/uscr-beacon-poller/package.json | 2 +- .../uscr-beacon-poller/tests/service/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json index 1855d7249..74790aa05 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json @@ -26,7 +26,7 @@ "docker:build": "docker build -t uscr-beacon-poller --build-arg lambda_name=uscr-beacon-poller --build-arg lambda_dir=hrm-domain/lambdas/custom-integrations -f ../../../../lambdas/Dockerfile ../../../../", "test:service:run": "jest --verbose --maxWorkers=1 --forceExit tests/service", "test:unit": "jest --verbose tests/unit", - "test:service": "cd ./tests/service && docker compose up -d && cd ../../../../../hrm-service && cross-env POSTGRES_PORT=5433 npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && cross-env HRM_DATABASE_PORT=5433 npm run test:service:run && cd ./tests/service && docker compose down", + "test:service": "cd ./tests/service && docker compose up -d && cd ../../../../../hrm-service && cross-env POSTGRES_PORT=5434 npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && cross-env HRM_DATABASE_PORT=5433 npm run test:service:run && cd ./tests/service && docker compose down", "test:service:ci": "run-s test:service" } } diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml index 45efc50e5..3edcc4643 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/tests/service/docker-compose.yml @@ -29,7 +29,7 @@ services: command: ['postgres', '-c', 'log_statement=all', '-c', 'shared_preload_libraries=pgaudit'] ports: - - '127.0.0.1:5433:5432' + - '127.0.0.1:5434:5432' service: image: hrm-service ports: From 8835ff5a5008880c9b21679d4b5bf8bfd72912eb Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 14:45:09 +0000 Subject: [PATCH 13/17] Run beacon poller service tests on port 5434 --- .../lambdas/custom-integrations/uscr-beacon-poller/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json index 74790aa05..1d7ba97c7 100644 --- a/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json +++ b/hrm-domain/lambdas/custom-integrations/uscr-beacon-poller/package.json @@ -26,7 +26,7 @@ "docker:build": "docker build -t uscr-beacon-poller --build-arg lambda_name=uscr-beacon-poller --build-arg lambda_dir=hrm-domain/lambdas/custom-integrations -f ../../../../lambdas/Dockerfile ../../../../", "test:service:run": "jest --verbose --maxWorkers=1 --forceExit tests/service", "test:unit": "jest --verbose tests/unit", - "test:service": "cd ./tests/service && docker compose up -d && cd ../../../../../hrm-service && cross-env POSTGRES_PORT=5434 npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && cross-env HRM_DATABASE_PORT=5433 npm run test:service:run && cd ./tests/service && docker compose down", + "test:service": "cd ./tests/service && docker compose up -d && cd ../../../../../hrm-service && cross-env POSTGRES_PORT=5434 npm run test:service:ci:migrate && cd ../lambdas/custom-integrations/uscr-beacon-poller && cross-env HRM_DATABASE_PORT=5434 npm run test:service:run && cd ./tests/service && docker compose down", "test:service:ci": "run-s test:service" } } From daa49ad320599e83ffc46efdb8bbb6c481039a5c Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 15:06:50 +0000 Subject: [PATCH 14/17] Fix connect error catching for create db --- resources-domain/resources-service/create-db.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index 793bfaec4..b3867b256 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -64,11 +64,9 @@ async function create() { lastErr = undefined; break; } catch (err) { - if ( - ['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name) - ) { + if (error.message?.toLowerCase?.includes('connect')) { console.debug( - "Creation failed to connect to DB, assuming it's not ready yet & retrying...", + "Creation failed connecting to DB, assuming it's not ready yet & retrying...", ); // eslint-disable-next-line @typescript-eslint/no-loop-func await new Promise(resolve => setTimeout(resolve, 250)); From 0e7f7419ce882265c29de69ada036a15cdb2f5d7 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 7 Jan 2026 15:22:59 +0000 Subject: [PATCH 15/17] Fix connect error catching for create db --- resources-domain/resources-service/create-db.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index b3867b256..1c133f5f0 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -64,7 +64,7 @@ async function create() { lastErr = undefined; break; } catch (err) { - if (error.message?.toLowerCase?.includes('connect')) { + if (err.message?.toLowerCase?.includes('connect')) { console.debug( "Creation failed connecting to DB, assuming it's not ready yet & retrying...", ); From f9c625863b492e67e83c62e9ffb2c77e63351369 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Thu, 8 Jan 2026 08:39:42 +0000 Subject: [PATCH 16/17] Fix connect error catching for create db --- resources-domain/resources-service/create-db.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index 1c133f5f0..bb81f66a5 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -64,7 +64,7 @@ async function create() { lastErr = undefined; break; } catch (err) { - if (err.message?.toLowerCase?.includes('connect')) { + if (err.message?.toLowerCase()?.includes('connect')) { console.debug( "Creation failed connecting to DB, assuming it's not ready yet & retrying...", ); From 72274a0422ac307082c3fa97c2a0227118d5869e Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Thu, 8 Jan 2026 09:05:38 +0000 Subject: [PATCH 17/17] Fix connect error catching for create db --- resources-domain/resources-service/create-db.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index bb81f66a5..b8309aeab 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -64,7 +64,8 @@ async function create() { lastErr = undefined; break; } catch (err) { - if (err.message?.toLowerCase()?.includes('connect')) { + // Catch and ECONNRESET, ECONNREFUSED or messages with 'connection' / 'connect' in. Cast a broad net! + if (err.message?.toLowerCase()?.includes('conn')) { console.debug( "Creation failed connecting to DB, assuming it's not ready yet & retrying...", );