Skip to content

feat(schemas): publish meta-schemas to schemas.opendecree.dev via Pages#263

Merged
zeevdr merged 1 commit into
mainfrom
feat/pages-publish-meta-schemas
Apr 29, 2026
Merged

feat(schemas): publish meta-schemas to schemas.opendecree.dev via Pages#263
zeevdr merged 1 commit into
mainfrom
feat/pages-publish-meta-schemas

Conversation

@zeevdr
Copy link
Copy Markdown
Member

@zeevdr zeevdr commented Apr 29, 2026

Summary

Phase 1 + Phase 3 of the schemas-publishing work for #125. Adds:

  1. .github/workflows/deploy-pages.yml — builds _site/ from schemas/v*/..., validates, uploads as the Pages artifact, deploys via actions/deploy-pages@v4. Triggers: push to main filtered on schemas/** + workflow_dispatch for manual republish.
  2. scripts/generate-schema-index.py — stdlib-only generator that walks _site/schema/v*/ and writes _site/index.html (table of versions and links) plus a _site/robots.txt.
  3. docs/development/schemas-hosting-runbook.md — one-time setup, publishing flow, immutability policy, troubleshooting.
  4. .agents/context/schema-spec.md — resolves the "Hosting target" open question to "Pages on decree itself, custom domain via Cloudflare CNAME (DNS-only)" + cross-links the runbook.

Closes #125 (after the manual one-time DNS + Pages setup below).

Allowlist publishing model

Pages source is set to GitHub Actions (not "Deploy from a branch"). The workflow:

  1. Builds a fresh _site/ directory in the runner's tmpfs each invocation.
  2. Copies schemas/vX.Y.Z/decree-{schema,config}.json into _site/schema/vX.Y.Z/ (note the dir rename: source is schemas/, URL is /schema/).
  3. Generates _site/index.html + _site/robots.txt.
  4. Runs an audit step that fails the run if _site/ contains anything other than:
    • _site/index.html
    • _site/robots.txt
    • _site/schema/vX.Y.Z/decree-{schema,config}.json
  5. Uploads only _site/ via actions/upload-pages-artifact@v3 (path: _site is an allowlist).

The rest of the repo (README, internal/, docs/, .agents/, etc.) is never exposed at any URL on schemas.opendecree.dev.

Validation

Pre-deploy validation runs three checks:

  1. scripts/validate-meta-schemas.py — same script ci.yml already runs on PRs (reuses CI: validate schema YAMLs against meta-schema #124 work). Asserts canonical files validate cleanly and known-invalid fixtures fail.
  2. $id-matches-publish-URL assertion — for each schemas/v*/decree-{schema,config}.json, parse $id and compare to the URL it'll be served at. Catches the rare stale-rename case.
  3. Audit step described above.

If any of these fail, the run fails before actions/deploy-pages is reached — no broken artifact ever reaches Pages.

⚠️ Bootstrap order — read before merging

The first push to main containing this workflow will trigger a deploy attempt. The deploy will fail with "Pages site not found" (or similar) until:

  1. Cloudflare: add CNAME schemasopendecree.github.io, DNS-only (gray cloud).
  2. decree repo Settings → Pages: Source = GitHub Actions, custom domain = schemas.opendecree.dev. If GitHub asks for a TXT verification record, add it via the same Cloudflare DNS panel.
  3. Wait for cert provisioning (15–60 min). Verify with curl -I https://schemas.opendecree.dev/.

After step 3, re-trigger via gh workflow run deploy-pages.yml. Subsequent pushes to schemas/** auto-deploy.

The runbook documents these steps in detail.

Out of scope

Test plan

  • Workflow YAML parses (python3 -c 'import yaml; yaml.safe_load(...)').
  • make validate-meta-schemas passes locally on main HEAD.
  • Smoke-tested the _site/ build + audit logic locally — produces 4 files, all on the allowlist.
  • Smoke-tested the $id-vs-URL check — both v0.1.0 files match.
  • Smoke-tested scripts/generate-schema-index.py — produces a valid HTML page listing v0.1.0.
  • Cert provisions, curl -I https://schemas.opendecree.dev/ returns 200 (post-merge, after manual setup).
  • First successful auto-deploy run after a schemas/** edit (post-merge).

Adds the GitHub Pages deploy workflow that serves the JSON Schema
2020-12 meta-schemas under schemas/v*/ at
https://schemas.opendecree.dev/schema/v*/decree-{schema,config}.json,
plus the supporting index generator and an operations runbook.

The workflow uses the explicit-allowlist publishing model: it builds
_site/ from scratch, copies only the JSON files, runs an audit step
that fails on unrecognized paths, and uploads exactly _site/ as the
Pages artifact. The rest of the repo is not exposed.

Pre-deploy validation reuses scripts/validate-meta-schemas.py (the
same script ci.yml runs on PRs) and adds a $id-matches-publish-URL
assertion so a stale rename can't slip through.

Bootstrap requires Cloudflare CNAME schemas → opendecree.github.io
(DNS-only) and Pages source = GitHub Actions with custom domain
schemas.opendecree.dev. Steps are documented in
docs/development/schemas-hosting-runbook.md. The first push that
includes this workflow will trigger an attempt to deploy; until
Pages is configured, configure-pages will fail, which is expected
and harmless — re-dispatch via workflow_dispatch after setup.

Closes #125
@zeevdr zeevdr merged commit 41c315d into main Apr 29, 2026
20 checks passed
@zeevdr zeevdr deleted the feat/pages-publish-meta-schemas branch April 29, 2026 13:15
@zeevdr zeevdr added enhancement New feature or request infra Docker, Helm, deployment size: M Moderate — a day or two, clear scope priority: P0 Blocks alpha or release labels May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request infra Docker, Helm, deployment priority: P0 Blocks alpha or release size: M Moderate — a day or two, clear scope

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish meta-schema at schemas.opendecree.io

1 participant