Skip to content

Commit 7b79f0e

Browse files
author
Release Manager
committed
gh-39973: Migrate CI build-doc to Meson <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes #12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes #12345". --> Make it possible to build the documentation with meson via ``` meson compile -C builddir doc-html ``` For this a couple of changes was necessary in the docbuilder: - Make `sage_docbuild` independent of `sage` so that meson can use `sage_docbuild` during config time to construct all the docbuild targets (otherwise one needs to first install sage, and then could configure the docbuild) - Properly handle input and output dirs for the docbuild, without relying on magic sage env variables ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [ ] The title is concise and informative. - [ ] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #39973 Reported by: Tobias Diez Reviewer(s): Dima Pasechnik, Tobias Diez, user202729
2 parents 85d6f2d + 3408887 commit 7b79f0e

File tree

18 files changed

+701
-518
lines changed

18 files changed

+701
-518
lines changed

.github/workflows/doc-build.yml

Lines changed: 54 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -16,117 +16,67 @@ on:
1616
- develop
1717
workflow_dispatch:
1818
# Allow to run manually
19-
inputs:
20-
platform:
21-
description: 'Platform'
22-
required: true
23-
default: 'ubuntu-noble-standard'
24-
docker_tag:
25-
description: 'Docker tag'
26-
required: true
27-
default: 'dev'
2819

2920
concurrency:
3021
# Cancel previous runs of this workflow for the same branch
3122
group: ${{ github.workflow }}-${{ github.ref }}
3223
cancel-in-progress: true
3324

3425
env:
35-
# Same as in build.yml
36-
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-incremental"
37-
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-with-targets:ci"
38-
FROM_DOCKER_REPOSITORY: "ghcr.io/sagemath/sage/"
39-
FROM_DOCKER_TARGET: "with-targets"
40-
FROM_DOCKER_TAG: ${{ github.event.inputs.docker_tag || 'dev'}}
41-
EXTRA_CONFIGURE_ARGS: --enable-fat-binary
26+
PYTHON_VERSION: 3.11
4227

4328
jobs:
4429
build-doc:
4530
runs-on: ubuntu-latest
46-
services:
47-
# https://docs.docker.com/build/ci/github-actions/local-registry/
48-
registry:
49-
image: registry:2
50-
ports:
51-
- 5000:5000
5231
steps:
53-
- name: Maximize build disk space
54-
uses: easimon/maximize-build-space@v10
55-
with:
56-
# need space in /var for Docker images
57-
root-reserve-mb: 30000
58-
remove-dotnet: true
59-
remove-android: true
60-
remove-haskell: true
61-
remove-codeql: true
62-
remove-docker-images: true
6332
- name: Checkout
6433
uses: actions/checkout@v4
65-
- name: Install test prerequisites
66-
# From docker.yml
67-
run: |
68-
sudo DEBIAN_FRONTEND=noninteractive apt-get update
69-
sudo DEBIAN_FRONTEND=noninteractive apt-get install tox
70-
sudo apt-get clean
71-
df -h
34+
7235
- name: Merge CI fixes from sagemath/sage
7336
run: |
74-
mkdir -p upstream
75-
.github/workflows/merge-fixes.sh 2>&1 | tee upstream/ci_fixes.log
37+
.github/workflows/merge-fixes.sh
7638
env:
7739
GH_TOKEN: ${{ github.token }}
78-
SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }}
79-
80-
# Building
81-
82-
- name: Generate Dockerfile
83-
# From docker.yml
84-
run: |
85-
tox -e ${{ env.TOX_ENV }}
86-
cp .tox/${{ env.TOX_ENV }}/Dockerfile .
87-
env:
88-
# Only generate the Dockerfile, do not run 'docker build' here
89-
DOCKER_TARGETS: ""
9040

91-
- name: Set up Docker Buildx
92-
uses: docker/setup-buildx-action@v3
41+
- name: Cache conda packages
42+
uses: actions/cache@v4
9343
with:
94-
driver-opts: network=host
95-
96-
- name: Build Docker image
97-
id: image
98-
uses: docker/build-push-action@v6
44+
path: ~/conda_pkgs_dir
45+
key:
46+
${{ runner.os }}-conda-${{ hashFiles('environment-${{ env.PYTHON_VERSION }}-linux.yml') }}
47+
48+
- name: Compiler cache
49+
uses: hendrikmuhs/[email protected]
9950
with:
100-
# push and load may not be set together at the moment
101-
push: true
102-
load: false
103-
context: .
104-
tags: ${{ env.BUILD_IMAGE }}
105-
target: with-targets
106-
cache-from: type=gha
107-
cache-to: type=gha,mode=max
108-
build-args: |
109-
NUMPROC=6
110-
USE_MAKEFLAGS=-k V=0 SAGE_NUM_THREADS=4 --output-sync=recurse
111-
TARGETS_PRE=build/make/Makefile
112-
TARGETS=ci-build-with-fallback
51+
key: ${{ runner.os }}-meson-${{ env.PYTHON_VERSION }}
11352

114-
- name: Start container
115-
id: container
116-
# Try to continue when "exporting to GitHub Actions Cache" failed with timeout
53+
- name: Setup Conda environment
54+
uses: conda-incubator/setup-miniconda@v3
55+
with:
56+
python-version: ${{ env.PYTHON_VERSION }}
57+
# Disabled for now due to
58+
# https://github.com/conda-incubator/setup-miniconda/issues/379
59+
# miniforge-version: latest
60+
use-mamba: true
61+
channels: conda-forge
62+
channel-priority: true
63+
activate-environment: sage-dev
64+
environment-file: environment-${{ env.PYTHON_VERSION }}-linux.yml
65+
66+
- name: Build Sage
67+
shell: bash -l {0}
11768
run: |
118-
docker run --name BUILD -dit \
119-
--mount type=bind,src=$(pwd),dst=$(pwd) \
120-
--workdir $(pwd) \
121-
${{ env.BUILD_IMAGE }} /bin/sh
69+
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
70+
export CC="ccache $CC"
71+
export CXX="ccache $CXX"
72+
pip install --no-build-isolation --config-settings=builddir=builddir --editable . -v
12273
12374
#
124-
# On pull request and push to develop events
75+
# For pull requests
12576
#
126-
12777
- name: Get workflow run-id
12878
id: get_run_id
129-
if: steps.container.outcome == 'success' && !startsWith(github.ref, 'refs/tags/') && github.event_name == 'pull_request'
79+
if: github.event_name == 'pull_request'
13080
run: |
13181
RESPONSE=$(curl -s -L \
13282
-H "Accept: application/vnd.github+json" \
@@ -149,6 +99,7 @@ jobs:
14999
- name: Store old doc
150100
id: worktree
151101
if: steps.download-doc.outcome == 'success'
102+
shell: bash -l {0}
152103
run: |
153104
git config --global --add safe.directory $(pwd)
154105
git config --global user.email "[email protected]"
@@ -164,8 +115,8 @@ jobs:
164115
# mathjax path in old doc (regex)
165116
mathjax_path_from="[-./A-Za-z_]*/tex-chtml[.]js?v=[0-9a-f]*"
166117
# mathjax path in new doc
167-
mathjax_path_to=$(docker exec -e SAGE_USE_CDNS=yes BUILD /sage/sage -python -c "from sage_docbuild.conf import mathjax_path; print(mathjax_path)")
168-
new_version=$(docker exec BUILD cat src/VERSION.txt)
118+
mathjax_path_to=$(SAGE_USE_CDNS=yes python -c "from src.sage_docbuild.conf import mathjax_path; print(mathjax_path)")
119+
new_version=$(cat src/VERSION.txt)
169120
# Wipe out chronic diffs between old doc and new doc
170121
(cd doc && \
171122
find . -name "*.html" | xargs sed -i -e '/class="sidebar-brand-text"/ s/Sage [0-9a-z.]* /Sage '"$new_version"' /' \
@@ -185,20 +136,15 @@ jobs:
185136
git add -A && git commit --quiet -m 'old')
186137
fi
187138
188-
- name: Build doc
139+
- name: Build documentation
189140
id: docbuild
190-
if: steps.container.outcome == 'success' && !startsWith(github.ref, 'refs/tags/')
191-
# Always non-incremental because of the concern that
192-
# incremental docbuild may introduce broken links (inter-file references) though build succeeds
141+
if: steps.worktree.outcome == 'success'
142+
shell: bash -l {0}
193143
run: |
194-
export GITHUB_REF=${{ github.ref }}
195-
export PR_SHA=${{ github.event.pull_request.head.sha }}
196-
export MAKE="make -j5 --output-sync=recurse" SAGE_NUM_THREADS=5
197-
make doc-clean doc-uninstall
198-
export SAGE_USE_CDNS=yes
199-
export SAGE_DOCBUILD_OPTS="--include-tests-blocks"
200-
./config.status && make sagemath_doc_html-no-deps
201-
shell: sh .github/workflows/docker-exec-script.sh BUILD /sage {0}
144+
meson compile -C builddir doc-html
145+
env:
146+
SAGE_USE_CDNS: yes
147+
SAGE_DOCBUILD_OPTS: "--include-tests-blocks"
202148

203149
- name: Copy doc
204150
id: copy
@@ -209,12 +155,7 @@ jobs:
209155
if [ -d "doc/html" ]; then
210156
rm -rf doc/html
211157
fi
212-
# Simpler "docker cp --follow-link ... doc" does not work
213-
mkdir -p doc
214-
mkdir -p temp
215-
docker cp --follow-link BUILD:/sage/local/share/doc/sage/html temp
216-
docker cp --follow-link BUILD:/sage/local/share/doc/sage/index.html temp
217-
cp -r -L temp/* doc/
158+
cp -r builddir/src/doc/* doc/
218159
# Check if we are on pull request event
219160
PR_NUMBER=""
220161
if [[ -n "$GITHUB_REF" ]]; then
@@ -275,30 +216,24 @@ jobs:
275216
- name: Build live doc
276217
id: buildlivedoc
277218
if: startsWith(github.ref, 'refs/tags/')
219+
shell: bash -l {0}
278220
run: |
279-
# Avoid running out of disk space
280-
rm -rf upstream
281-
export MAKE="make -j5 --output-sync=recurse" SAGE_NUM_THREADS=5
282-
export PATH="build/bin:$PATH"
283-
eval $(sage-print-system-package-command auto update)
284-
eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip)
285-
eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive texlive_luatex free_fonts xindy)
286-
export SAGE_USE_CDNS=yes
287-
export SAGE_LIVE_DOC=yes
288-
export SAGE_JUPYTER_SERVER=binder:sagemath/sage-binder-env/dev
289-
make doc-clean doc-uninstall
290-
./config.status && make sagemath_doc_html-no-deps sagemath_doc_pdf-no-deps
291-
shell: sh .github/workflows/docker-exec-script.sh BUILD /sage {0}
221+
meson compile -C builddir doc-html
222+
env:
223+
SAGE_USE_CDNS: yes
224+
SAGE_LIVE_DOC: yes
225+
SAGE_JUPYTER_SERVER: binder:sagemath/sage-binder-env/dev
226+
SAGE_DOCBUILD_OPTS: "--include-tests-blocks"
292227

293228
- name: Copy live doc
294229
id: copylivedoc
295230
if: steps.buildlivedoc.outcome == 'success'
296231
run: |
297232
mkdir -p ./livedoc
298233
# We copy everything to a local folder
299-
docker cp --follow-link BUILD:/sage/local/share/doc/sage/html livedoc
300-
docker cp --follow-link BUILD:/sage/local/share/doc/sage/pdf livedoc
301-
docker cp --follow-link BUILD:/sage/local/share/doc/sage/index.html livedoc
234+
cp -r builddir/src/doc/html livedoc/
235+
cp -r builddir/src/doc/pdf livedoc/
236+
cp builddir/src/doc/index.html livedoc/
302237
zip -r livedoc.zip livedoc
303238
304239
- name: Upload live doc

environment-3.11-linux.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ dependencies:
340340
- soupsieve=2.7=pyhd8ed1ab_0
341341
- sphinx=8.2.3=pyhd8ed1ab_0
342342
- sphinx-basic-ng=1.0.0b2=pyhd8ed1ab_3
343+
- sphinx-copybutton=0.5.2=pyhd8ed1ab_1
343344
- sphinx-inline-tabs=2023.4.21=pyhd8ed1ab_1
344345
- sphinxcontrib-applehelp=2.0.0=pyhd8ed1ab_1
345346
- sphinxcontrib-devhelp=2.0.0=pyhd8ed1ab_1

meson.build

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ project(
44
version: files('src/VERSION.txt'),
55
license: 'GPL v3',
66
default_options: ['c_std=c17', 'cpp_std=c++17', 'python.install_env=auto'],
7+
meson_version: '>=1.2',
78
)
89

910
# Python module
@@ -215,4 +216,6 @@ for path in file_paths:
215216
]
216217
run_command(create_files_command, check: true)
217218

219+
root = meson.current_source_dir()
220+
218221
subdir('src')

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ test = [
215215
]
216216
docs = [
217217
"sphinx",
218-
"sphinx-inline-tabs",
218+
"sphinx-copybutton",
219+
"sphinx-inline-tabs",
219220
"furo",
220221
"python-dateutil",
221222
]
@@ -232,6 +233,7 @@ dev = [
232233
"conda-lock",
233234
"grayskull",
234235
"toml",
236+
"uv",
235237
]
236238

237239
[tool.ruff]

src/build-docs.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from sage_docbuild.__main__ import main
2+
3+
if __name__ == "__main__":
4+
main()

src/doc/Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ doc-inventory-reference: doc-src
4040
$(eval DOCS = $(shell sage --docbuild --all-documents reference))
4141
@if [ -z "$(DOCS)" ]; then echo "Error: 'sage --docbuild --all-documents' failed"; exit 1; fi
4242
$(eval BIBLIO = $(firstword $(DOCS)))
43-
$(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS)))
43+
$(eval OTHER_DOCS = $(filter-out reference_top, $(wordlist 2, 100, $(DOCS))))
4444
$(MAKE) doc-inventory--$(subst /,-,$(BIBLIO))
4545
$(MAKE) $(foreach doc, $(OTHER_DOCS), doc-inventory--$(subst /,-,$(doc)))
4646
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-inventory--reference_top
@@ -51,7 +51,7 @@ doc-html-reference-sub: doc-inventory-reference
5151
$(eval DOCS = $(shell sage --docbuild --all-documents reference))
5252
@if [ -z "$(DOCS)" ]; then echo "Error: 'sage --docbuild --all-documents' failed"; exit 1; fi
5353
$(eval BIBLIO = $(firstword $(DOCS)))
54-
$(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS)))
54+
$(eval OTHER_DOCS = $(filter-out reference_top, $(wordlist 2, 100, $(DOCS))))
5555
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-html--$(subst /,-,$(BIBLIO))
5656
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(OTHER_DOCS), doc-html--$(subst /,-,$(doc)))
5757

@@ -63,7 +63,7 @@ doc-html-reference: doc-html-reference-sub
6363
doc-html-other: doc-html-reference
6464
$(eval DOCS = $(shell sage --docbuild --all-documents all))
6565
@if [ -z "$(DOCS)" ]; then echo "Error: 'sage --docbuild --all-documents' failed"; exit 1; fi
66-
$(MAKE) $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-html--$(subst /,-,$(doc)))
66+
$(MAKE) $(foreach doc, $(DOCS), doc-html--$(subst /,-,$(doc)))
6767

6868
doc-html: doc-html-reference doc-html-other
6969
SAGE_DOC=$$(sage --python -c "from sage.env import SAGE_DOC; print(SAGE_DOC)")
@@ -78,7 +78,7 @@ doc-pdf-reference: doc-inventory-reference
7878
$(eval DOCS = $(shell sage --docbuild --all-documents reference))
7979
@if [ -z "$(DOCS)" ]; then echo "Error: 'sage --docbuild --all-documents' failed"; exit 1; fi
8080
$(eval BIBLIO = $(firstword $(DOCS)))
81-
$(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS)))
81+
$(eval OTHER_DOCS = $(filter-out reference_top, $(wordlist 2, 100, $(DOCS))))
8282
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-pdf--$(subst /,-,$(BIBLIO))
8383
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(OTHER_DOCS), doc-pdf--$(subst /,-,$(doc)))
8484
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-pdf--reference_top
@@ -87,7 +87,7 @@ doc-pdf-reference: doc-inventory-reference
8787
doc-pdf-other: doc-pdf-reference
8888
$(eval DOCS = $(shell sage --docbuild --all-documents all))
8989
@if [ -z "$(DOCS)" ]; then echo "Error: 'sage --docbuild --all-documents' failed"; exit 1; fi
90-
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-pdf--$(subst /,-,$(doc)))
90+
$(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(DOCS), doc-pdf--$(subst /,-,$(doc)))
9191

9292
doc-pdf: doc-pdf-reference doc-pdf-other
9393
SAGE_DOC=$$(sage --python -c "from sage.env import SAGE_DOC; print(SAGE_DOC)")

src/doc/bootstrap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ if [ -z "$SAGE_ROOT" ]; then
1818
fi
1919

2020
cd "$SAGE_ROOT"
21+
export PATH=build/bin:$PATH
2122

2223
OUTPUT_DIR="src/doc/en/installation"
2324
mkdir -p "$OUTPUT_DIR"

src/doc/en/installation/meson.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ To compile and install Sage in editable install, then just use:
172172
memory_allocator \
173173
"numpy >=1.25" \
174174
jinja2 \
175-
setuptool
175+
setuptools
176176
$ uv sync --frozen --inexact --no-build-isolation
177177
178178
You can then start Sage from the command line with ``./sage``

src/doc/en/reference/conf_sub.py

100644100755
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
# serve to show the default.
1212

1313
import os
14-
from sage.env import SAGE_DOC_SRC, SAGE_DOC
15-
from sage_docbuild.conf import release, exclude_patterns
14+
15+
from sage.env import SAGE_DOC, SAGE_DOC_SRC
1616
from sage_docbuild.conf import *
17+
from sage_docbuild.conf import exclude_patterns
1718

1819
# Add any paths that contain custom static files (such as style sheets),
1920
# relative to this directory to html_static_path. They are copied after the
@@ -26,7 +27,7 @@
2627
ref_out = os.path.join(SAGE_DOC, 'html', 'en', 'reference')
2728

2829
# We use the main document's title, if we can find it.
29-
rst_file = open('index.rst', 'r')
30+
rst_file = open('index.rst', 'r', encoding='utf-8')
3031
rst_lines = rst_file.read().splitlines()
3132
rst_file.close()
3233

src/doc/en/reference/repl/meson.build

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
doc_src += custom_target(
2+
'doc-src',
3+
output: ['options.txt'],
4+
command: [py, src / 'sage' / 'cli', '--help'],
5+
capture: true,
6+
)

0 commit comments

Comments
 (0)