Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions .github/workflows/validate-pattern-specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
name: Validate Pattern Specs

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
validate-pattern-specs:
runs-on: ubuntu-latest

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get changed files
id: changed-files
run: |
# New specification files
NEW_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=A -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "new_spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$NEW_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Modified specification files
MODIFIED_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=M -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "modified_spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$MODIFIED_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# All changed specification files
ALL_SPEC_FILES=$(git diff origin/main --name-only --diff-filter=AM -- specifications/pattern-specification/*.md ":(exclude)*dev.md" || true)
echo "spec_files<<EOF" >> $GITHUB_OUTPUT
echo "$ALL_SPEC_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# New schema files
NEW_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=A -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "new_schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$NEW_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Modified schema files
MODIFIED_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=M -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "modified_schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$MODIFIED_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# All changed schema files
ALL_SCHEMA_FILES=$(git diff origin/main --name-only --diff-filter=AM -- specifications/pattern-schema/*.json ":(exclude)*dev.json" || true)
echo "schema_files<<EOF" >> $GITHUB_OUTPUT
echo "$ALL_SCHEMA_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Validate pattern specification files
if: steps.changed-files.outputs.spec_files != ''
run: |
# First, check if any existing specification files were modified (not allowed)
if [ -n "${{ steps.changed-files.outputs.modified_spec_files }}" ]; then
echo "::error::Modifying existing versioned specification files is not allowed. Modified files: ${{ steps.changed-files.outputs.modified_spec_files }}"
exit 1
fi

# Validate new specification files
NEW_SPEC_FILES="${{ steps.changed-files.outputs.new_spec_files }}"
while IFS= read -r file; do
if [ -n "$file" ]; then
# New specification file - validate version consistency
# Extract version once
FILENAME_VERSION=$(echo "$file" | sed -n 's/.*pattern-specification-\([^/]*\)\.md/\1/p')
FILE_VERSION=$(sed -n 's/^version:[[:space:]]*\([^[:space:]]*\).*/\1/p' "$file" | head -1)

# Validate filename vs content version
if [ "$FILENAME_VERSION" != "$FILE_VERSION" ]; then
echo "::error::Specification file name does not match the specification version. Expected: $FILENAME_VERSION, Got: $FILE_VERSION"
exit 1
fi
fi
done <<< "$NEW_SPEC_FILES"

- name: Validate pattern schema files
if: steps.changed-files.outputs.schema_files != ''
run: |
SCHEMA_FILES="${{ steps.changed-files.outputs.schema_files }}"
while IFS= read -r file; do
if [ -n "$file" ]; then
# Skip the latest file to ensure proper validation of $id field
if [[ "$file" == *"pattern-schema-latest.json" ]]; then
continue
fi

# Check if this is a modified existing versioned file (not allowed)
if git show origin/main:$file >/dev/null 2>&1; then
echo "::error::Modifying existing versioned schema files is not allowed. Modified file: $file"
exit 1
fi

# Extract version from filename
VERSION=$(echo "$file" | sed -n 's/.*pattern-schema-\([^/]*\)\.json/\1/p')
if [ -n "$VERSION" ]; then
# Construct expected ID for the new versioned file
EXPECTED_ID="https://raw.githubusercontent.com/ansible/pattern-service/main/specifications/pattern-schema/pattern-schema-${VERSION}.json"

# Validate versioned schema file's $id field
ACTUAL_ID=$(git show HEAD:$file | jq -r '.["$id"] // empty')
if [ "$ACTUAL_ID" != "$EXPECTED_ID" ]; then
echo "::error::Schema file $file has incorrect \$id field. Expected: $EXPECTED_ID, Got: $ACTUAL_ID"
exit 1
fi

# Validate latest schema file $id points to new version
LATEST_ID=$(git show HEAD:specifications/pattern-schema/pattern-schema-latest.json | jq -r '.["$id"] // empty')
if [ "$LATEST_ID" != "$EXPECTED_ID" ]; then
echo "::error::Latest schema file was not updated to point to new version $VERSION. Expected \$id: $EXPECTED_ID, Got: $LATEST_ID"
exit 1
fi
fi
fi
done <<< "$SCHEMA_FILES"