Delivery and governance
Repository and pipelines
All code, database migrations and infrastructure configuration live in one GitHub repository. Every deploy runs in GitHub Actions. Changes reach preview automatically, and reach production only when someone runs the promote workflow for that app.
The repository
- Location
twocolddogs/hnzradtools, private, on a personal GitHub account. Default branchdevelop.- History
- About 1,400 commits since March 2026. One human contributor, plus the GitHub Copilot coding agent.
- Structure
- An npm workspaces monorepo. Shared code goes in
packages/and is consumed as a workspace dependency, never copied between apps. - Plan limits
- On the current plan, branch protection, rulesets and required reviews are unavailable. Moving the repository into a Health NZ organisation removes this limit (R4).
| Path | Contents |
|---|---|
apps/site-profiles | Site Profiles, and the email worker under workers/hnz-email |
apps/my-radiology | Member portal |
apps/service-sizing | Worker API and frontend/ |
apps/triage | worker/, frontend/, offline scripts/ |
workers/hnz-identity | Identity hub, migrations, tests |
packages/ | Shared code (below) |
docs/ | Plans, access model, cutover run sheet |
scripts/ | Database drift check and utilities |
.github/workflows | CI, deploy and promote workflows |
architecture/ | This pack |
| Package | Purpose |
|---|---|
@hnz/auth | Token signing and verification, password hashing, random tokens (Web Crypto) |
@hnz/crypto | AES-256-GCM encryption and HMAC blind indexes, with strict key checks |
@hnz/role-constants | Leadership and member role registries |
@hnz/specialty-constants | Radiologist specialty keys and labels |
@hnz/broadcast-renderer | Announcement text to HTML |
The hub uses @hnz/auth and @hnz/crypto. The older apps still carry their own copies of that code, and moving them onto the packages is on the roadmap (R18).
How a change reaches production
Rollback
Revert the promote merge commit on the production branch and push; the push redeploys the previous code. Database migrations are forward-only and are not reversed by a revert. For data, D1's 30-day point-in-time restore (Time Travel) is the recovery tool; documenting it and recording a restore point before each production migration is on the roadmap (R15). Cloudflare also offers one-click rollback to an earlier deployment for Pages and Workers, which is faster than a revert.
Workflows
| Workflow | Runs on | Does |
|---|---|---|
deploy-site-profiles.yml | push to develop or site-profiles-prod | Build, apply D1 migrations, deploy Pages. |
deploy-my-radiology.yml | push to develop or my-radiology-prod | Build, apply D1 migrations, deploy Pages. |
deploy-service-sizing.yml | push to develop or service-sizing-prod | Apply migrations, deploy the Worker, then build and deploy the frontend. |
deploy-triage.yml | push to develop or triage-prod | Deploy the Worker and frontend. Migrations are applied by hand (R20). |
deploy-hnz-identity.yml | push to develop or hnz-identity-prod | Apply migrations, deploy the hub. |
deploy-hnz-email.yml | push to develop or site-profiles-prod | Deploy the email worker. |
deploy-portal.yml | push to develop or main | Deploy the launch page. Currently publishes more than the launch page (R1). |
deploy-architecture.yml | push to develop touching architecture/ | Publish this pack to architecture.hnzradtools.nz. |
promote-to-prod.yml | manual, choose an app | Merge all of develop into the app's production branch, apply production migrations, build and deploy that app. The default option promotes My HNZ Radiology and Site Profiles together. |
ci-*.yml (five) | pull requests; pushes to develop and prod branches | Type check only. Runs alongside the deploy, not before it (R16). |
One gap: the promote workflow merges using GitHub's built-in token, which does not trigger other workflows. Anything that deploys only from a push, such as the email worker, is therefore not redeployed by a promote, and the hub is not yet a promote option (R6).
Deploys authenticate with two repository secrets, CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID. Runtime secrets are set directly in Cloudflare and never pass through GitHub.
Database migrations
Each app's schema is a numbered sequence of SQL files in its migrations/ directory. D1 records which files have run and never runs one twice.
- Append-only. Once a migration has run in any environment, the file is frozen. To change what it did, add a new migration, written to be safe to re-run (
IF NOT EXISTS,INSERT OR IGNORE). Editing an applied file leaves environments with different schemas but identical-looking histories. - Preview first. A push to
developapplies new migrations to the preview database; promote applies them to production before the new code is deployed. - Drift check.
scripts/check-d1-drift.sh <app>compares applied migrations, repository files and the live schema across production and preview, and exits non-zero on any difference. It is read-only and should be run before any non-trivial schema change.
Proposed governance under Health NZ
These changes turn the existing pipeline into one that meets an organisational standard. None needs application changes.
| Change | Why |
|---|---|
| Transfer the repository to a Health NZ GitHub organisation | Ownership, access management through Health NZ accounts, and the features below. |
Protect develop and every *-prod branch; require pull requests with one review | No change reaches preview or production without a second person. |
A production environment with required reviewers, holding a production-only Cloudflare token | Promotion needs Health NZ approval, and the preview token cannot touch production. |
| Make deploys wait for CI; add CI for the hub and email worker; run the existing tests | A failing check stops a release. |
| Enable Dependabot alerts and updates, secret scanning and push protection | Known-vulnerable dependencies and leaked credentials are caught automatically. |
Add a CODEOWNERS file for migrations, auth code and workflows | The most sensitive paths always get the right reviewer. |