Skip to content

Commit 96b2edd

Browse files
committed
Add GitHub Pages schema explorer
Publish the FermentationJSON schema catalog through GitHub Pages and add an interactive JSON Schema Studio-based explorer. Build and deploy the site automatically from main while keeping the repository schemas and catalog as the authoritative source.
1 parent 58d5115 commit 96b2edd

5 files changed

Lines changed: 432 additions & 0 deletions

File tree

.github/workflows/pages.yml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Deploy schema explorer
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- ".github/workflows/pages.yml"
9+
- "schemas/**"
10+
- "tools/schema-explorer/**"
11+
- "tests/**"
12+
- "pyproject.toml"
13+
- "uv.lock"
14+
workflow_dispatch:
15+
16+
permissions:
17+
contents: read
18+
pages: write
19+
id-token: write
20+
21+
concurrency:
22+
group: pages
23+
cancel-in-progress: true
24+
25+
jobs:
26+
build:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Check out FermentationJSON
30+
uses: actions/checkout@v7
31+
32+
- name: Set up Python
33+
uses: actions/setup-python@v7
34+
with:
35+
python-version: "3.14"
36+
37+
- name: Install uv
38+
run: python -m pip install uv
39+
40+
- name: Validate FermentationJSON
41+
run: |
42+
uv sync --frozen
43+
uv run pytest
44+
uv run ruff check .
45+
uv run ruff format --check .
46+
47+
- name: Check out JSON Schema Studio v0.9.1
48+
uses: actions/checkout@v7
49+
with:
50+
repository: ioflux-org/studio-json-schema
51+
ref: v0.9.1
52+
path: .pages-vendor/json-schema-studio
53+
54+
- name: Set up Node.js
55+
uses: actions/setup-node@v7
56+
with:
57+
node-version: "22"
58+
cache: npm
59+
cache-dependency-path: .pages-vendor/json-schema-studio/package-lock.json
60+
61+
- name: Build JSON Schema Studio
62+
working-directory: .pages-vendor/json-schema-studio
63+
run: |
64+
npm ci
65+
npm run build -- --base=./
66+
67+
- name: Build FermentationJSON Pages site
68+
run: |
69+
python tools/schema-explorer/build_site.py \
70+
--studio-dist .pages-vendor/json-schema-studio/dist \
71+
--studio-license .pages-vendor/json-schema-studio/LICENSE \
72+
--output _site
73+
74+
- name: Configure GitHub Pages
75+
uses: actions/configure-pages@v6
76+
77+
- name: Upload GitHub Pages artifact
78+
uses: actions/upload-pages-artifact@v5
79+
with:
80+
path: _site/
81+
82+
deploy:
83+
environment:
84+
name: github-pages
85+
url: ${{ steps.deployment.outputs.page_url }}
86+
runs-on: ubuntu-latest
87+
needs: build
88+
steps:
89+
- name: Deploy to GitHub Pages
90+
id: deployment
91+
uses: actions/deploy-pages@v5

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ catalog.
6868

6969
Passing JSON Schema validation establishes structural validity only. Full FermentationJSON conformance also includes semantic requirements that are not completely expressible in JSON Schema, such as reference integrity, scientific interpretation rules, compatibility preservation, and loss-reporting behavior.
7070

71+
## Interactive schema explorer
72+
73+
The repository's GitHub Pages workflow publishes and visualizes the current pre-release schema set at:
74+
75+
`https://gregrr.github.io/fermentation-json/`
76+
77+
The Pages site provides an interactive schema graph and a selector generated from the versioned schema catalog. Cataloged schemas are also published as raw JSON at their canonical `$id` paths. The site is rebuilt automatically from `main`; the repository schemas remain the authoritative source, and the published `0.1.0` schema set remains explicitly pre-release until promoted through the project's release process.
78+
7179
## Quantity model
7280

7381
Every interoperable quantity has a canonical representation. A reported representation is optional but strongly recommended when the value originated from user input, an imported document, an instrument, a laboratory result, a product label, a publication, or another identifiable source.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from __future__ import annotations
2+
3+
import importlib.util
4+
import json
5+
from pathlib import Path
6+
7+
ROOT = Path(__file__).resolve().parents[2]
8+
BUILD_SCRIPT = ROOT / "tools" / "schema-explorer" / "build_site.py"
9+
CATALOG_PATH = ROOT / "schemas" / "catalog.v0.1.0.json"
10+
11+
spec = importlib.util.spec_from_file_location("schema_explorer_build_site", BUILD_SCRIPT)
12+
assert spec is not None and spec.loader is not None
13+
build_site_module = importlib.util.module_from_spec(spec)
14+
spec.loader.exec_module(build_site_module)
15+
16+
17+
def _fake_studio(tmp_path: Path) -> tuple[Path, Path]:
18+
studio = tmp_path / "studio-dist"
19+
(studio / "assets").mkdir(parents=True)
20+
(studio / "assets" / "index-test.js").write_text("export {};\n", encoding="utf-8")
21+
(studio / "index.html").write_text(
22+
(
23+
'<!doctype html><div id="root"></div>'
24+
'<script type="module" crossorigin '
25+
'src="/fermentation-json/studio/assets/index-test.js"></script>'
26+
),
27+
encoding="utf-8",
28+
)
29+
license_path = tmp_path / "LICENSE"
30+
license_path.write_text("MIT test license\n", encoding="utf-8")
31+
return studio, license_path
32+
33+
34+
def test_pages_build_publishes_cataloged_schemas_at_canonical_paths(tmp_path: Path) -> None:
35+
studio, license_path = _fake_studio(tmp_path)
36+
output = tmp_path / "site"
37+
38+
build_site_module.build_site(studio, license_path, output)
39+
40+
catalog = json.loads(CATALOG_PATH.read_text(encoding="utf-8"))
41+
version = catalog["version"]
42+
for entry in catalog["schemas"]:
43+
published = output / "schemas" / version / entry["path"]
44+
assert published.read_bytes() == (ROOT / "schemas" / entry["path"]).read_bytes()
45+
46+
47+
def test_pages_launcher_and_studio_bootstrap_are_catalog_driven(tmp_path: Path) -> None:
48+
studio, license_path = _fake_studio(tmp_path)
49+
output = tmp_path / "site"
50+
51+
build_site_module.build_site(studio, license_path, output)
52+
53+
launcher = (output / "index.html").read_text(encoding="utf-8")
54+
studio_index = (output / "studio" / "index.html").read_text(encoding="utf-8")
55+
56+
assert "FermentationJSON Schema Explorer" in launcher
57+
assert "pre-release schema set 0.1.0" in launcher
58+
assert "core/document.schema.json" in launcher
59+
assert "ingredients/hop.schema.json" in launcher
60+
assert "ioflux.schema.editor.content" in studio_index
61+
assert "../schemas/0.1.0/${schemaPath}" in studio_index
62+
assert 'await import("/fermentation-json/studio/assets/index-test.js")' in studio_index
63+
assert '<script type="module" crossorigin src=' not in studio_index
64+
assert (output / ".nojekyll").is_file()
65+
assert (output / "third-party" / "json-schema-studio-MIT.txt").read_text(
66+
encoding="utf-8"
67+
) == "MIT test license\n"

tools/schema-explorer/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# FermentationJSON schema explorer
2+
3+
The public GitHub Pages site is built from the repository's versioned schema
4+
catalog and the tagged MIT-licensed JSON Schema Studio application.
5+
6+
The repository schemas remain authoritative. The Pages build:
7+
8+
1. validates the repository test suite;
9+
2. builds JSON Schema Studio from the pinned upstream tag;
10+
3. publishes every cataloged schema at the path implied by its canonical `$id`;
11+
4. generates a FermentationJSON schema selector from `schemas/catalog.v0.1.0.json`;
12+
5. preloads the selected schema into the unmodified Studio application; and
13+
6. deploys the resulting static site to GitHub Pages.
14+
15+
JSON Schema Studio is not vendored into this repository. The deployment workflow
16+
checks out the pinned upstream release and includes its MIT license in the
17+
published site.
18+
19+
The current integration targets JSON Schema Studio `v0.9.1`.

0 commit comments

Comments
 (0)