-
Notifications
You must be signed in to change notification settings - Fork 30
/
validate_pr.py
101 lines (82 loc) · 3.72 KB
/
validate_pr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import os
import re
from jsonschema import Draft7Validator, validate, ValidationError
import json
import sys
import requests
def validate_blueprints():
errors = []
# Get the list of directories touched in the current branch
touched_dirs = get_touched_directories()
for dir in touched_dirs:
if not re.match(r'^blueprints/[^/]+$', dir):
continue
blueprint_json_path = os.path.join(dir, 'blueprint.json')
# Check if blueprint.json file exists
if not os.path.exists(blueprint_json_path):
errors.append(f"Error: {dir}/{blueprint_json_path} file does not exist in this PR.")
continue
# Read and validate the JSON file
try:
with open(blueprint_json_path, 'r') as f:
blueprint_json = json.load(f)
except json.JSONDecodeError as e:
errors.append(f"Error: Invalid JSON in {blueprint_json_path}: {str(e)}")
continue
# Validate the Blueprint against the JSON schema
schema_url = 'https://playground.wordpress.net/blueprint-schema.json'
schema = json.loads(requests.get(schema_url).text)
try:
validate(instance=blueprint_json, schema=schema, cls=Draft7Validator)
except ValidationError as e:
error_path = " > ".join(e.absolute_path)
at_error = f"at {error_path}" if error_path else "at root"
errors.append(
f"Error: {dir}/{blueprint_json_path} does not match the JSON schema.\n"
f"{str(e.message)} {at_error}.\n"
)
continue
# Recursively find all urls in the blueprint.json file
urls = find_urls(blueprint_json)
# Check if the URLs all point to raw.githubusercontent.com/wordpress/blueprints/{CURRENT BRANCH}
urls_valid = True
current_branch = os.environ.get('GITHUB_BRANCH') or os.popen('git rev-parse --abbrev-ref HEAD').read().strip()
for url in urls:
if not url.startswith('https://') and not url.startswith('http://'):
continue
if not url.startswith(f'https://raw.githubusercontent.com/wordpress/blueprints/{current_branch}/'):
urls_valid = False
errors.append(
f"Error: {dir}/{blueprint_json_path} contains a URL that is not allowed: \n* {url}\n"
f"Since the current branch is {current_branch}, the URL should start with \n* https://raw.githubusercontent.com/wordpress/blueprints/{current_branch}/\n"
"In general, all URLs in the blueprint.json file must start with https://raw.githubusercontent.com/wordpress/blueprints/{CURRENT BRANCH}/"
)
if not urls_valid:
continue
if len(errors):
for error in errors:
print(error)
sys.exit(1)
def find_urls(obj):
urls = []
if isinstance(obj, dict):
for key, value in obj.items():
if key == 'url':
urls.append(value)
urls.extend(find_urls(value))
elif isinstance(obj, list):
for item in obj:
urls.extend(find_urls(item))
return urls
def get_touched_directories():
# Run git diff command to get the list of directories touched in the current branch as compared to
# the point where it was forked from the trunk branch
diff_output = os.popen('git diff --name-only $(git merge-base trunk HEAD)').read()
touched_dirs = set()
# Extract the directory paths from the diff output
for line in diff_output.splitlines():
dir_path = os.path.dirname(line)
touched_dirs.add(dir_path)
return touched_dirs
# Call the function to validate blueprints
validate_blueprints()