forked from bertiniteam/b2
-
Notifications
You must be signed in to change notification settings - Fork 0
229 lines (208 loc) · 9.5 KB
/
Copy pathbuild_docs.yml
File metadata and controls
229 lines (208 loc) · 9.5 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
name: Build and deploy documentation 📝
on:
workflow_call:
# When called from publish.yml, the caller's build_and_test job has
# already produced the wheel artifact this workflow needs. The internal
# build_and_test job below is skipped in that case.
inputs:
deploy:
description: 'Deploy to GitHub Pages after building'
required: false
type: boolean
default: true
workflow_dispatch:
inputs:
deploy:
description: 'Deploy to GitHub Pages after building'
required: false
type: boolean
default: true
ref:
description: 'Branch, tag, or SHA to build docs for (defaults to the dispatched ref).'
required: false
type: string
default: ''
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true
jobs:
build_and_test:
name: Build wheel (for docs)
# Only run when triggered manually. workflow_call invocations assume the
# caller already ran build_and_test in the same workflow run, so the
# wheel artifact is already available.
if: github.event_name == 'workflow_dispatch'
uses: ./.github/workflows/build_and_test.yml
with:
# Docs only need the ubuntu-latest / python-3.11 wheel; skip the full
# OS/Python matrix and the wheel/C++ test jobs.
minimal: true
ref: ${{ inputs.ref }}
# The Doxygen C++ reference needs NO wheel, so it builds CONCURRENTLY with the
# wheel (the minimal `build_and_test` on dispatch, or the caller's build_and_test
# on workflow_call) instead of waiting behind it. Its output is handed to
# python_docs as the `docs-cpp` artifact for final assembly.
cpp_docs:
name: Build C++ docs (Doxygen)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
ref: ${{ inputs.ref || github.ref }}
- name: Compute build metadata
id: meta
run: |
SHORT=$(git rev-parse --short HEAD)
DATE=$(date -u +'%Y-%m-%d %H:%M UTC')
echo "short=$SHORT" >> "$GITHUB_OUTPUT"
echo "date=$DATE" >> "$GITHUB_OUTPUT"
- name: Install system dependencies (Doxygen)
run: |
sudo apt-get update
# texlive-binaries provides bibtex, which Doxygen needs to number and
# render the \cite references (CITE_BIB_FILES in the Doxyfile) into a
# bibliography in the published C++ docs.
sudo apt-get install -y doxygen graphviz texlive-binaries
- name: Fetch doxygen-awesome-css
run: |
curl -sSL https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v2.3.4.tar.gz | tar -xz
mv doxygen-awesome-css-2.3.4 doxygen-awesome-css
- name: Build C++ docs (Doxygen)
env:
PROJECT_NUMBER: "${{ steps.meta.outputs.short }} (${{ steps.meta.outputs.date }})"
run: |
mkdir -p build/docs/cpp site
# Append PROJECT_NUMBER override via stdin; Doxygen reads stdin
# config when invoked with `-` and merges with the file.
(cat Doxyfile; echo "PROJECT_NUMBER = $PROJECT_NUMBER") | doxygen -
mv build/docs/cpp site/cpp
- name: Upload C++ docs artifact
uses: actions/upload-artifact@v5
with:
name: docs-cpp
path: site/cpp
if-no-files-found: error
python_docs:
name: Build docs
needs: [build_and_test, cpp_docs]
# `build_and_test` is skipped when invoked via workflow_call; treat that
# as success so python_docs runs in both modes. cpp_docs always runs, so it
# must genuinely succeed (its artifact is assembled into the final site).
if: |
always() &&
(needs.build_and_test.result == 'success' || needs.build_and_test.result == 'skipped') &&
needs.cpp_docs.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write # push the persistent docs-store branch (the durable versioned-docs store)
steps:
- uses: actions/checkout@v5
with:
ref: ${{ inputs.ref || github.ref }}
# gitpython (used by python/docs/source/conf.py to derive version)
# needs the full history; the default depth=1 leaves it unable to
# resolve HEAD's commit object on some refs.
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Compute build metadata
id: meta
run: |
SHA=$(git rev-parse HEAD)
SHORT=$(git rev-parse --short HEAD)
DATE=$(date -u +'%Y-%m-%d %H:%M UTC')
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
echo "short=$SHORT" >> "$GITHUB_OUTPUT"
echo "date=$DATE" >> "$GITHUB_OUTPUT"
echo "Build metadata: $SHORT ($SHA) at $DATE"
- name: Install Python deps for Sphinx
# The bertini2 wheel bundles the eigenpy C++ libraries it links
# against; no Python `eigenpy` install is required to import bertini
# for sphinx autodoc.
run: |
python -m pip install --upgrade pip
pip install \
sphinx furo sphinxcontrib-bibtex gitpython \
scikit-build-core build numpy matplotlib pandas sympy networkx
- name: Download built wheel
uses: actions/download-artifact@v5
with:
name: wheels-ubuntu-latest-3.11
path: dist/
- name: Install bertini from built wheel
run: pip install --no-index --find-links dist/ bertini2
# The Doxygen C++ reference was built in parallel by the cpp_docs job; drop it
# into site/cpp so the assembled site/ has cpp + python + landing.
- name: Download C++ docs
uses: actions/download-artifact@v5
with:
name: docs-cpp
path: site/cpp
- name: Run tutorial doctests (Sphinx)
# Execute the `.. testcode::` / `>>>` blocks in the docs against the installed wheel, so
# the tutorials are verified code, not just prose. Fails the build if any doctest fails.
working-directory: python/docs
run: |
sphinx-build -b doctest --keep-going source ../../build/docs/doctest
- name: Build Python docs (Sphinx)
working-directory: python/docs
env:
BERTINI_GIT_SHA: ${{ steps.meta.outputs.sha }}
BERTINI_BUILD_DATE: ${{ steps.meta.outputs.date }}
run: |
# -d keeps the .doctrees pickle cache OUT of the published tree (site/python); it is a
# build intermediate, never part of the site.
sphinx-build -b html -W --keep-going -d ../../build/docs/py-doctrees source ../../site/python
- name: Add landing page
env:
COMMIT_SHA: ${{ steps.meta.outputs.sha }}
COMMIT_SHORT: ${{ steps.meta.outputs.short }}
BUILD_DATE: ${{ steps.meta.outputs.date }}
run: |
sed \
-e "s|__COMMIT_SHA__|${COMMIT_SHA}|g" \
-e "s|__COMMIT_SHORT__|${COMMIT_SHORT}|g" \
-e "s|__BUILD_DATE__|${BUILD_DATE}|g" \
doc_resources/landing/index.html > site/index.html
cp doc_resources/landing/style.css site/style.css
- name: Determine release version
id: relver
run: |
VERSION=$(tr -d '[:space:]' < VERSION)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# Only a public release (X.Y.Z, no pre/dev suffix) gets a durable versioned-docs directory.
if echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "is_release=true" >> "$GITHUB_OUTPUT"
else
echo "is_release=false" >> "$GITHUB_OUTPUT"
echo "::notice::VERSION '$VERSION' is not a public release; docs built but not deployed "\
"(the site keeps only X.Y.Z versions -- deploy happens from real release tags)."
fi
- name: Assemble & publish the versioned docs store
# Fold the freshly-built site/ into the persistent docs-store branch as /vX.Y.Z/, refresh
# the /stable/ redirect + root landing (derived from every version present), and push it back.
# GitHub Pages serves this branch DIRECTLY (Pages source = docs-store), so this push IS the
# deploy -- no actions/deploy-pages, no artifact exchange. The branch is the durable byte
# store; older versions are never rebuilt. Public releases only.
if: steps.relver.outputs.is_release == 'true' && inputs.deploy
env:
STORE_BRANCH: docs-store
REMOTE: https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git
run: |
set -euo pipefail
if git ls-remote --exit-code --heads "$REMOTE" "$STORE_BRANCH" >/dev/null 2>&1; then
git clone --branch "$STORE_BRANCH" --single-branch --depth 1 "$REMOTE" store
else
echo "No $STORE_BRANCH yet; starting a fresh store."
git init -q store && git -C store checkout -q -b "$STORE_BRANCH"
fi
# --cname keeps the bertini2.org custom domain in the branch (branch-source Pages reads it).
python tools/assemble_versioned_docs.py --site site --store store \
--version "${{ steps.relver.outputs.version }}" --stable --cname bertini2.org
git -C store config user.name "github-actions[bot]"
git -C store config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git -C store add -A
git -C store commit -q -m "docs: publish v${{ steps.relver.outputs.version }}" || echo "store unchanged"
git -C store push -q "$REMOTE" HEAD:"$STORE_BRANCH"