-
Notifications
You must be signed in to change notification settings - Fork 1
219 lines (191 loc) · 9.44 KB
/
Copy pathdocs.yml
File metadata and controls
219 lines (191 loc) · 9.44 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
name: Deploy Docs
on:
push:
branches: [main]
# The union of every input that can reach the published bytes: `docs/**`
# (the only tree VitePress reads -- docs/.vitepress/config.mts and
# docs/.vitepress/theme/** import nothing outside docs/) plus every input
# to the screenshot pipeline that tests/e2e/screenshots.e2e.ts drives.
# scripts/native/** is in the set because it decides which native binary
# the built app loads; a broken rebuild changes what the app renders, or
# whether it starts at all.
#
# This list IS the authoritative declaration of that set -- there is no
# other file to keep it in sync with. If you add an input the screenshots
# depend on, add it here too: a missing entry silently skips a run that
# was needed and leaves the published site stale.
#
# Deliberately a workflow-level filter, unlike build.yml:22-27 which uses a
# job-level dorny/paths-filter. That comment's hazard -- workflow-level
# `paths-ignore` leaving required status checks permanently pending -- does
# not apply here: docs.yml has no `pull_request` trigger and is not a
# required check. A workflow-level filter costs 0 s on a skip where a
# job-level filter still spins up a runner. `workflow_dispatch` below is the
# escape hatch if this filter ever wrongly skips a needed run.
paths:
- 'docs/**'
- 'src/**'
- 'resources/**'
- 'tests/e2e/screenshots.e2e.ts'
- 'tests/e2e/test-data/demo-case.json'
- 'playwright.config.ts'
- 'electron.vite.config.ts'
- 'tsconfig*.json'
- 'package.json'
- 'package-lock.json'
- '.nvmrc'
- 'scripts/native/**'
- '.github/workflows/docs.yml'
workflow_dispatch:
permissions:
contents: read
# Deliberately diverges from GitHub's Pages starter template, which sets
# `cancel-in-progress: false` to let production deployments finish.
#
# That is the wrong trade for a docs site rebuilt from `main` on every push.
# GitHub Pages serialises deployments API-side, so several pushes in quick
# succession leave every run sitting in `deployment_queued` until
# `actions/deploy-pages` gives up with "Timeout reached, aborting!". Observed
# 2026-08-06: three pushes to `main` within ~25 minutes (two PR merges plus a
# release version bump) produced three queued deploys; two timed out after
# 10 minutes each having built the whole Electron app and screenshot suite
# first.
#
# Superseding is also semantically right here: the docs site only ever reflects
# the tip of `main`, so an in-flight deploy of an older commit has no value once
# a newer one exists. Nothing is lost by cancelling it.
concurrency:
group: pages
cancel-in-progress: true
jobs:
build-screenshots:
name: Build & Screenshots
runs-on: ubuntu-latest
# Baseline is 237 s. 20 minutes is ~5x headroom -- enough for a cold native
# cache (which adds a ~35 s compile) plus a slow runner, without letting a
# hung Electron launch burn a full 6-hour default timeout.
timeout-minutes: 20
steps:
- name: Configure git line endings
run: git config --global core.autocrlf false
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # actions/checkout@v7.0.1
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # actions/setup-node@v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Allow Electron to use unprivileged user namespaces (Ubuntu 24.04)
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Extract Electron version
id: electron-ver
shell: bash
run: echo "ver=$(node -p "require('./package.json').devDependencies.electron")" >> "$GITHUB_OUTPUT"
# Restore the repo-owned ABI-keyed native cache BEFORE npm ci, so
# postinstall restores a binary instead of compiling one. `.cache/native`
# is a sibling of node_modules and survives `npm ci`.
# Path is `.cache/native`, never bare `.cache` — `.cache/tsbuildinfo` is a
# sibling with a different key. No restore-keys: a partial match is
# rejected by manifestIsFresh() anyway, and the absence documents intent.
- name: Restore native ABI cache
id: native-cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # actions/cache@v6.1.0
with:
path: .cache/native
key: native-${{ runner.os }}-${{ runner.arch }}-${{ steps.electron-ver.outputs.ver }}-${{ hashFiles('package-lock.json') }}
# libsqlite3-dev and build-essential exist only to compile
# better-sqlite3-multiple-ciphers. The ABI-keyed native cache restores a
# prebuilt binary, so on a hit nothing normally compiles and these
# packages are 9 s of dead weight.
#
# Not airtight, deliberately: scripts/native/rebuild-native.mjs verifies
# the restored binary's ABI and, on a mismatch it cannot resolve, purges
# the entry and compiles for real -- while `cache-hit` is still 'true'.
# On ubuntu-latest that fallback compile still has build-essential from
# the runner image, so it succeeds; if it ever did not, this job fails
# loudly and publishes nothing. build.yml:289-291 keeps its equivalent
# step unconditional for exactly this coupling; docs.yml accepts the
# trade because 9 s is 4% of its 237 s baseline.
- name: Install system dependencies
if: steps.native-cache.outputs.cache-hit != 'true'
run: |
sudo apt-get update
sudo apt-get install -y libsqlite3-dev build-essential
- name: Install dependencies
run: npm ci
- name: Rebuild native modules for Electron
run: npm run rebuild:electron
# This job builds and drives the packaged Electron app (screenshots.e2e.ts
# launches it via Playwright), so assert the ELECTRON ABI, not node.
- name: Assert native ABI
run: node scripts/native/assert-native-abi.mjs electron
- name: Build Electron app
run: npx electron-vite build
- name: Generate screenshots
run: xvfb-run --auto-servernum npx playwright test tests/e2e/screenshots.e2e.ts
- name: Upload screenshots
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # actions/upload-artifact@v7.0.1
with:
name: screenshots
path: docs/public/screenshots/*.png
retention-days: 1
deploy:
name: Deploy to GitHub Pages
needs: build-screenshots
runs-on: ubuntu-latest
# Baseline is 39 s, but actions/deploy-pages waits on the Pages API with its
# own 1200000 ms budget. 25 minutes sits just above that so the action's own
# timeout reports the real error rather than being masked by a job kill.
timeout-minutes: 25
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # actions/checkout@v7.0.1
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # actions/setup-node@v7.0.0
with:
node-version-file: '.nvmrc'
cache: 'npm'
# Deliberately no native ABI cache and no `assert-native-abi.mjs` check
# in this job. `--ignore-scripts` skips both the dependency's own
# install script and the root `postinstall`, so no `.node` binary is
# placed at all — this job only runs VitePress, which never touches the
# native module. An ABI assertion here would fail a perfectly correct
# job because there is nothing on disk to verify. Do not "fix" this
# inconsistency with the other jobs; it is intentional.
- name: Install dependencies (skip native rebuild — only VitePress needed)
run: npm ci --ignore-scripts
- name: Download screenshots
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # actions/download-artifact@v8.0.1
with:
name: screenshots
path: docs/public/screenshots/
- name: Build docs
run: npm run docs:build
- name: Setup Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # actions/configure-pages@v6.0.0
- name: Upload to Pages
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # actions/upload-pages-artifact@v5.0.0
with:
path: docs/.vitepress/dist
# `timeout` is the action's own budget for waiting on the Pages API to
# move a created deployment out of `deployment_queued`; the default is
# 600000 ms. On 2026-08-06 four consecutive deploys sat queued for the
# full ten minutes and aborted, while the artifact, the workflow and the
# Pages configuration were all verified correct — i.e. the stall was on
# the Pages side, not ours. Twenty minutes gives a slow-but-working
# backend room to finish instead of burning the whole docs build.
#
# This is resilience, not a root-cause fix. If deploys still time out,
# the problem is server-side and belongs in a GitHub support ticket —
# do not keep raising this number.
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # actions/deploy-pages@v5.0.1
with:
timeout: 1200000