-
Notifications
You must be signed in to change notification settings - Fork 2.4k
527 lines (462 loc) Β· 21.3 KB
/
sphinxbuild.yml
File metadata and controls
527 lines (462 loc) Β· 21.3 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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
name: "Build documentation"
on:
pull_request:
push:
branches:
- master
- stable*
permissions:
contents: read
concurrency:
group: build-documentation-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
setup-latex-cache:
name: Cache LaTeX packages
runs-on: ubuntu-latest
steps:
- name: Configure apt cache
run: |
mkdir -p ${{ runner.temp }}/.cache/archives
mkdir -p ${{ runner.temp }}/.cache/lists
echo 'Dir::Cache::archives "${{ runner.temp }}/.cache/archives";' | sudo tee /etc/apt/apt.conf.d/apt-cache-tmp
- name: Cache LaTeX apt packages
id: cache-latex-apt
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2
restore-keys: |
latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-
latex-apt-${{ runner.os }}-${{ runner.arch }}-
lookup-only: true
- name: Download LaTeX packages (cache miss only)
if: steps.cache-latex-apt.outputs.cache-hit != 'true'
run: |
for i in 1 2 3; do
sudo DEBIAN_FRONTEND=noninteractive apt-get update \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists" \
-o Acquire::Retries=3 && break
echo "apt-get update failed (attempt $i), retrying in 15s..."
sleep 15
done
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
--download-only \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists" \
python3-pil python3-pip texlive-fonts-recommended latexmk \
texlive-latex-extra texlive-latex-recommended texlive-xetex \
texlive-fonts-extra-links texlive-fonts-extra xindy tex-gyre
# Ensure downloaded packages are owned by the current user so they can be cached
sudo chown -R $(id -u):$(id -g) ${{ runner.temp }}/.cache/
- name: Save LaTeX apt cache (cache miss only)
if: steps.cache-latex-apt.outputs.cache-hit != 'true'
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2
build:
name: Build ${{ matrix.manual.name }}
runs-on: ubuntu-latest
needs: setup-latex-cache
strategy:
fail-fast: false
matrix:
manual:
- name: "user_manual"
directory: "user_manual"
make_target: "html"
build_path: "_build/html"
build_pdf_path: "_build/latex"
publish: true
- name: "user_manual-en"
directory: "user_manual"
make_target: "html-lang-en"
build_path: "_build/html"
publish: false
- name: "developer_manual"
directory: "developer_manual"
make_target: "html"
build_path: "_build/html/com"
publish: true
- name: "admin_manual"
directory: "admin_manual"
make_target: "html"
build_path: "_build/html/com"
build_pdf_path: "_build/latex"
publish: true
steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.10"
cache: "pip"
- name: Install pip dependencies
run: pip install -r requirements.txt
- name: Configure apt cache
if: ${{ matrix.manual.build_pdf_path }}
run: |
mkdir -p ${{ runner.temp }}/.cache/archives
mkdir -p ${{ runner.temp }}/.cache/lists
echo 'Dir::Cache::archives "${{ runner.temp }}/.cache/archives";' | sudo tee /etc/apt/apt.conf.d/apt-cache-tmp
- name: Restore LaTeX apt cache
if: ${{ matrix.manual.build_pdf_path }}
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
# Use relative path https://github.com/actions/cache/issues/1127
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2
restore-keys: |
latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-
latex-apt-${{ runner.os }}-${{ runner.arch }}-
- name: Install LaTeX from cache
if: ${{ matrix.manual.build_pdf_path }}
timeout-minutes: 5
run: |
debs=(${{ runner.temp }}/.cache/archives/*.deb)
if [ ! -e "${debs[0]}" ]; then
echo "No .deb files found in cache archives β cache may be empty or missing." >&2
exit 1
fi
sudo dpkg -i --force-depends "${debs[@]}"
sudo DEBIAN_FRONTEND=noninteractive apt-get install -f -y --no-install-recommends \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists"
- name: Build html documentation
run: cd ${{ matrix.manual.directory }} && make ${{ matrix.manual.make_target }}
- name: Compute PDF release version
if: ${{ matrix.manual.build_pdf_path }}
id: pdf_version
run: |
branch="${GITHUB_REF#refs/heads/}"
if [[ "$branch" == stable* ]]; then
echo "release=${branch#stable}" >> $GITHUB_OUTPUT
else
echo "release=latest" >> $GITHUB_OUTPUT
fi
- name: Build pdf documentation
if: ${{ matrix.manual.build_pdf_path }}
env:
DOCS_RELEASE: ${{ steps.pdf_version.outputs.release }}
run: |
set -e
cd ${{ matrix.manual.directory }}
make latexpdf
ls -la ${{ matrix.manual.build_pdf_path }}
cp ${{ matrix.manual.build_pdf_path }}/*.pdf ${{ matrix.manual.build_path }}/
- name: Upload static documentation
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: ${{ matrix.manual.publish }}
with:
name: ${{ matrix.manual.name }}
path: ${{ matrix.manual.directory }}/${{ matrix.manual.build_path }}
# ============================================================================
# STAGE AND VALIDATE
# ============================================================================
# This job is responsible for:
# 1. Determining deployment target folder names (branch_name/version_name)
# 2. Organizing build artifacts into a clean structure
# 3. Validating the documentation (link checking)
# 4. Uploading a minimal staging artifact for the deploy job
#
# IMPORTANT: This job does NOT modify gh-pages. It only prepares and validates
# the artifacts that will be deployed. The actual deployment happens in the
# deploy job.
# ============================================================================
stage-and-check:
name: Stage and check documentation
needs: build
runs-on: ubuntu-latest
outputs:
# branch_name: The primary deployment folder name for this branch
# - master β "latest"
# - stable<N> (if highest) β "stable"
# - stable<N> (if not highest) β "<N>" (numeric version)
branch_name: ${{ steps.branch.outputs.branch_name }}
# additional_deployment: ONLY set if deploying the highest stable branch
# - If this IS the highest stable β "<N>" (numeric version, e.g. "32")
# - Otherwise β "" (empty string)
#
# This allows the highest stable to be deployed to TWO locations:
# server/stable/ (via branch_name)
# server/<N>/ (via additional_deployment)
additional_deployment: ${{ steps.branch.outputs.additional_deployment }}
steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download all artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: artifacts/
# ========================================================================
# PREPARE FOR LINK VALIDATION: BUILD FULL PAGE CONTEXT
# ========================================================================
# We need to validate links in the new documentation, but some links may
# point to other versions or branches that are already deployed. So we:
# 1. Fetch the existing gh-pages content (old versions)
# 2. Merge in the new artifacts (what we're about to deploy)
# 3. Run link checks only on the NEW content, but with full context
# ========================================================================
# ========================================================================
# FETCH GH-PAGES FOR LINK VALIDATION CONTEXT
# ========================================================================
# We need the existing gh-pages content (old versions) so that link
# validation can resolve cross-version references. We use git cache
# to make this fast.
# ========================================================================
- name: Cache git metadata for gh-pages
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata
- name: Checkout gh-pages branch for validation context
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: gh-pages
fetch-depth: 1
path: validation-context
# ========================================================================
# DETERMINE DEPLOYMENT TARGETS (branch_name and version_name)
# ========================================================================
# Logic:
# 1. Determine current_branch: use GITHUB_REF if push, GITHUB_BASE_REF if PR
# 2. Find the highest numbered stable branch from git remotes
# 3. Map the current branch to deployment folder names:
#
# master β branch_name=latest (no version_name)
#
# stable<N> where N is highest β branch_name=stable, version_name=<N>
# (deployed to both server/stable/ and server/<N>/)
#
# stable<N> where N is not highest β branch_name=<N> (no version_name)
# (deployed only to server/<N>/)
#
# Any other branch β branch_name=<branch> (no version_name)
# ========================================================================
- name: Determine deployment targets (branch_name and version_name)
id: branch
run: |
# Determine which branch we're building from
current_branch=${GITHUB_REF#refs/heads/}
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
current_branch=${GITHUB_BASE_REF}
fi
# Find the highest numbered stable branch from the remote
# e.g., "stable30", "stable31", "stable32" β extract "32"
highest_stable=$(git ls-remote --heads origin | sed -n 's?.*refs/heads/stable\([0-9]\{2\}\)$?\1?p' | sort -n | tail -1)
highest_stable_branch="stable${highest_stable}"
echo "Current branch: $current_branch"
echo "Highest stable branch found: $highest_stable_branch"
# Map branch to deployment folder names
case "$current_branch" in
"master")
# master always deploys to "latest"
echo "branch_name=latest" >> $GITHUB_OUTPUT
;;
"$highest_stable_branch")
# Highest stable gets TWO locations: both "stable" and "<N>"
echo "branch_name=stable" >> $GITHUB_OUTPUT
echo "additional_deployment=${highest_stable}" >> $GITHUB_OUTPUT
;;
*)
# Other branches (including older stable branches) get their branch name
# For stable<N> where N is not highest: strip "stable" prefix to get just "<N>"
branch_for_deploy="${current_branch#stable}"
echo "branch_name=$branch_for_deploy" >> $GITHUB_OUTPUT
;;
esac
- name: Log deployment targets
run: |
echo "Deployment target folder: ${{ steps.branch.outputs.branch_name }}"
echo "Additional deployment folder (if applicable): ${{ steps.branch.outputs.additional_deployment }}"
# ========================================================================
# ORGANIZE ARTIFACTS FOR DEPLOYMENT
# ========================================================================
# Create a clean, minimal staging structure:
# - Deploy only the NEW artifacts for this branch
# - No need to include existing versions (we'll merge them during deploy)
# ========================================================================
- name: Organize artifacts for deployment
id: organize
run: |
branch="${{ steps.branch.outputs.branch_name }}"
# Create the branch folder directly
mkdir -p "stage/${branch}"
# Copy artifacts preserving their manual folder structure
# Each artifact (user_manual, admin_manual, developer_manual) contains
# the build output that should be placed in a folder named after the artifact
for artifact in artifacts/*; do
if [ -d "$artifact" ]; then
manual_name="$(basename "$artifact")"
# Create the manual-specific folder
mkdir -p "stage/${branch}/${manual_name}"
# Copy artifact contents into the manual folder
cp -r "$artifact/"* "stage/${branch}/${manual_name}/"
fi
done
# Move PDF files to the root of the branch folder for cleaner structure
find "stage/${branch}/" -maxdepth 2 -name "*.pdf" -type f -exec mv {} "stage/${branch}/" \;
# Clean up empty directories
find stage -type d -empty -delete
echo "Staged artifacts for ${branch}:"
find stage -type f | head -20
# ========================================================================
# CACHE STAGING ARTIFACTS
# ========================================================================
# Cache the staging folder for use in deploy job.
# This avoids artifact storage overhead (saves ~1.8GB).
# ========================================================================
- name: Cache staged artifacts
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: stage/
key: staged-docs-${{ github.sha }}
# ============================================================================
# DEPLOY
# ============================================================================
# This job is responsible for:
# 1. Downloading the staged artifacts from stage-and-check
# 2. Applying them to the gh-pages branch
# 3. Creating a pull request for the deployment
#
# This job ONLY runs on pushes (not on pull requests), since we only want
# to deploy when code is merged to master or a stable branch.
# ============================================================================
deploy:
name: Deploy documentation for gh-pages
needs: stage-and-check
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata
- name: Checkout gh-pages branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: gh-pages
fetch-depth: 1
persist-credentials: false
- name: Restore staged artifacts from cache
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: stage/
key: staged-docs-${{ github.sha }}
fail-on-cache-miss: true
# ========================================================================
# APPLY STAGED ARTIFACTS TO GH-PAGES
# ========================================================================
# Strategy:
# - Copy from stage/<branch_name>/ to server/<branch_name>/
# - If version_name is set, ALSO copy to server/<version_name>/
# - This allows the highest stable to live in both locations
# ========================================================================
- name: Apply staged artifacts to gh-pages
id: apply
run: |
branch="${{ needs.stage-and-check.outputs.branch_name }}"
additional="${{ needs.stage-and-check.outputs.additional_deployment }}"
changed=0
# Deploy to primary branch folder
echo "Deploying to server/${branch}/"
if [ -d "stage/${branch}" ]; then
rm -rf "server/${branch}"
mkdir -p "server/${branch}"
cp -r "stage/${branch}/"* "server/${branch}/" || true
changed=1
fi
# If this is the highest stable branch, also deploy to its versioned folder
if [ -n "${additional}" ]; then
echo "Also deploying to server/${additional}/ (additional versioned deployment)"
rm -rf "server/${additional}"
mkdir -p "server/${additional}"
cp -r "stage/${branch}/"* "server/${additional}/" || true
changed=1
fi
# Clean up empty directories
find . -type d -empty -delete
# Log the final directory structure for debugging
echo "Final server/ structure:"
find server -type d -maxdepth 2
# Check if there are actual changes
if git diff --quiet HEAD; then
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "has_changes=true" >> $GITHUB_OUTPUT
fi
# Remove the stage/ directory BEFORE creating the PR so it doesn't get committed
- name: Clean up staging cache before commit
run: rm -rf stage/
- name: Create Pull Request for documentation deployment
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
id: cpr
if: steps.apply.outputs.has_changes == 'true'
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: "chore: update documentation for `${{ needs.stage-and-check.outputs.branch_name }}`"
committer: nextcloud-command <nextcloud-command@users.noreply.github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: "automated/deploy/documentation-${{ needs.stage-and-check.outputs.branch_name }}"
base: gh-pages
title: "Documentation update for `${{ needs.stage-and-check.outputs.branch_name }}`"
body: |
This PR was automatically generated by the CI workflow and
includes the latest changes for the `${{ needs.stage-and-check.outputs.branch_name }}` branch.
delete-branch: true
labels: "automated, 3. to review"
- name: Enable Pull Request Automerge
run: gh pr merge --merge --auto "${{ steps.cpr.outputs.pull-request-number }}"
if: steps.cpr.outputs.pull-request-number != ''
env:
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
summary:
needs: [build, stage-and-check, deploy]
runs-on: ubuntu-latest-low
if: always()
permissions:
contents: read
name: build-deploy-summary
steps:
- name: Summary status
run: |
if ${{ github.event_name == 'pull_request' }}
then
echo "This workflow ran for a pull request. We need build and stage-and-check to succeed, but deploy will be skipped"
if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi
else
echo "This workflow ran for a push. We need all jobs to succeed, including deploy"
if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi
fi