-
Notifications
You must be signed in to change notification settings - Fork 0
141 lines (123 loc) · 4.33 KB
/
Copy pathvalidate-content.yml
File metadata and controls
141 lines (123 loc) · 4.33 KB
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
name: validate-content
on:
push:
branches: ['**']
pull_request:
branches: ['**']
jobs:
validate:
name: Validate blog frontmatter, JSON, and build scripts
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Python deps
run: pip install pyyaml
- name: Validate blog frontmatter
run: |
python3 - <<'PY'
import pathlib, sys, yaml
REQUIRED = {"title", "date", "category", "excerpt"}
blog_dir = pathlib.Path("website/assets/blog")
if not blog_dir.exists():
print(f"::warning::{blog_dir} not found, skipping")
sys.exit(0)
posts = sorted(blog_dir.glob("*.md"))
if not posts:
print(f"::warning::No posts found in {blog_dir}")
sys.exit(0)
errors = []
categories = set()
for p in posts:
text = p.read_text(encoding="utf-8")
if not text.startswith("---"):
errors.append(f"{p.name}: missing frontmatter")
continue
try:
_, fm, _ = text.split("---", 2)
except ValueError:
errors.append(f"{p.name}: malformed frontmatter delimiters")
continue
try:
data = yaml.safe_load(fm) or {}
except yaml.YAMLError as e:
errors.append(f"{p.name}: YAML parse error: {e}")
continue
missing = REQUIRED - set(data.keys())
if missing:
errors.append(f"{p.name}: missing required fields: {sorted(missing)}")
continue
if data.get("category"):
categories.add(str(data["category"]))
if errors:
for e in errors:
print(f"::error::{e}")
sys.exit(1)
print(f"OK: {len(posts)} posts, {len(categories)} categories")
PY
- name: Validate JSON data files
run: |
python3 - <<'PY'
import json, pathlib, sys
roots = [
pathlib.Path("website/assets/data"),
pathlib.Path("website/assets/data/pages"),
]
errors = []
count = 0
for root in roots:
if not root.exists():
continue
for jf in sorted(root.glob("*.json")):
count += 1
try:
json.loads(jf.read_text(encoding="utf-8"))
except json.JSONDecodeError as e:
errors.append(f"{jf}: {e}")
if errors:
for e in errors:
print(f"::error::{e}")
sys.exit(1)
print(f"OK: {count} JSON files parsed cleanly")
PY
- name: Set up Node 20
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Dry-run build-blog-index
run: |
if [ -f website/scripts/build-blog-index.py ]; then
python3 website/scripts/build-blog-index.py
else
echo "::warning::website/scripts/build-blog-index.py not found"
fi
- name: Dry-run build-sitemap
run: |
if [ -f website/scripts/build-sitemap.py ]; then
python3 website/scripts/build-sitemap.py
else
echo "::warning::website/scripts/build-sitemap.py not found"
fi
- name: Summary
run: |
python3 - <<'PY'
import json, pathlib
posts = list(pathlib.Path("website/assets/blog").glob("*.md")) \
if pathlib.Path("website/assets/blog").exists() else []
idx = pathlib.Path("website/assets/blog/index.json")
cats = []
if idx.exists():
try:
data = json.loads(idx.read_text(encoding="utf-8"))
cats = data.get("categories", [])
except Exception:
pass
pages = list(pathlib.Path("website").glob("*.html"))
print(f"Posts: {len(posts)}")
print(f"Categories: {len(cats)}")
print(f"Pages: {len(pages)}")
PY