Skip to content

Commit f088c9a

Browse files
committed
JSON Schema validation and URL validation for PRs
1 parent d2f9f8d commit f088c9a

File tree

4 files changed

+74
-7
lines changed

4 files changed

+74
-7
lines changed

.github/workflows/ships-blueprint-json.yml .github/workflows/has-valid-blueprint-json.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Ships a valid Blueprint.json file?
1+
name: Has a valid Blueprint.json file?
22

33
on:
44
pull_request:
@@ -15,6 +15,10 @@ jobs:
1515
run: |
1616
git fetch origin trunk
1717
18+
- name: Install pre-requisites
19+
run: |
20+
pip install -r requirements.txt
21+
1822
- name: Run validate_pr.py
1923
run: |
2024
python validate_pr.py

blueprints/custom-post/blueprint.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
"title": "Custom Post Type: Books",
55
"description": "Blueprint that added a custom post type to playground",
66
"author": "bph",
7-
"categories": ["Content", "CPT"]
7+
"categories": [
8+
"Content",
9+
"CPT"
10+
]
811
},
912
"landingPage": "/wp-admin/",
1013
"steps": [
@@ -28,4 +31,4 @@
2831
"pluginPath": "books/books.php"
2932
}
3033
]
31-
}
34+
}

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests

validate_pr.py

+63-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import os
22
import re
3+
from jsonschema import Draft7Validator, validate, ValidationError
34
import json
45
import sys
6+
import requests
57

68
def validate_blueprints():
9+
errors = []
10+
711
# Get the list of directories touched in the current branch
812
touched_dirs = get_touched_directories()
913

@@ -14,17 +18,71 @@ def validate_blueprints():
1418

1519
# Check if blueprint.json file exists
1620
if not os.path.exists(blueprint_json_path):
17-
print(f"Error: {dir}/{blueprint_json_path} file does not exist in this PR.")
18-
sys.exit(1)
21+
errors.append(f"Error: {dir}/{blueprint_json_path} file does not exist in this PR.")
22+
continue
1923

2024
# Read and validate the JSON file
2125
try:
2226
with open(blueprint_json_path, 'r') as f:
2327
blueprint_json = json.load(f)
2428
except json.JSONDecodeError as e:
25-
print(f"Error: Invalid JSON in {blueprint_json_path}: {str(e)}")
26-
sys.exit(1)
29+
errors.append(f"Error: Invalid JSON in {blueprint_json_path}: {str(e)}")
30+
continue
31+
32+
# Validate the Blueprint against the JSON schema
33+
schema_url = 'https://playground.wordpress.net/blueprint-schema.json'
34+
schema = json.loads(requests.get(schema_url).text)
35+
36+
try:
37+
validate(instance=blueprint_json, schema=schema, cls=Draft7Validator)
38+
except ValidationError as e:
39+
error_path = " > ".join(e.absolute_path)
40+
at_error = f"at {error_path}" if error_path else "at root"
41+
errors.append(
42+
f"Error: {dir}/{blueprint_json_path} does not match the JSON schema.\n"
43+
f"{str(e.message)} {at_error}.\n"
44+
)
45+
continue
46+
47+
# Recursively find all urls in the blueprint.json file
48+
urls = find_urls(blueprint_json)
2749

50+
# Check if the URLs all point to raw.githubusercontent.com/adamziel/blueprints/{CURRENT BRANCH}
51+
urls_valid = True
52+
current_branch = os.popen('git rev-parse --abbrev-ref HEAD').read().strip()
53+
for url in urls:
54+
if not url.startswith('https://') and not url.startswith('http://'):
55+
continue
56+
if not url.startswith(f'https://raw.githubusercontent.com/adamziel/blueprints/{current_branch}/'):
57+
urls_valid = False
58+
errors.append(
59+
f"Error: {dir}/{blueprint_json_path} contains a URL that is not allowed: \n* {url}\n"
60+
f"Since the current branch is {current_branch}, the URL should start with \n* https://raw.githubusercontent.com/adamziel/blueprints/{current_branch}/\n"
61+
"In general, all URLs in the blueprint.json file must start with https://raw.githubusercontent.com/adamziel/blueprints/{CURRENT BRANCH}/"
62+
)
63+
64+
if not urls_valid:
65+
continue
66+
67+
if len(errors):
68+
for error in errors:
69+
print(error)
70+
sys.exit(1)
71+
72+
73+
def find_urls(obj):
74+
urls = []
75+
if isinstance(obj, dict):
76+
for key, value in obj.items():
77+
if key == 'url':
78+
urls.append(value)
79+
urls.extend(find_urls(value))
80+
elif isinstance(obj, list):
81+
for item in obj:
82+
urls.extend(find_urls(item))
83+
return urls
84+
85+
2886

2987
def get_touched_directories():
3088
# Run git diff command to get the list of directories touched in the current branch
@@ -37,5 +95,6 @@ def get_touched_directories():
3795
touched_dirs.add(dir_path)
3896

3997
return touched_dirs
98+
4099
# Call the function to validate blueprints
41100
validate_blueprints()

0 commit comments

Comments
 (0)