Skip to content

Sync SchemaStore

Sync SchemaStore #211

name: Sync SchemaStore
on:
# Run after successful release
workflow_run:
workflows: ["Release"]
types:
- completed
# Manual trigger for testing
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run mode (compare only, no PR)'
required: false
default: false
type: boolean
permissions:
contents: read
jobs:
sync:
name: Sync schema to SchemaStore
runs-on: ubuntu-latest
# Only run if release succeeded (or manual trigger)
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout rumdl
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Fetch SchemaStore schema
id: fetch
run: |
# Fetch current SchemaStore schema
curl -s https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/rumdl.json > schemastore-current.json
# Check if fetch succeeded
if [ ! -s schemastore-current.json ]; then
echo "Failed to fetch SchemaStore schema"
exit 1
fi
echo "Fetched SchemaStore schema"
- name: Generate SchemaStore-compatible schema
run: |
# Convert local schema to SchemaStore format:
# - Use draft-07 (SchemaStore standard)
# - Use "definitions" instead of "$defs"
# - Set proper $id
jq '
# Convert $defs to definitions
if has("$defs") then
.definitions = .["$defs"] | del(.["$defs"])
else
.
end |
# Update $ref paths
walk(if type == "string" and startswith("#/$defs/") then sub("#/\\$defs/"; "#/definitions/") else . end) |
# Remove non-standard "format" fields (e.g., "uint" from schemars)
walk(if type == "object" and .format == "uint" then del(.format) else . end) |
# Set SchemaStore metadata
.["$schema"] = "http://json-schema.org/draft-07/schema#" |
.["$id"] = "https://json.schemastore.org/rumdl.json"
' rumdl.schema.json > rumdl-schemastore.json
echo "Generated SchemaStore-compatible schema"
- name: Compare schemas
id: compare
run: |
# Compare converted local schema with SchemaStore (both now in same format)
LOCAL_FLAVORS=$(jq -r '.definitions.MarkdownFlavor.enum | sort | join(",")' rumdl-schemastore.json)
REMOTE_FLAVORS=$(jq -r '.definitions.MarkdownFlavor.enum | sort | join(",")' schemastore-current.json)
echo "Local flavors: $LOCAL_FLAVORS"
echo "Remote flavors: $REMOTE_FLAVORS"
# Normalize both for comparison (sorted keys, ignore whitespace)
jq -S '.' rumdl-schemastore.json > local-normalized.json
jq -S '.' schemastore-current.json > remote-normalized.json
if diff -q local-normalized.json remote-normalized.json > /dev/null 2>&1; then
echo "schemas_match=true" >> "$GITHUB_OUTPUT"
echo "✅ Schemas are in sync"
else
echo "schemas_match=false" >> "$GITHUB_OUTPUT"
echo "❌ Schemas differ"
echo ""
echo "=== Key differences ==="
# Show flavor differences specifically
echo "Flavor differences:"
diff <(jq -r '.definitions.MarkdownFlavor.enum[]' schemastore-current.json | sort) \
<(jq -r '.definitions.MarkdownFlavor.enum[]' rumdl-schemastore.json | sort) || true
fi
- name: Create PR to SchemaStore
if: steps.compare.outputs.schemas_match == 'false' && inputs.dry_run != true
env:
GH_TOKEN: ${{ secrets.SCHEMASTORE_PAT }}
run: |
set -euo pipefail
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
BRANCH="rumdl-schema-update"
# Check for existing PR (to decide whether to create one later)
EXISTING_PR_NUM=$(gh pr list --repo SchemaStore/schemastore --author rvben --head "rvben:${BRANCH}" --state open --json number --jq '.[0].number // empty')
# Clone upstream directly. The fork (rvben/schemastore) is only the PR
# head — we push our branch to it but never sync its master, so the bot
# doesn't need the `workflow` scope when upstream changes
# .github/workflows/*.
git clone --depth=1 https://github.com/SchemaStore/schemastore.git schemastore-repo
cd schemastore-repo
git remote add fork "https://x-access-token:${GH_TOKEN}@github.com/rvben/schemastore.git"
git checkout -B "${BRANCH}"
# Install dependencies first (Prettier needs prettier-plugin-sort-json)
npm ci
# Copy schema
cp ../rumdl-schemastore.json src/schemas/json/rumdl.json
# Format with Prettier to match SchemaStore's pre-commit hooks
npx prettier --write src/schemas/json/rumdl.json
# Check for actual changes vs master
if git diff --quiet HEAD -- src/schemas/json/rumdl.json; then
echo "✅ Schema matches master, nothing to do"
exit 0
fi
# Validate schema
echo "Running SchemaStore validation..."
if ! node cli.js check --schema-name=rumdl.json; then
echo "❌ Schema validation failed"
exit 1
fi
echo "✅ Schema validation passed"
# Generate changelog
OLD_FLAVORS=$(jq -r '.definitions.MarkdownFlavor.enum // [] | sort | join(", ")' ../schemastore-current.json)
NEW_FLAVORS=$(jq -r '.definitions.MarkdownFlavor.enum // [] | sort | join(", ")' src/schemas/json/rumdl.json)
CHANGELOG="- Synced with upstream rumdl schema"
if [ "$OLD_FLAVORS" != "$NEW_FLAVORS" ]; then
CHANGELOG="- Updated MarkdownFlavor enum: \`${NEW_FLAVORS}\`"
fi
# Commit and push
git add src/schemas/json/rumdl.json
git commit -m "feat(rumdl): update schema to v${VERSION}"
git push fork "${BRANCH}" --force
# Create PR only if none exists
if [ -n "$EXISTING_PR_NUM" ]; then
echo "✅ Updated existing PR #${EXISTING_PR_NUM}"
exit 0
fi
PR_BODY="Updates the rumdl JSON schema to v${VERSION}.
## Changes
${CHANGELOG}
## Validation
- Schema passes \`node cli.js check --schema-name=rumdl.json\`
## Source
- Schema source: https://github.com/rvben/rumdl/blob/main/rumdl.schema.json
- Release: https://github.com/rvben/rumdl/releases/tag/v${VERSION}
---
*This PR was automatically generated by the [rumdl release workflow](https://github.com/rvben/rumdl/blob/main/.github/workflows/sync-schemastore.yml).*"
gh pr create \
--repo SchemaStore/schemastore \
--head "rvben:${BRANCH}" \
--title "feat(rumdl): update schema to v${VERSION}" \
--body "$PR_BODY"
echo "✅ Created PR to SchemaStore"
- name: Dry run summary
if: steps.compare.outputs.schemas_match == 'false' && inputs.dry_run == true
run: |
echo "## 🧪 Dry Run Summary"
echo ""
echo "Would create PR to SchemaStore with:"
echo ""
echo "### Schema changes:"
diff schemastore-current.json rumdl-schemastore.json || true
echo ""
echo "To create the PR, run this workflow without dry_run mode."
- name: Already in sync
if: steps.compare.outputs.schemas_match == 'true'
run: |
echo "✅ SchemaStore is already in sync with local schema"
echo "No action needed."