-
Notifications
You must be signed in to change notification settings - Fork 3.6k
167 lines (152 loc) · 6.45 KB
/
Copy pathsite-validate-dev.yml
File metadata and controls
167 lines (152 loc) · 6.45 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
name: '🌐 Landing Site · ✅ Validate (Dev)'
# =============================================================================
# Unified Site — Content & Build Validation
# =============================================================================
#
# Validates the unified mlsysbook.ai landing site (landing + about + community
# + newsletter) before the preview/publish workflows ever touch it.
#
# Flow:
# 1. BUILD_SITE — Quarto render of the unified site
# 2. CHECK_LINKS — Lychee external-link reachability (Tier 2, non-blocking)
# 3. SUMMARY — Aggregate results
#
# Why this exists:
# site-preview-dev.yml jumps straight to building & SSH-deploying. With no
# validation gate the dev preview can land broken. This workflow is the
# missing CI counterpart added as part of the staged-rollout safety net.
#
# Triggers:
# - push: dev branch, site/** or shared/** paths
# - pull_request: site/** or shared/** changes
# - workflow_dispatch: manual
#
# Deploys to: N/A (validate only)
#
# Related:
# - site-preview-dev.yml — Dev preview deploy (gates on this passing)
# - site-publish-live.yml — Production deploy
#
# =============================================================================
on:
workflow_dispatch:
# Reusable: site-preview-dev.yml calls this via `uses:` so the deploy
# job can `needs:` a green validate. Standalone push/PR triggers stay
# so the publish guard and README badge still see direct runs on dev.
workflow_call:
pull_request:
paths:
- 'site/**'
- 'shared/**'
- '.github/workflows/site-validate-dev.yml'
- '.github/workflows/site-preview-dev.yml'
push:
branches: [dev]
paths:
- 'site/**'
- 'shared/**'
- '.github/workflows/site-validate-dev.yml'
- '.github/workflows/site-preview-dev.yml'
permissions:
contents: read
concurrency:
# `head_ref || run_id` keeps PR cancel-on-amend behavior while making
# push and workflow_call runs unique per-run, so a push to dev that
# triggers both this workflow standalone AND Preview's `uses:` call
# doesn't collide on a shared group. See staffml-validate-dev.yml.
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
# ===========================================================================
# Stage 1: Quarto site build
# ===========================================================================
build-site:
name: '🔨 Build Unified Site'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: 📥 Checkout
uses: actions/checkout@v6
- name: 🐍 Setup Python
uses: actions/setup-python@v6
with:
python-version: ${{ vars.PYTHON_VERSION || '3.12' }}
- name: 📬 Install newsletter sync deps (no API call)
run: |
pip install -r site/newsletter/requirements.txt
# We deliberately do NOT pull from Buttondown here — that requires
# a secret and is the deploy workflow's responsibility. We only need
# the deps so Quarto can render the newsletter index.
- name: 🔧 Setup Quarto
uses: quarto-dev/quarto-actions/setup@v2
- name: 🔨 Build Unified Site (HTML)
working-directory: site
env:
# The render's pre-render step (scripts/build_stats.py) queries the
# GitHub API for stars and merged PRs. Unauthenticated, the search
# endpoint allows 10 req/min per IP and Actions runners share IPs, so
# without a token the call intermittently fails and the page silently
# falls back to the committed cache.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# BUTTONDOWN_API_KEY is deliberately absent. This workflow runs on
# pull_request, so a fork PR could read any secret exposed here.
# Without the key the stats step keeps the committed subscriber
# count, which is the correct behaviour for a validation build.
run: quarto render
- name: 🔍 Validate build output
run: |
MISSING=0
for page in index.html about/index.html community/index.html newsletter/index.html; do
if [ ! -f "site/_build/$page" ]; then
echo "❌ MISSING: $page"
MISSING=$((MISSING + 1))
fi
done
if [ "$MISSING" -gt 0 ]; then
echo "❌ $MISSING critical pages missing from build."
exit 1
fi
echo "✅ Site built successfully"
echo "📊 Build size: $(du -sh site/_build | cut -f1)"
echo "📄 Pages: $(find site/_build -name '*.html' | wc -l)"
# ===========================================================================
# Stage 2: Link integrity (Tier 2 — non-blocking baseline)
# ===========================================================================
# Tier 1 pre-commit (shared/scripts/check-internal-links.py) already blocks
# broken internal links + anchors. This Lychee pass adds external
# reachability as a warning. Flip fail_on_broken=true once baseline is clean.
check-links:
name: '🔗 Check Links'
uses: ./.github/workflows/infra-link-check.yml
with:
path_pattern: './site/**/*.qmd'
lycheeignore_path: 'shared/config/.lycheeignore'
fail_on_broken: false
max_concurrency: 8
# ===========================================================================
# Summary
# ===========================================================================
summary:
name: '📊 Summary'
runs-on: ubuntu-latest
needs: [build-site, check-links]
if: always()
steps:
- name: 📊 Generate Summary
run: |
echo "## 🌐 Unified Site Validation Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| 🔨 Site Build (HTML) | ${{ needs.build-site.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| 🔗 Link Check | ${{ needs.check-links.result }} (non-blocking) |" >> $GITHUB_STEP_SUMMARY
- name: ❌ Check for failures
run: |
if [ "${{ needs.build-site.result }}" = "failure" ]; then
echo "❌ Validation failed"
exit 1
fi
if [ "${{ needs.check-links.result }}" = "failure" ]; then
echo "⚠️ Link check found issues (non-blocking)"
fi
echo "✅ Core checks passed"