-
Notifications
You must be signed in to change notification settings - Fork 3
227 lines (204 loc) · 8.14 KB
/
Copy pathdocs.yml
File metadata and controls
227 lines (204 loc) · 8.14 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
222
223
224
225
226
227
name: Docs
# Deploy the Astro docs site at `docs/` to GitHub Pages.
#
# Behaviour:
# - Push to `main` → build with PPVM_BASE=/ and publish
# to the gh-pages branch root.
# - Pull request (opened / → build with PPVM_BASE=/pr-preview/pr-<N>
# synchronize / reopened) and let rossjrw/pr-preview-action publish
# the build to gh-pages under
# `pr-preview/pr-<N>/`. Triggered only when
# the diff actually touches inputs the
# site depends on.
# - Pull request closed → cleanup-preview job removes the
# `pr-preview/pr-<N>/` subdirectory.
#
# The Rust API site under `/rust-api/` is published by `rust-docs.yml`
# and survives our deploys via `keep_files: true`.
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened]
paths:
# Site sources, the Rust workspace (consumed by the API JSON
# extractor), and the Python package (consumed by the notebook
# build step + the Python API extractor).
- "docs/**"
- "crates/**"
- "ppvm-python/**"
- ".github/workflows/docs.yml"
pull_request_target:
types: [closed]
# No workflow-wide write privileges. Each job declares the narrowest
# token scope it actually needs. The `build` job executes user-controlled
# notebooks via `npm run extract:notebooks`, so its token must not be
# able to push to `gh-pages` (or anything else). Deploys run on
# separately-scoped jobs that don't see the notebook execution context.
permissions:
contents: read
concurrency:
# Serialise per-PR (and main); a fresh build cancels any in-flight one
# for the same ref so PR comments don't pile up on rapid pushes.
group: docs-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
# Build the static site once, upload it as an artifact, and let the
# downstream jobs decide where (if anywhere) to publish it.
if: github.event.action != 'closed'
name: Build Astro site
runs-on: ubuntu-latest
# Notebook execution runs arbitrary repo-controlled Python here;
# the token in this job stays read-only so a malicious PR can't
# exfiltrate it into a gh-pages write.
permissions:
contents: read
outputs:
base: ${{ steps.compute-base.outputs.base }}
steps:
- uses: actions/checkout@v4
# Build inputs: nightly Rust for the rustdoc-JSON extractor,
# uv to run griffe for the Python extractor, Node 22 for Astro.
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
- uses: astral-sh/setup-uv@v5
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
cache-dependency-path: docs/package-lock.json
- name: Restore executed-notebook cache
# Reuses already-executed notebook HTML across runs. The key
# mirrors what `build-notebooks.py` hashes per-notebook: every
# Jupytext source + the lockfiles + every Cargo.toml. If any
# of those change, the cache misses and the build script
# re-executes the affected notebooks (still reusing the
# unchanged ones via the per-notebook content hash). The
# `restore-keys` fallback gives us a partial hit when *some*
# of those inputs change — the script then re-executes only
# the notebooks whose fingerprint no longer matches.
uses: actions/cache@v4
with:
path: docs/.notebook-cache
key: notebooks-v1-${{ hashFiles('docs/notebooks/**/*.py', 'docs/scripts/build-notebooks.py', 'Cargo.lock', 'Cargo.toml', 'crates/*/Cargo.toml', 'ppvm-python/uv.lock') }}
restore-keys: |
notebooks-v1-
- name: Install Astro deps
# `npm ci` is faster than `npm install` and asserts the
# lockfile is in sync; it fails loudly if package.json and
# package-lock.json have drifted.
run: npm ci
working-directory: docs
- name: Compute base path
id: compute-base
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "base=/ppvm/pr-preview/pr-${{ github.event.pull_request.number }}/" >> "$GITHUB_OUTPUT"
else
echo "base=/ppvm/" >> "$GITHUB_OUTPUT"
fi
- name: Compute git ref for source links
id: compute-ref
# "Source" links on the Examples pages resolve against this ref.
# PR previews use the PR head SHA so new files (that aren't on
# main yet) still link correctly; main deploys use the merge
# commit SHA so the link is stable forever.
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "ref=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
else
echo "ref=${{ github.sha }}" >> "$GITHUB_OUTPUT"
fi
- name: Build site
# `npm run build` aggregates the three extraction steps
# (`extract:rust`, `extract:python`, `extract:notebooks`) plus
# `astro build` into a single command. See `docs/README.md`
# for the per-step breakdown and the per-component escape
# hatches a developer would use locally.
working-directory: docs
env:
PPVM_SITE: https://queracomputing.github.io
PPVM_BASE: ${{ steps.compute-base.outputs.base }}
PPVM_GIT_REF: ${{ steps.compute-ref.outputs.ref }}
RUSTFLAGS: "-C target-feature=+aes,+sse2"
run: npm run build
- name: Upload built site
uses: actions/upload-artifact@v4
with:
name: docs-dist
path: docs/dist/
if-no-files-found: error
retention-days: 7
deploy-main:
name: Deploy to gh-pages
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
# Only this job writes to gh-pages; it doesn't run any
# repo-controlled scripts (the artifact is already built).
permissions:
contents: write
concurrency:
group: deploy-gh-pages
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: docs-dist
path: docs/dist/
- name: Publish to gh-pages root
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/dist
# Preserve /rust-api/ (managed by rust-docs.yml) and
# /pr-preview/* (managed by pr-preview-action below).
keep_files: true
commit_message: "docs: deploy ${{ github.sha }}"
deploy-preview:
name: Deploy PR preview
needs: build
if: github.event_name == 'pull_request' && github.event.action != 'closed'
runs-on: ubuntu-latest
# Writes the pre-built artifact to gh-pages/pr-preview/pr-<N>/
# and comments back on the PR.
permissions:
contents: write
pull-requests: write
concurrency:
group: deploy-gh-pages
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: docs-dist
path: docs/dist/
- name: Deploy PR preview to gh-pages/pr-preview/pr-<N>
uses: rossjrw/pr-preview-action@v1
with:
source-dir: docs/dist/
preview-branch: gh-pages
umbrella-dir: pr-preview
cleanup-preview:
name: Clean up PR preview
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
runs-on: ubuntu-latest
# Removes the gh-pages/pr-preview/pr-<N>/ subtree and edits the
# PR's preview comment; nothing else.
permissions:
contents: write
pull-requests: write
concurrency:
group: deploy-gh-pages
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
- uses: rossjrw/pr-preview-action@v1
with:
source-dir: docs/dist/
preview-branch: gh-pages
umbrella-dir: pr-preview
action: remove