Contributing
Thank you for your interest in contributing to gofhir/models. This page covers the development setup, testing workflow, and guidelines for submitting changes.
Prerequisites
- Go 1.23 or later – The project uses Go workspaces and generics.
- Git – For cloning the repository and managing branches.
Getting Started
Clone the Repository
git clone https://github.com/gofhir/models.git
cd modelsUnderstand the Project Layout
models/
cmd/generator/ # Code generator tool
internal/ # Shared generation infrastructure
specs/ # FHIR StructureDefinition JSON files
r4/ # Generated R4 module (github.com/gofhir/models/r4/v2)
helpers/ # Hand-written helper constants (not generated)
r4b/ # Generated R4B module (github.com/gofhir/models/r4b/v2)
r5/ # Generated R5 module (github.com/gofhir/models/r5/v2)
docs/ # Documentation site (Hugo)
go.work # Go workspace fileSet Up the Workspace
The repository uses a Go workspace (go.work) to link all modules together for local development. No additional setup is required – Go will automatically use the workspace when you build or test from within the repository.
# Verify the workspace is functional
go work syncRunning Tests
Each FHIR version module has its own test suite. Run tests from the module directory:
# Test R4
cd r4 && go test ./...
# Test R4B
cd r4b && go test ./...
# Test R5
cd r5 && go test ./...Or run all tests from the repository root:
cd r4 && go test ./... && cd ../r4b && go test ./... && cd ../r5 && go test ./...The test suites cover:
- Resource struct construction and field access
- JSON marshaling and unmarshaling (including
resourceTypeinjection and contained resources) - XML marshaling and unmarshaling (namespace handling, primitive encoding, backbone elements)
- Fluent builder correctness
- Registry functions (NewResource, UnmarshalResource, GetResourceType, etc.)
- FHIRPath model metadata accuracy
- Code system constant validation
- Decimal type precision preservation
Fetching the FHIR specifications
The generator reads three JSON bundles per version from specs/. They total about
143 MB and are not committed, so a fresh clone has to download them first:
# Download and verify every version
./scripts/fetch-specs.sh
# Or just the one you need
./scripts/fetch-specs.sh r4
# Check what is already on disk without downloading
./scripts/fetch-specs.sh --verifyEach file is verified against the SHA-256 pinned in specs.lock, which also
records the source URL and FHIR release. A mismatch is a hard failure: if the
published specification changes, update specs.lock deliberately rather than
letting the generated output drift.
Without these files the generator stops with
failed to read required value sets. That is intentional — it used to continue
and silently emit *string in place of every generated code system type.
Conformance suite
conformance/ round-trips every official FHIR example through the library —
about 12,400 files across the three versions — and compares the outcome against
recorded known-failure lists in conformance/testdata/known_failures/.
./scripts/fetch-examples.sh # download the corpora (~200 MB per version)
cd conformance && go test ./...The suite skips itself when the corpus is absent, so it never forces the download
on a plain go test ./....
The lists are a ratchet, not a snapshot: the suite fails both when a passing file starts failing (a regression) and when a listed file starts passing (progress that has to be recorded). After a fix, re-record them and read the diff — every line removed is a bug fixed:
cd conformance && go test . -update-knownRegenerating Models
If you modify the code generator or update the FHIR specification files, regenerate the code.
cmd/generator is its own Go module, so run it from that directory:
cd cmd/generator
go run . r4 # Regenerate R4 code
go run . r4b # Regenerate R4B code
go run . r5 # Regenerate R5 codeCI regenerates all three versions on every pull request and fails if the result differs from what is committed, so include the regenerated output in your PR.
After regeneration, run the full test suite to verify correctness:
cd r4 && go test ./... && cd ../r4b && go test ./... && cd ../r5 && go test ./...r4/, r4b/, or r5/ directly (except for the helpers/ subdirectory). All generated files begin with // Code generated by gofhir. DO NOT EDIT. and will be overwritten when the generator runs. Modify the generator code in internal/codegen/generator instead.Types of Contributions
Bug Fixes
- Open an issue describing the bug with a minimal reproduction case.
- Create a branch:
git checkout -b fix/description. - Add a failing test that demonstrates the bug.
- Fix the issue – if it involves generated code, fix the generator and regenerate.
- Verify all tests pass.
- Submit a pull request.
New Features
- Open an issue to discuss the feature before starting work.
- Create a branch:
git checkout -b feat/description. - Implement the feature with tests.
- If the feature involves generated code, update the generator templates and regenerate all versions.
- Submit a pull request.
Documentation
- Documentation lives in
docs/content/en/docs/. - The site uses Hugo with the Hextra theme.
- To preview locally:
cd docs
hugo serverHelper Constants
The r4/helpers/ directory contains hand-written convenience constants. Contributions of new helper constants are welcome – for example:
- Additional LOINC codes for common clinical observations
- Additional UCUM unit helper functions
- Pre-built
CodeableConceptvalues for common value sets
Commit Message Convention
This project uses Conventional Commits for commit messages. The release-please bot uses these to generate changelogs and determine version bumps.
| Prefix | Purpose | Version Bump |
|---|---|---|
feat: | New feature | Minor |
fix: | Bug fix | Patch |
refactor: | Code restructuring | – |
docs: | Documentation only | – |
test: | Test additions/changes | – |
chore: | Maintenance tasks | – |
Examples:
feat: add Encounter resource builder validation
fix: correct XML namespace for contained resources
refactor: consolidate generated files and add XML deserialization
docs: add examples for Bundle constructionPull Request Guidelines
- One concern per PR – Keep pull requests focused on a single change.
- Include tests – All code changes should have corresponding tests.
- Run the full suite – Ensure all tests pass across all three FHIR versions before submitting.
- Regenerate if needed – If your change affects the generator, include the regenerated output in the PR.
- Follow existing style – Match the coding style and patterns used in the existing codebase.
- Update documentation – If your change adds or modifies public API, update the relevant documentation pages.
Code of Conduct
Please be respectful and constructive in all interactions. We are building tools for healthcare interoperability, and a welcoming community helps us do that better.