Skip to content
Contributing

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 models

Understand 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 file

Set 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 sync

Running 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 resourceType injection 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 --verify

Each 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-known

Regenerating 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 code

CI 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 ./...
Never edit the generated files in 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

  1. Open an issue describing the bug with a minimal reproduction case.
  2. Create a branch: git checkout -b fix/description.
  3. Add a failing test that demonstrates the bug.
  4. Fix the issue – if it involves generated code, fix the generator and regenerate.
  5. Verify all tests pass.
  6. Submit a pull request.

New Features

  1. Open an issue to discuss the feature before starting work.
  2. Create a branch: git checkout -b feat/description.
  3. Implement the feature with tests.
  4. If the feature involves generated code, update the generator templates and regenerate all versions.
  5. Submit a pull request.

Documentation

  1. Documentation lives in docs/content/en/docs/.
  2. The site uses Hugo with the Hextra theme.
  3. To preview locally:
cd docs
hugo server

Helper 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 CodeableConcept values 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.

PrefixPurposeVersion Bump
feat:New featureMinor
fix:Bug fixPatch
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 construction

Pull Request Guidelines

  1. One concern per PR – Keep pull requests focused on a single change.
  2. Include tests – All code changes should have corresponding tests.
  3. Run the full suite – Ensure all tests pass across all three FHIR versions before submitting.
  4. Regenerate if needed – If your change affects the generator, include the regenerated output in the PR.
  5. Follow existing style – Match the coding style and patterns used in the existing codebase.
  6. 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.

Last updated on