Most conformance failures get caught the worst possible way: a partner rejects a message in production, someone files a ticket, and you reverse-engineer what changed three sprints ago. The fix is boring and effective. Score your resources against the profile on every push, and fail the build when conformance regresses. Same idea as a unit test, aimed at US Core or AU Core instead of your business logic.
Why shift conformance left
Base FHIR validation only tells you the JSON is well-formed and the data types line up. It says nothing about whether a Patient carries the identifier and gender that US Core demands, or the birthDate that AU Core makes mandatory. Those are profile rules, and a resource can pass a plain schema check while failing every profile your trading partner cares about.
Catching that at merge time is cheap. Catching it after a payer or a state registry rejects a batch is not. The earlier the signal, the smaller the blast radius, so put the check where your team already looks: the PR.
The check, as a CI gate
The Interoperall CLI ships as a single binary. Its coverage command scores one or more FHIR resources against a profile and exits non-zero if any error-severity rule fails. That exit code is the whole trick. A non-zero exit fails the step, which fails the build, which blocks the merge.
Here's a GitHub Actions workflow that gates on US Core and AU Core. It's the same file you'll find in the repo at .github/workflows/interoperall-conformance.yml, trimmed for the page.
name: Interoperall conformance
on: [push, pull_request]
jobs:
conformance:
runs-on: ubuntu-latest
env:
INTEROPERALL_API_KEY: ${{ secrets.INTEROPERALL_API_KEY }}
# Point this at your published linux-x64 release asset.
INTEROPERALL_CLI_URL: https://github.com/your-org/interoperall/releases/download/cli-v1.0.0/interoperall-linux-x64
steps:
- uses: actions/checkout@v4
- name: Install CLI
run: |
curl -fsSL "$INTEROPERALL_CLI_URL" -o "$RUNNER_TEMP/interoperall"
chmod +x "$RUNNER_TEMP/interoperall"
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"
- run: interoperall whoami
- run: interoperall coverage us-core-patient examples/ci/patient-good.json
- run: interoperall coverage au-core-patient examples/ci/patient-au.json
A few notes on the moving parts:
- Installing the CLI. It isn't on npm yet, so CI downloads a prebuilt binary. Set
INTEROPERALL_CLI_URLto your published release asset and pin it to a tagged version so builds stay reproducible. Don't track "latest". whoamifirst. It confirms the key is valid before the real work runs, so a bad secret fails fast with a clear message instead of halfway through.- The coverage steps. Each one scores a known-good resource. If someone edits a mapping and drops
identifier, the score falls, an error rule fails, the command exits 1, and the PR turns red.
Not on GitHub?
The logic is portable. A shell script does the same three things, install, authenticate, gate, and drops into GitLab CI, Jenkins, or a pre-push hook. There's a ready-made examples/ci/run.sh in the repo you can adapt. The only GitHub-specific pieces are the YAML wrapper and the secrets syntax.
Getting an API key
You need a key for the authenticated commands. Generate one in the Interoperall app, then store it as a masked CI secret named INTEROPERALL_API_KEY. The CLI reads it from the environment, so no key ever lands in your workflow file. If you want a purely local check with no key and no network call, add --offline to any coverage command and it evaluates against the bundled profiles right on the runner.
The runs show up in your dashboard
Here's the part teams underestimate. Every authenticated CLI call is logged to your Interoperall account, so each CI run becomes a row in your metrics. Open the metrics dashboard and you'll see the coverage calls your pipeline made, broken out in the CLI versus API adoption view. That gives you a running picture of how often conformance gets checked across your repos, and which profiles you actually exercise, without anyone hand-reporting it. Offline runs stay local and don't appear, which is the right tradeoff when you're testing on a laptop.
Wire it once and conformance stops being a thing you remember to check. It's just part of the build, with a paper trail to prove it.