Skip to content

Validating a realm in CI

realm_validate answers “would this load?” inside a running appliance. The same checks run with no appliance at all, so a realm repository can make them a required check — including on pull requests from forks, which can reach neither an appliance nor its MCP door. They cover what realm_validate covers: realm.yml, types and their parents, joins, producers and the governance their source can honour, views, rules, apps, side files, and the handler build.

The validator ships in the appliance server image, ghcr.io/embabel/assistant, as a second command. The image you validate with is the appliance whose verdict you get, so pin the tag your users run when it matters; latest follows releases.

A realm that builds on other realms names them. A realm that extends realm-code-model’s types, or joins through realm-java-code’s producers, does not load alone, and is not judged alone: each realm given as a dependency counts as installed beside it — its types and producers, not its own problems. The default world’s types are always known, as they are in every world.

A property a query reads that no type declares is a warning — an error under strict. Every view, lens script, type examples: query, sources.yml query, and the Cypher or {prop: …} map a type or join description shows is read for n.prop, n {.prop} and (n:Label {prop: …}) on a node of a declared type. The property counts as declared when that type or any of its ancestors or descendants declares it — in this realm, a dependency, or the default world — when a producer feeding the type names it (compute:, project:, the join’s recordKeyField, a brings: child’s id and project:), when a DERIVE head stamps it, or when it is the node’s id, its content, or an ai_-prefixed value. A map in a description may pin a join’s anchor by its keyField instead. A node whose label no type gives properties, whose type extends one not installed beside it, or whose name is rebound (UNWIND … AS n, … AS n) is not judged. Declare what the rows carry: an undeclared property is missing from the schema a model writes Cypher from, and is never coerced to a type. A deployment can switch the check off as realm-undeclared-properties.

.github/workflows/validate.yml
name: Validate
on: [push, pull_request]
jobs:
realm:
uses: embabel-worlds/realm-spec/.github/workflows/validate-realm.yml@main
with:
with: embabel-worlds/realm-code-model embabel-worlds/realm-java-code
# path: . the realm's directory in this repository
# image: ghcr.io/embabel/assistant:<tag>
# strict: true fail on warnings too

Then mark realm / validate required under the repository’s branch protection. with takes owner/repo, owner/repo@ref (a branch or tag), or ./dir in the same repository, separated by spaces or newlines. The workflow needs no secret and only contents: read; the checkout and every dependency are mounted read-only.

Terminal window
docker run --rm --entrypoint realm-validate \
-v "$PWD:/realms/my-realm:ro" \
-v "$PWD/../realm-code-model:/with/realm-code-model:ro" \
ghcr.io/embabel/assistant:latest /realms/my-realm --with /with/realm-code-model

With the appliance CLI installed, embabel realm validate . --with ../realm-code-model runs the same image at the appliance’s own version, with nothing running.

Option Meaning
--with <dir> a realm installed beside this one; repeatable
--json the report as JSON: realm, ok, passed, errors, warnings, notes, problems[] with severity, message, suggestion and location (file, path, line, column)
--strict fail on warnings as well as errors

Exit status 0 passes, 1 does not (an error, or a warning under --strict), and 2 could not validate — a directory that does not exist, or a check that itself failed. A note never fails.