Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 51 additions & 106 deletions .github/workflows/doc-build-pdf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,148 +2,93 @@ name: Build documentation (PDF)

on:
pull_request:
merge_group:
push:
tags:
# Match all release tags including beta, rc
- '[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.beta[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+.beta[0-9]+'
- '[0-9]+.[0-9]+.rc[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+.rc[0-9]+'
branches:
- develop
workflow_dispatch:
# Allow to run manually
inputs:
platform:
description: 'Platform'
required: true
default: 'ubuntu-noble-standard'
docker_tag:
description: 'Docker tag'
required: true
default: 'dev'

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

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

jobs:
build-doc-pdf:
doc-pdf:
runs-on: ubuntu-latest
services:
# https://docs.docker.com/build/ci/github-actions/local-registry/
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Maximize build disk space
uses: easimon/maximize-build-space@v10
with:
# need space in /var for Docker images
root-reserve-mb: 30000
remove-dotnet: true
remove-android: true
remove-haskell: true
remove-codeql: true
remove-docker-images: true
- name: Checkout
uses: actions/checkout@v4
- name: Install test prerequisites
# From docker.yml
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install tox
sudo apt-get clean
df -h

- name: Merge CI fixes from sagemath/sage
run: |
mkdir -p upstream
.github/workflows/merge-fixes.sh 2>&1 | tee upstream/ci_fixes.log
.github/workflows/merge-fixes.sh
env:
GH_TOKEN: ${{ github.token }}
SAGE_CI_FIXES_FROM_REPOSITORIES: ${{ vars.SAGE_CI_FIXES_FROM_REPOSITORIES }}

# Building

- name: Generate Dockerfile
# From docker.yml
run: |
tox -e ${{ env.TOX_ENV }}
cp .tox/${{ env.TOX_ENV }}/Dockerfile .
env:
# Only generate the Dockerfile, do not run 'docker build' here
DOCKER_TARGETS: ""

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache conda packages
uses: actions/cache@v4
with:
driver-opts: network=host

- name: Build Docker image
id: image
uses: docker/build-push-action@v6
path: ~/conda_pkgs_dir
key:
${{ runner.os }}-conda-${{ hashFiles('environment-${{ env.PYTHON_VERSION }}-linux.yml') }}

- name: Compiler cache
uses: hendrikmuhs/[email protected]
with:
# push and load may not be set together at the moment
push: true
load: false
context: .
tags: ${{ env.BUILD_IMAGE }}
target: with-targets
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
NUMPROC=6
USE_MAKEFLAGS=-k V=0 SAGE_NUM_THREADS=4 --output-sync=recurse
TARGETS_PRE=build/make/Makefile
TARGETS=ci-build-with-fallback

- name: Start container
id: container
# Try to continue when "exporting to GitHub Actions Cache" failed with timeout
if: (success() || failure())
run: |
docker run --name BUILD -dit \
--mount type=bind,src=$(pwd),dst=$(pwd) \
--workdir $(pwd) \
${{ env.BUILD_IMAGE }} /bin/sh
key: ${{ runner.os }}-meson-${{ env.PYTHON_VERSION }}

#
# On PRs and pushes to branches
#

- name: Update system packages
id: packages
if: (success() || failure()) && steps.container.outcome == 'success'
- name: Setup Conda environment
uses: conda-incubator/setup-miniconda@v3
with:
python-version: ${{ env.PYTHON_VERSION }}
# Disabled for now due to
# https://github.com/conda-incubator/setup-miniconda/issues/379
# miniforge-version: latest
use-mamba: true
channels: conda-forge
channel-priority: true
activate-environment: sage-dev
environment-file: environment-${{ env.PYTHON_VERSION }}-linux.yml

- name: Build Sage
shell: bash -l {0}
run: |
export PATH="build/bin:$PATH"
eval $(sage-print-system-package-command auto update)
eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip)
eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive texlive_luatex free_fonts xindy)
shell: sh .github/workflows/docker-exec-script.sh BUILD /sage {0}
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
export CC="ccache $CC"
export CXX="ccache $CXX"
pip install --no-build-isolation --config-settings=builddir=builddir . -v

- name: Build doc (PDF)
id: docbuild
if: (success() || failure()) && steps.packages.outcome == 'success'
- name: Build documentation
shell: bash -l {0}
run: |
export MAKE="make -j5 --output-sync=recurse" SAGE_NUM_THREADS=5
make doc-clean doc-uninstall; make sagemath_doc_html-build-deps sagemath_doc_pdf-no-deps
shell: sh .github/workflows/docker-exec-script.sh BUILD /sage {0}
sudo DEBIAN_FRONTEND=noninteractive sudo apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install $(build/bin/sage-get-system-packages debian texlive texlive_luatex free_fonts xindy)
meson compile -C builddir doc-pdf
env:
SAGE_DOCBUILD_OPTS: "--include-tests-blocks"

- name: Copy doc
id: copy
if: (success() || failure()) && steps.docbuild.outcome == 'success'
run: |
mkdir -p ./doc
# We copy everything to a local folder
docker cp BUILD:/sage/local/share/doc/sage/pdf doc
cp -r builddir/src/doc/pdf doc/
# Zip everything for increased performance
zip -r doc-pdf.zip doc

- name: Upload doc
if: (success() || failure()) && steps.copy.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: doc-pdf
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/doc-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ env:
PYTHON_VERSION: 3.11

jobs:
build-doc:
doc-html:
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ extra = [
"pkg:generic/qepcad",
"pkg:generic/tides",
]
docs-pdf = [
"pkg:generic/latexmk",
"pkg:generic/lualatex",
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is free_fonts and xindy not needed to be included here?


[dependency-groups]
test = ["pytest", "pytest-xdist", "coverage"]
Expand Down
34 changes: 29 additions & 5 deletions src/sage_docbuild/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@

EXAMPLES::

sage: from sage_docbuild.builders import DocBuilder

Check failure on line 177 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_dir[0]>", line 1, in <module> from sage_docbuild.builders import DocBuilder ModuleNotFoundError: No module named 'sage_docbuild'
sage: from sage_docbuild.build_options import BuildOptions

Check failure on line 178 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_dir[1]>", line 1, in <module> from sage_docbuild.build_options import BuildOptions ModuleNotFoundError: No module named 'sage_docbuild'
sage: import tempfile
sage: with tempfile.TemporaryDirectory() as directory:

Check failure on line 180 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_dir[3]>", line 2, in <module> options = BuildOptions(output_dir=Path(directory), source_dir=Path('src/doc')) ^^^^^^^^^^^^ NameError: name 'BuildOptions' is not defined
....: options = BuildOptions(output_dir=Path(directory), source_dir=Path('src/doc'))
....: builder = DocBuilder('en/tutorial', options)
....: builder._output_dir('html')
Expand All @@ -196,10 +196,10 @@

EXAMPLES::

sage: from sage_docbuild.builders import DocBuilder

Check failure on line 199 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder.Path[0]>", line 1, in <module> from sage_docbuild.builders import DocBuilder ModuleNotFoundError: No module named 'sage_docbuild'
sage: from sage_docbuild.build_options import BuildOptions

Check failure on line 200 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder.Path[1]>", line 1, in <module> from sage_docbuild.build_options import BuildOptions ModuleNotFoundError: No module named 'sage_docbuild'
sage: import tempfile
sage: with tempfile.TemporaryDirectory() as directory:

Check failure on line 202 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder.Path[3]>", line 2, in <module> options = BuildOptions(output_dir=Path(directory), source_dir=Path('src/doc')) ^^^^^^^^^^^^ NameError: name 'BuildOptions' is not defined
....: options = BuildOptions(output_dir=Path(directory), source_dir=Path('src/doc'))
....: builder = DocBuilder('en/tutorial', options)
....: builder._doctrees_dir()
Expand All @@ -215,10 +215,10 @@

EXAMPLES::

sage: from sage_docbuild.builders import DocBuilder

Check failure on line 218 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_formats[0]>", line 1, in <module> from sage_docbuild.builders import DocBuilder ModuleNotFoundError: No module named 'sage_docbuild'
sage: from sage_docbuild.build_options import BuildOptions

Check failure on line 219 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_formats[1]>", line 1, in <module> from sage_docbuild.build_options import BuildOptions ModuleNotFoundError: No module named 'sage_docbuild'
sage: options = BuildOptions(source_dir=Path('src/doc'))

Check failure on line 220 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_formats[2]>", line 1, in <module> options = BuildOptions(source_dir=Path('src/doc')) ^^^^^^^^^^^^ NameError: name 'BuildOptions' is not defined
sage: builder = DocBuilder('tutorial', options)

Check failure on line 221 in src/sage_docbuild/builders.py

View workflow job for this annotation

GitHub Actions / Conda (ubuntu, Python 3.12, new)

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 733, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/share/miniconda/envs/sage-dev/lib/python3.12/site-packages/sage/doctest/forker.py", line 1157, in compile_and_execute exec(compiled, globs) File "<doctest sage_docbuild.builders.DocBuilder._output_formats[3]>", line 1, in <module> builder = DocBuilder('tutorial', options) ^^^^^^^^^^ NameError: name 'DocBuilder' is not defined
sage: builder._output_formats()
['changes', 'html', 'htmlhelp', 'inventory', 'json', 'latex', 'linkcheck', 'pickle', 'web']
"""
Expand Down Expand Up @@ -265,13 +265,37 @@
with open(tex_file, 'w') as f:
f.write(ref)

make_target = "cd '%s' && $MAKE %s && mv -f *.pdf '%s'"
error_message = "failed to run $MAKE %s in %s"
make_cmd = os.environ.get('MAKE', 'make')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the user set MAKE='make -j5'? if so the command below would fail.

(it's encouraged that they set MAKEFLAGS=-j5 instead, but still…)

command = 'all-pdf'
logger.debug(f"Running {make_cmd} {command} in {tex_dir}")

proc = subprocess.run(
[make_cmd, command],
check=False, cwd=tex_dir,
capture_output=True,
text=True,
)

if proc.returncode != 0:
logger.error(f"stdout from {make_cmd}:\n{proc.stdout}")
logger.error(f"stderr from {make_cmd}:\n{proc.stderr}")
raise RuntimeError(f"failed to run {make_cmd} {command} in {tex_dir}")

if proc.stdout:
logger.debug(f"make stdout:\n{proc.stdout}")
if proc.stderr:
# Still surface stderr even on success, but at debug level
logger.debug(f"make stderr:\n{proc.stderr}")

# Move generated PDFs
for pdf in tex_dir.glob("*.pdf"):
try:
shutil.move(str(pdf), pdf_dir)
except Exception as e:
logger.error(f"Failed moving {pdf} to {pdf_dir}: {e}")
raise

if subprocess.call(make_target % (tex_dir, command, pdf_dir), close_fds=False, shell=True):
raise RuntimeError(error_message % (command, tex_dir))
logger.warning(f"Build finished. The built documents can be found in {pdf_dir}.")
logger.info(f"Build finished. The built documents can be found in {pdf_dir}.")

def clean(self, *args):
shutil.rmtree(self._doctrees_dir())
Expand Down
2 changes: 2 additions & 0 deletions tools/update-conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def get_dependencies(pyproject_toml: Path, python: str, platform: str) -> set[st
.replace("symengine", "python-symengine")
.replace("memory_allocator", "memory-allocator")
.replace("pkg:generic/r-lattice", "r-lattice")
.replace("pkg:generic/latexmk", "latexmk")
for req in all_requirements
}
# Exclude requirements not available on conda (for a given platform)
Expand All @@ -177,6 +178,7 @@ def get_dependencies(pyproject_toml: Path, python: str, platform: str) -> set[st
"sagemath_giac",
"pynormaliz", # due to https://github.com/sagemath/sage/issues/40214
"latte-integrale", # due to https://github.com/sagemath/sage/issues/40216
"pkg:generic/lualatex", # texlive-core doesn't include lualatex
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this by default include texlive into the conda environment? Since most users/developers of sage don't want to build documentation and tex live is very heavy, I'd rather not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've now uncommented the info in pyproject.toml so that it doesn't get included in the conda env (or any other env that reads the "external" info for that matter). But it's still there for people to look at it.

}
if platform in ("linux-aarch64", "osx-arm64"):
exclude_packages |= {
Expand Down
Loading