Sync SchemaStore #211
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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." |