Skip to content

Schema Validation

Schema Validation #6

name: Schema Validation
# This workflow handles the validation of schemas on pull requests.
# It ensures schemas are correct before they can be merged to the main branch.
# The actual deployment happens in the schema-deployment.yml workflow after merging.
on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- schema-updates
paths:
- 'package/v*/**'
- 'registry/v*/**'
- '.github/workflows/schema-validation.yml'
workflow_dispatch: # Allows manual triggering of the workflow
inputs:
force:
description: 'Force validation even if no changes detected'
type: boolean
required: true
default: false
pkg_schema_version:
description: 'Package schema version'
type: string
required: false
default: 'v1'
registry_schema_version:
description: 'Registry schema version'
type: string
required: false
default: 'v1'
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
pkg_versions: ${{ steps.extract-versions.outputs.pkg_versions }}
registry_versions: ${{ steps.extract-versions.outputs.registry_versions }}
highest_pkg_version: ${{ steps.extract-versions.outputs.highest_pkg_version }}
highest_registry_version: ${{ steps.extract-versions.outputs.highest_registry_version }}
has_changes: ${{ steps.extract-versions.outputs.has_changes }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
files: |
package/v*/**
registry/v*/**
- name: Extract versions from changed files
id: extract-versions
run: |
# Handle workflow_dispatch with force
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.force }}" == "true" ]]; then
echo "pkg_versions=[\"${{ github.event.inputs.pkg_schema_version }}\"]" >> $GITHUB_OUTPUT
echo "registry_versions=[\"${{ github.event.inputs.registry_schema_version }}\"]" >> $GITHUB_OUTPUT
echo "highest_pkg_version=${{ github.event.inputs.pkg_schema_version }}" >> $GITHUB_OUTPUT
echo "highest_registry_version=${{ github.event.inputs.registry_schema_version }}" >> $GITHUB_OUTPUT
echo "has_changes=true" >> $GITHUB_OUTPUT
exit 0
fi
# Use tj-actions/changed-files to get versions
changed_files="${{ steps.changed-files.outputs.all_changed_files }}"
# Check if we have any changes
if [[ -z "$changed_files" ]]; then
echo "No changes detected in package or registry schemas."
echo "pkg_versions=[]" >> $GITHUB_OUTPUT
echo "registry_versions=[]" >> $GITHUB_OUTPUT
echo "highest_pkg_version=" >> $GITHUB_OUTPUT
echo "highest_registry_version=" >> $GITHUB_OUTPUT
echo "has_changes=false" >> $GITHUB_OUTPUT
exit 0
fi
# Extract unique versions using simple regex
pkg_versions=$(echo "$changed_files" | grep -oE 'package/v[0-9]+(\.[0-9]+)*' | cut -d'/' -f2 | sort -u | jq -R . | jq -s .)
registry_versions=$(echo "$changed_files" | grep -oE 'registry/v[0-9]+(\.[0-9]+)*' | cut -d'/' -f2 | sort -u | jq -R . | jq -s .)
# Handle empty arrays
if [[ "$pkg_versions" == "[null]" ]]; then pkg_versions="[]"; fi
if [[ "$registry_versions" == "[null]" ]]; then registry_versions="[]"; fi
# Find highest versions
highest_pkg=$(echo "$pkg_versions" | jq -r '.[]' | sort -V | tail -n1)
highest_registry=$(echo "$registry_versions" | jq -r '.[]' | sort -V | tail -n1)
# Set outputs
echo "pkg_versions=$pkg_versions" >> $GITHUB_OUTPUT
echo "registry_versions=$registry_versions" >> $GITHUB_OUTPUT
echo "highest_pkg_version=$highest_pkg" >> $GITHUB_OUTPUT
echo "highest_registry_version=$highest_registry" >> $GITHUB_OUTPUT
# Check if we have changes
if [[ "$pkg_versions" != "[]" ]] || [[ "$registry_versions" != "[]" ]]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi
validate-schemas:
if: needs.detect-changes.outputs.has_changes == 'true'
needs: [detect-changes]
runs-on: ubuntu-latest
strategy:
matrix:
schema-type: [package, registry]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js for schema validation
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install AJV for validation
run: npm install -g ajv-cli ajv-formats
- name: Validate schemas
run: |
schema_type="${{ matrix.schema-type }}"
if [[ "$schema_type" == "package" ]]; then
versions='${{ needs.detect-changes.outputs.pkg_versions }}'
file_name="hatch_pkg_metadata_schema.json"
else
versions='${{ needs.detect-changes.outputs.registry_versions }}'
file_name="hatch_all_pkg_metadata_schema.json"
fi
if [[ "$versions" == "[]" ]]; then
echo "No $schema_type schema changes detected, skipping validation"
exit 0
fi
echo "Validating $schema_type schemas for versions: $versions"
for version in $(echo "$versions" | jq -r '.[]'); do
schema_file="$schema_type/$version/$file_name"
if [[ -f "$schema_file" ]]; then
echo "✅ Validating: $schema_file"
if ajv compile -s "$schema_file" --spec=draft7 -c ajv-formats; then
echo "✅ $schema_type schema $version validation successful"
else
echo "❌ $schema_type schema $version validation failed"
exit 1
fi
else
echo "❌ Schema file not found at $schema_file"
exit 1
fi
done
validation-summary:
if: always()
needs: [detect-changes, validate-schemas]
runs-on: ubuntu-latest
steps:
- name: Generate validation summary
run: |
echo "## 📋 Schema Validation Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.detect-changes.outputs.has_changes }}" == "false" ]]; then
echo "### No Changes Detected" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ No schema changes found in this pull request." >> $GITHUB_STEP_SUMMARY
else
echo "### Changes Detected" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.detect-changes.outputs.pkg_versions }}" != "[]" ]]; then
echo "- **Package Schemas**: ${{ needs.detect-changes.outputs.pkg_versions }}" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.detect-changes.outputs.registry_versions }}" != "[]" ]]; then
echo "- **Registry Schemas**: ${{ needs.detect-changes.outputs.registry_versions }}" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Validation Status" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.validate-schemas.result }}" == "success" ]]; then
echo "✅ **All schema validations passed!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "🚀 This pull request is ready for merge. The deployment workflow will automatically create releases when merged to main." >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.validate-schemas.result }}" == "failure" ]]; then
echo "❌ **Schema validation failed!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "🔧 Please review the validation errors above and fix the schema issues before merging." >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.validate-schemas.result }}" == "skipped" ]]; then
echo "⏭️ **Validation skipped** (no changes detected)" >> $GITHUB_STEP_SUMMARY
else
echo "❓ **Validation status unknown**" >> $GITHUB_STEP_SUMMARY
fi
fi