Repository navigation
221 lines (191 loc) · 8.82 KB
/
Copy pathdocs.yml
File metadata and controls
221 lines (191 loc) · 8.82 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
name: docs
# The family documentation site.
# One site for five packages: this repository holds it, and the API reference
# is reflected out of all five `src/` trees at build time.
#
# Pull requests build and check but never deploy. `master` deploys. The
# reference documents the satellites at the versions
# `docs/.api-workspace/composer.lock` holds — a caret on 0.x pins a minor, so
# the lock moves in the release PR that follows a satellite release, and the
# `composer outdated` step below turns a lock left behind into a red build
# rather than a site that quietly documents a version three minors old (which
# is what happened between 2026-08-28 and 2026-09-05).
on:
pull_request:
paths: &paths
- 'docs/**'
- 'examples/case-studies/**'
- 'perf/**'
- 'src/**'
- 'perf/README.md'
- 'llms.txt'
- 'README.md'
- 'README.ru.md'
- 'MIGRATION.md'
- '.vale.ini'
- '.github/workflows/docs.yml'
push:
branches:
- master
paths: *paths
# The weekly run re-reads the lock, so a satellite release nobody pinned is
# reported within a week even when nothing here changed.
schedule:
- cron: '41 5 * * 1' # Mondays, 05:41 UTC
workflow_dispatch:
permissions:
contents: read
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Full history and tags: the API pages are stamped with `git
# describe`, which sees neither at the default depth of 1.
fetch-depth: 0
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: '8.4'
coverage: none
extensions: tokenizer
tools: composer:v2
- name: Cache Composer dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.composer/cache
key: composer-${{ runner.os }}-${{ hashFiles('**/composer.json') }}
restore-keys: composer-${{ runner.os }}-
# Needed by the case studies, which run against this checkout's engine.
- name: Install PHP dependencies
run: composer install --no-interaction --no-progress --prefer-dist
# docs/.api-workspace is NOT part of composer.json: the engine must
# never require its own satellites (`composer why testo/testo` stays
# empty for an engine-only install). It installs all four from their
# published tags next to a path repository on this checkout, so one
# autoloader covers all five src/ trees.
- name: Install the API reflection workspace
working-directory: docs/.api-workspace
run: composer install --no-interaction --no-progress
# A satellite with a release the pins do not reach is documented at the
# wrong version, silently. `--direct` looks at the four satellites only
# (and the docblock parser, ignored), `--strict` makes it a red build.
- name: Refuse a workspace that documents a satellite behind its release
working-directory: docs/.api-workspace
run: composer outdated --direct --strict --ignore phpdocumentor/reflection-docblock
# What every engine reference page is stamped with. On a tagged commit
# `git describe` prints the tag; between releases it prints the nearest
# tag plus the commit, so a page built from master still says which
# commit it describes. Without this the pages say "working tree", which
# is true locally and meaningless once published.
- name: Resolve the engine version for the API pages
id: engine-version
run: echo "version=$(git describe --tags --always)" >> "$GITHUB_OUTPUT"
- name: Refresh the API reflection snapshot
env:
DOCS_UNDERSTUDY_VERSION: ${{ steps.engine-version.outputs.version }}
run: php docs/scripts/reflect-api.php > docs/scripts/api-snapshot.json
# The analyser packages have no @api class — their contract is the set
# of identifiers they report — so /api/rules comes from its own
# reflector over extension.neon and the installed sources.
- name: Refresh the analyser rules snapshot
run: php docs/scripts/reflect-rules.php > docs/scripts/rules-snapshot.json
# A deliberate non-check: the refreshed snapshots are NOT compared
# against the committed ones. Satellite versions come from Packagist, so
# a satellite release legitimately changes them with no commit in this
# repository — a drift check would turn every satellite release into a
# red master here.
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: npm
cache-dependency-path: docs/package-lock.json
- name: Install docs dependencies
working-directory: docs
run: npm ci
- name: Build docs (drafts + API pages + MIGRATION.md + integrity + VitePress + anchors)
working-directory: docs
run: npm run docs:build
# Separate step, and after the build: it needs PHP, and its failure
# ("the page quotes output the script no longer produces") is a content
# problem, not a build problem — the distinction is worth one glance at
# the job summary.
# Two content checks, both needing PHP, both after the build for the same
# reason: their failure ("the page says something the code does not do")
# is a content problem, not a build problem.
- name: Verify the guide's claims against the engine
run: php docs/scripts/check-claims.php
- name: Verify cookbook case studies reproduce their quoted output
run: node docs/scripts/check-cookbook.mjs
# Skipped on pull requests: `deploy` is skipped there too, so nothing
# consumes the artifact — and both steps call the Pages API, which does
# not exist until Pages is switched on for the repository. A PR must
# not depend on that.
- name: Setup Pages
if: github.event_name != 'pull_request'
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Upload artifact
if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: docs/src/.vitepress/dist
prose:
name: Prose
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Vale ships as a single binary. Downloaded with a pinned version and a
# pinned checksum rather than through a third-party action: the action
# route wants a token and `pull-requests: write` for its annotations,
# and the two lines of `::error` below produce the same annotations with
# no write permission anywhere in this workflow.
- name: Install Vale
env:
VALE_VERSION: 3.9.1
VALE_SHA256: fbc2eb47d0b8c50220ed1a2c5c611fbe0904ed567d638143d482016a18fd2db0
run: |
curl -fsSL -o vale.tar.gz \
"https://github.com/errata-ai/vale/releases/download/v${VALE_VERSION}/vale_${VALE_VERSION}_Linux_64-bit.tar.gz"
echo "${VALE_SHA256} vale.tar.gz" | sha256sum --check --strict
tar -xzf vale.tar.gz vale
sudo install -m 0755 vale /usr/local/bin/vale
rm vale vale.tar.gz
- name: Sync Vale styles
run: vale sync
# Hand-written sections only: docs/src/api/** is generated from
# docblocks and a prose linter on it reports nothing fixable on the
# site (plan §7).
- name: Lint prose
run: |
vale --output=JSON docs/src/index.md docs/src/guide docs/src/cookbook docs/src/adapters > vale.json || true
jq -r 'to_entries[] | .key as $file | .value[]
| "::error file=\($file),line=\(.Line),col=\(.Span[0])::\(.Check): \(.Message)"' vale.json
found=$(jq 'to_entries | map(.value | length) | add // 0' vale.json)
echo "Vale findings: $found"
test "$found" -eq 0
deploy:
name: Deploy
needs: [build, prose]
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
pages: write # publish the built site to GitHub Pages
id-token: write # required by actions/deploy-pages for OIDC Pages deployment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1