-
Notifications
You must be signed in to change notification settings - Fork 2
PR: Add robust JSON linting, formatting, and schema validation with CI integration #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,323 @@ | ||
| --- | ||
| name: JSON Linting & Validation | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - develop | ||
| - main | ||
| - 'claude/**' | ||
| paths: | ||
| - '**.json' | ||
| - '!package-lock.json' | ||
| - 'schemas/**/*.schema.json' | ||
| - '.github/workflows/json-validation.yml' | ||
| - 'scripts/json-validation/**' | ||
| pull_request: | ||
| paths: | ||
| - '**.json' | ||
| - '!package-lock.json' | ||
| - 'schemas/**/*.schema.json' | ||
| - '.github/workflows/json-validation.yml' | ||
| - 'scripts/json-validation/**' | ||
| workflow_dispatch: | ||
| inputs: | ||
| glob: | ||
| description: 'Glob pattern for JSON files' | ||
| required: false | ||
| default: '**/*.json' | ||
| schema: | ||
| description: 'Path to schema file (optional)' | ||
| required: false | ||
| read-only: | ||
| description: 'Read-only mode (no file modifications)' | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| format-check: | ||
| name: Format Check (Prettier) | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Check JSON formatting | ||
| run: npx prettier --check "**/*.json" "!package-lock.json" "!**/node_modules/**" | ||
|
|
||
| - name: Generate formatting report | ||
| if: failure() | ||
| run: | | ||
| echo "# JSON Formatting Issues" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "The following files need formatting:" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo '```bash' >> $GITHUB_STEP_SUMMARY | ||
| echo "npx prettier --write \"**/*.json\"" >> $GITHUB_STEP_SUMMARY | ||
| echo '```' >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| syntax-validation: | ||
| name: Syntax Validation | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Validate JSON syntax | ||
| run: node scripts/json-validation/validate-json.js --validate-only --strict --glob "**/*.json" | ||
|
|
||
| - name: Upload syntax errors | ||
| if: failure() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: syntax-errors | ||
| path: reports/jsonlint.log | ||
| retention-days: 7 | ||
|
|
||
| schema-validation: | ||
| name: Schema Validation | ||
| runs-on: ubuntu-latest | ||
| needs: syntax-validation | ||
|
|
||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| validation: | ||
| - name: 'Frontmatter Schema' | ||
| glob: '.github/automation/schemas/frontmatter.schema.json' | ||
| schema: 'https://json-schema.org/draft/2020-12/schema' | ||
| spec: 'draft2020' | ||
| - name: 'CodeRabbit Overrides' | ||
| glob: 'schemas/coderabbit-overrides.v2.json' | ||
| schema: 'https://json-schema.org/draft-07/schema' | ||
| spec: 'draft7' | ||
| - name: 'Metrics Config' | ||
| glob: '.github/metrics/metrics.config.json' | ||
| schema: null | ||
| spec: 'draft2020' | ||
| - name: 'WordPress Schemas' | ||
| glob: 'schemas/wp/*.schema.json' | ||
| schema: 'https://json-schema.org/draft-07/schema' | ||
| spec: 'draft7' | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Validate ${{ matrix.validation.name }} | ||
| if: matrix.validation.schema != null | ||
| run: | | ||
| echo "Validating: ${{ matrix.validation.name }}" | ||
| echo "Glob: ${{ matrix.validation.glob }}" | ||
| echo "Schema: ${{ matrix.validation.schema }}" | ||
| echo "Spec: ${{ matrix.validation.spec }}" | ||
|
|
||
| # Create temporary schema file from URL if needed | ||
| if [[ "${{ matrix.validation.schema }}" == http* ]]; then | ||
| curl -s "${{ matrix.validation.schema }}" > /tmp/schema.json | ||
| SCHEMA_PATH="/tmp/schema.json" | ||
| else | ||
| SCHEMA_PATH="${{ matrix.validation.schema }}" | ||
| fi | ||
|
|
||
| # Run validation | ||
| node scripts/json-validation/validate-json.js \ | ||
| --glob "${{ matrix.validation.glob }}" \ | ||
| --schema "$SCHEMA_PATH" \ | ||
| --spec "${{ matrix.validation.spec }}" \ | ||
| --validate-only \ | ||
| --errors json | ||
|
|
||
| - name: Syntax-only validation for ${{ matrix.validation.name }} | ||
| if: matrix.validation.schema == null | ||
| run: | | ||
| echo "Syntax-only validation for: ${{ matrix.validation.name }}" | ||
| node scripts/json-validation/validate-json.js \ | ||
| --glob "${{ matrix.validation.glob }}" \ | ||
| --validate-only \ | ||
| --strict | ||
|
|
||
| - name: Upload validation errors | ||
| if: failure() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: schema-errors-${{ matrix.validation.name }} | ||
| path: reports/ | ||
| retention-days: 7 | ||
|
|
||
| validate-changed-files: | ||
| name: Validate Changed Files (PR) | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Get changed JSON files | ||
| id: changed-files | ||
| uses: tj-actions/changed-files@v46 | ||
| with: | ||
| files: | | ||
| **.json | ||
| files_ignore: | | ||
| package-lock.json | ||
| **/node_modules/** | ||
|
|
||
| - name: Format and validate changed files | ||
| if: steps.changed-files.outputs.any_changed == 'true' | ||
| run: | | ||
| echo "Changed JSON files:" | ||
| echo "${{ steps.changed-files.outputs.all_changed_files }}" | ||
|
|
||
| # Create temp file list | ||
| echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' > /tmp/changed-files.txt | ||
|
|
||
| # Format check | ||
| echo "Checking formatting..." | ||
| npx prettier --check $(cat /tmp/changed-files.txt | tr '\n' ' ') | ||
|
|
||
| # Validate syntax | ||
| echo "Validating syntax..." | ||
| while IFS= read -r file; do | ||
| echo "Checking: $file" | ||
| node -e "JSON.parse(require('fs').readFileSync('$file', 'utf8'))" || exit 1 | ||
| done < /tmp/changed-files.txt | ||
|
|
||
|
Comment on lines
+202
to
+231
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainChanged-files Prettier check is the direct cause of the reported Prettier/ESM pipeline failure In - name: Format check
run: |
echo "Checking formatting..."
npx prettier --check $(cat /tmp/changed-files.txt | tr '\n' ' ')The pipeline error you shared:
comes from this To make this step robust and consistent with your JSON validator script:
- npx prettier --check $(cat /tmp/changed-files.txt | tr '\n' ' ')
+ npx prettier --check --no-config $(cat /tmp/changed-files.txt | tr '\n' ' ')
- # Validate syntax
- echo "Validating syntax..."
- while IFS= read -r file; do
- echo "Checking: $file"
- node -e "JSON.parse(require('fs').readFileSync('$file', 'utf8'))" || exit 1
- done < /tmp/changed-files.txt
+ # Validate syntax using the shared JSON validation script
+ echo "Validating syntax..."
+ node scripts/json-validation/validate-json.js --validate-only --strict --glob "$(tr '\n' ' ' < /tmp/changed-files.txt)"This should resolve the current Prettier config/ESM failure and centralize JSON syntax checks in one place. Please re-run the “JSON Linting & Validation” workflow on a PR with changed JSON files after adding I'll verify the review comment by examining the workflow file, prettier configuration, and the referenced validation script. Length of output: 5544 Length of output: 14099 Add The Prettier invocation fails because - npx prettier --check $(cat /tmp/changed-files.txt | tr '\n' ' ')
+ npx prettier --check --no-config $(cat /tmp/changed-files.txt | tr '\n' ' ')This resolves the config loading error while keeping Prettier's formatting rules applied to JSON files only (which is safe for JSON-only validation). 🤖 Prompt for AI Agents |
||
| - name: Comment on PR | ||
| if: failure() && github.event_name == 'pull_request' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| github.rest.issues.createComment({ | ||
| issue_number: context.issue.number, | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| body: `⚠️ **JSON validation failed** | ||
|
|
||
| Please ensure all JSON files are: | ||
| 1. Properly formatted (run \`npm run format:json\`) | ||
| 2. Valid syntax | ||
| 3. Schema-compliant (if applicable) | ||
|
|
||
| See workflow logs for details. | ||
|
|
||
| ## Quick fix commands: | ||
| \`\`\`bash | ||
| # Format all JSON files | ||
| npx prettier --write "**/*.json" | ||
|
|
||
| # Validate specific file | ||
| node scripts/json-validation/validate-json.js --glob "path/to/file.json" | ||
| \`\`\` | ||
|
|
||
| See [JSON Validation Documentation](https://github.com/lightspeedwp/.github/blob/develop/scripts/json-validation/README.md) for more details.` | ||
| }) | ||
|
|
||
| comprehensive-validation: | ||
| name: Comprehensive Validation | ||
| runs-on: ubuntu-latest | ||
| needs: [format-check, syntax-validation] | ||
| if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/develop' | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Run comprehensive validation | ||
| run: | | ||
| GLOB="${{ github.event.inputs.glob || '**/*.json' }}" | ||
| SCHEMA="${{ github.event.inputs.schema || '' }}" | ||
| READONLY="${{ github.event.inputs.read-only || 'false' }}" | ||
|
|
||
| CMD="node scripts/json-validation/validate-json.js --glob \"$GLOB\" --strict" | ||
|
|
||
| if [ "$READONLY" = "true" ]; then | ||
| CMD="$CMD --read-only" | ||
| fi | ||
|
|
||
| if [ -n "$SCHEMA" ]; then | ||
| CMD="$CMD --schema \"$SCHEMA\"" | ||
| fi | ||
|
|
||
| echo "Running: $CMD" | ||
| eval $CMD | ||
|
|
||
| - name: Upload validation report | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: validation-report | ||
| path: reports/ | ||
| retention-days: 30 | ||
|
|
||
| - name: Generate summary | ||
| if: always() | ||
| run: | | ||
| echo "# Comprehensive JSON Validation Report" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "**Glob pattern:** \`${{ github.event.inputs.glob || '**/*.json' }}\`" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| if [ -f "reports/ajv-errors.txt" ]; then | ||
| echo "## Validation Errors" >> $GITHUB_STEP_SUMMARY | ||
| echo '```' >> $GITHUB_STEP_SUMMARY | ||
| head -n 50 reports/ajv-errors.txt >> $GITHUB_STEP_SUMMARY | ||
| echo '```' >> $GITHUB_STEP_SUMMARY | ||
| else | ||
| echo "✅ All validations passed!" >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Prettier format-check is likely affected by the ESM/CommonJS config issue
The
format-checkjob runs:Given
"type": "module"inpackage.jsonand the reported error aboutrequirenot being defined in ESM scope during JSON validation, Prettier is probably loading a JS config that still usesmodule.exports/require, causing failures. (prettier.io)Since your JSON validator script already uses
--no-configto avoid these config issues for JSON, you can mirror that here:That keeps the JSON formatting check stable even if the main Prettier config remains CommonJS-oriented.
After adding
--no-config, please re-run the workflow to confirm the format-check job no longer fails due to the Prettier config; if you prefer using the shared config, you’ll instead need to convert it to an ESM-compatible form per Prettier’s configuration docs. (prettier.io)Length of output: 429
🏁 Script executed:
Length of output: 24843
🏁 Script executed:
Length of output: 4383
Add
--no-configto Prettier invocations to resolve ESM/CommonJS config conflictThe prettier.config.js uses CommonJS (
require(),module.exports) while package.json specifies"type": "module"(ESM). When Prettier runs without--no-config, it attempts to load the CommonJS config in an ESM context, causing failures. Your validate-json.js script already handles this correctly with--no-config.Add the flag to both Prettier calls in this workflow:
Line 61 (format-check job):
Line 223 (validate-changed-files job):
Alternatively, convert prettier.config.js to ESM syntax (import/export) to align with your module setup.
🤖 Prompt for AI Agents