Schema Validation #6
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: 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 |