A dbt project of Tamanu's standard models. This includes:
- raw (or source) schema
- reporting schema
- analytics schema (upcoming)
This project includes AI rules for AI assistants located in the ai/ directory.
To use these AI rules with Cline or Cursor, you need to create a symbolic link to the ai/ directory to make the rules accessible to your AI assistant.
Python and dbt dependencies are managed with uv from
pyproject.toml. Run project commands through uv run — it syncs the virtualenv
automatically — and pass --env-file .env to load the database credentials and
DBT_PROFILES_DIR:
cp .env.example .env # then fill in real values
uv run --env-file .env dbt deps # one-time: install dbt packages (from hub.getdbt.com)
uv run --env-file .env dbt build # build + test
uv run --env-file .env sqlfluff lint models.env (copied from .env.example) provides the DB connection vars plus
DBT_PROFILES_DIR=config, so dbt finds config/profiles.yml without a --profiles-dir
flag. Run dbt deps once before building or linting. There is no session-start hook or
manual venv activation — uv run handles the environment.
We use SQLFluff and the configuration file is located in the root folder and is named .sqlfluff.
There are two commands available to run:
sqlfluff lint models- Lints the file (does not apply fix)sqlfluff fix models- Fixes the SQL files
Automated Upgrade (Recommended): Use the GitHub Actions workflow to automatically upgrade to the latest Tamanu version or specify a version manually.
Quick start:
- Go to Actions → "Tamanu Version Upgrade"
- Click "Run workflow"
- Leave version empty for auto-detection or specify a version
- Review and merge the generated PR
- After merging, run locally:
python scripts/build_reporting_assets.py
The GitHub Actions workflow updates the version and refreshes source models. After merging, you need to run the build script locally to prepare models and generate reporting assets (requires database connection).
To refresh the source models from the Tamanu repository, execute the following command:
python scripts/refresh_tamanu_source.py
This command pulls the source model information from the Tamanu repository based on the version specified in the dbt_project.yml file. All models located under the tamanu/database/model/central-server/public/ folder (remote tamanu repository) will be copied to the models/sources/ folder (local repository).
After upgrading the Tamanu version (via GitHub Actions), build the reporting assets:
python scripts/build_reporting_assets.pyThis script performs the following steps:
- Generate survey models (for non-standard deployments)
- Validate report configurations
- Process translations (check, generate macro, convert to Excel)
- Clean and prepare dbt environment
- Build dbt models and documentation
- Generate language-specific reports for all supported languages
- List all Tamanu reports
The generated assets are saved in the compiled/ folder. The documentation is versioned and placed in a subfolder:
- Dataset SQL scripts:
compiled/views/reporting_schema_build_script.sql - Compiled report JSON files:
compiled/reports/ - Import script:
compiled/reports/importReports.js - Versioned documentation:
compiled/v{VERSION}/reporting-docs-v{VERSION}-{DEPLOYMENT}.html
Set has_sensitive_facility: true in the vars block of dbt_project.yml to include models
tagged restricted (sensitive-facility dataset views) when generating reports and the reporting
schema script. When false (the default), those models are silently excluded from both
generate_project_reports() and generate_reporting_schema_script().
The flag is read at script run-time from dbt_project.yml via get_dbt_project_vars(), not
from the dbt runtime context, so it must be set in the file before running the build scripts.
To automatically generate dbt models and documentation for surveys from database, execute the following command:
python scripts/generate_survey_models.py
This will generate models and documentation for all surveys in the Tamanu database.
This script generates a list of all reports in the repository and outputs the result in a Markdown file.
To generate a report list:
python list_tamanu_reports.py
To import the compiled report definitions (and optionally a reporting schema) into a
central server running on Kubernetes, use the scripts in
scripts/import-reports/. There is a PowerShell version for
Windows (import-reports-k8s.ps1) and an equivalent Bash version for macOS/Linux
(import-reports-k8s.sh). They switch the kubectl context first and default to the
demo cluster (configurable via --context / -Context), and default to a read-only
plan, only writing when re-run with -Apply / --apply. See
scripts/import-reports/README.md for prerequisites,
options, and examples.
We will use semantic versioning < major >.< minor >.< patch >. This number will mirror Tamanu's release
< major >.< minor > version numbers with the < patch > number for patching within this repository.
A release is a version bump and a compiled bundle, in one PR, followed by a tag.
Both halves matter: publishing is driven by the tag, but it uploads the bundle committed
under compiled/v<version>/. Tagging a version with no bundle behind it publishes
nothing — the upload fails on a path that does not exist, or is skipped silently.
Releases are usually cut from the maintenance branch for the version (2.60, 2.59, …),
not from main. main carries the next in-development version.
From the version branch you are releasing:
uv run --env-file .env python scripts/prepare_release.pyThis works out the next patch version, cuts a release/vX.Y.Z branch, stamps
dbt_project.yml and pyproject.toml, builds the reporting assets, diffs the result
against the last released bundle, and drafts the commit message and PR body under
target/. It stops before committing — add --commit to have the commit made — and
never pushes or opens the PR.
Before building anything it checks that dbt resolves to the release database matching the
version being released. Building against the wrong database — a stale .env still
pointing at another version, or a deployment replica — produces artefacts that look
completely valid and are wrong for the branch. Use --dry-run to see what it would do,
and --no-db-check only when preparing a release from an already-built bundle.
- Bump the version in
dbt_project.ymlandpyproject.toml - Build the bundle (see Build Reporting Assets); commit the
three aggregate artefacts under
compiled/v<version>/. The per-report JSONs are gitignored build output - Open a PR against the version branch and merge it (merge commit, not squash)
- Then draft a GitHub release: choose the version branch, tag it
vX.Y.Z, and publish
Publishing the release is what triggers publish-artifacts.yml, which uploads the bundle
to S3 and registers it with the meta-server. Never upload bundles by hand. If a release
publishes nothing, check that compiled/v<version>/ was committed before the tag was cut.
Copyright (C) 2026 BES International Limited.
This project is licensed under the GNU General Public License, Version 3.0 (LICENSE) or https://www.gnu.org/licenses/gpl-3.0-standalone.html, or any later version of that licence, at your option.
models/sources/ and models/logs/ are not authored here. They are copied verbatim from
database/model/public and database/model/logs in
beyondessential/tamanu by
scripts/refresh_tamanu_source.py, and re-synced on every Tamanu upgrade. Those files fall
under Tamanu's default GPL 3.0-or-later terms. Edit them upstream, not here.