Skip to content

Commit 3ec191b

Browse files
CI: create a CI for testing docs updates + solve different docs issues (#1045)
* CI: create a CI for testing docs updates * STY: apply ruff format to docs/conf.py Wrap the long for-loop tuple in StaticJupyterExecute.run to satisfy the 88-char line length, fixing the `ruff format --check` linter failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Update .github/workflows/docs.yml --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ae23cc6 commit 3ec191b

7 files changed

Lines changed: 175 additions & 1 deletion

File tree

.github/workflows/docs.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Documentation
2+
3+
on:
4+
# Only PRs targeting master (base branch = master) and pushes to master.
5+
pull_request:
6+
types: [opened, synchronize, reopened, ready_for_review]
7+
branches: [master]
8+
paths:
9+
- "docs/**"
10+
- "rocketpy/**" # docstrings feed the autodoc API reference
11+
- "pyproject.toml"
12+
- "requirements*"
13+
- ".readthedocs.yaml"
14+
- ".github/workflows/docs.yml"
15+
push:
16+
branches: [master]
17+
paths:
18+
- "docs/**"
19+
- "rocketpy/**"
20+
- "pyproject.toml"
21+
- "requirements*"
22+
- ".readthedocs.yaml"
23+
- ".github/workflows/docs.yml"
24+
25+
defaults:
26+
run:
27+
shell: bash
28+
29+
jobs:
30+
build-docs:
31+
runs-on: ubuntu-latest
32+
strategy:
33+
matrix:
34+
python-version: ["3.12"] # match the Read the Docs build environment
35+
env:
36+
MPLBACKEND: Agg
37+
# Render jupyter-execute cells as static code blocks instead of running
38+
# them. This keeps the check fast and deterministic: no simulations and,
39+
# crucially, no live network calls to external weather/data servers (which
40+
# make the full build slow and flaky). Read the Docs still executes the
41+
# cells to render live outputs; this job only validates the docs structure
42+
# (reStructuredText, cross-references, toctrees, autodoc API reference).
43+
DOCS_SKIP_EXECUTE: "1"
44+
steps:
45+
- uses: actions/checkout@main
46+
47+
- name: Install pandoc (required by nbsphinx)
48+
run: sudo apt-get update && sudo apt-get install -y pandoc
49+
50+
- name: Set up Python ${{ matrix.python-version }}
51+
uses: actions/setup-python@main
52+
with:
53+
python-version: ${{ matrix.python-version }}
54+
cache: "pip"
55+
cache-dependency-path: |
56+
docs/requirements.txt
57+
requirements.txt
58+
59+
- name: Install dependencies (mirrors .readthedocs.yaml)
60+
run: |
61+
python -m pip install --upgrade pip
62+
pip install -r docs/requirements.txt
63+
pip install -r requirements.txt
64+
pip install .[all]
65+
66+
- name: Cache Sphinx doctrees
67+
uses: actions/cache@main
68+
with:
69+
path: docs/_build/doctrees
70+
key: sphinx-doctrees-${{ github.ref }}-${{ hashFiles('docs/**', 'rocketpy/**') }}
71+
restore-keys: |
72+
sphinx-doctrees-${{ github.ref }}-
73+
sphinx-doctrees-
74+
75+
- name: Build docs (warnings-as-errors)
76+
working-directory: docs
77+
run: |
78+
sphinx-build -b html -W --keep-going \
79+
-d _build/doctrees \
80+
-w _build/sphinx-warnings.txt \
81+
. _build/html
82+
83+
- name: Surface Sphinx warnings as annotations
84+
if: always()
85+
run: |
86+
if [ -s docs/_build/sphinx-warnings.txt ]; then
87+
echo "::group::Sphinx warnings"
88+
cat docs/_build/sphinx-warnings.txt
89+
echo "::endgroup::"
90+
while IFS= read -r line; do
91+
echo "::warning::${line}"
92+
done < docs/_build/sphinx-warnings.txt
93+
else
94+
echo "No Sphinx warnings 🎉"
95+
fi
96+
97+
- name: Upload built HTML
98+
if: always()
99+
uses: actions/upload-artifact@main
100+
with:
101+
name: docs-html
102+
path: docs/_build/html
103+
if-no-files-found: error

docs/conf.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@
6767
"allow_errors": True, # Continue building even if cells raise errors
6868
}
6969

70+
# When DOCS_SKIP_EXECUTE=1, ``jupyter-execute`` directives are rendered as
71+
# static (non-executing) code blocks instead of running live code. This makes
72+
# structural doc builds fast and deterministic (no simulations, no network),
73+
# which is what the GitHub Actions docs check relies on. Read the Docs leaves
74+
# this unset, so it still executes the cells and renders their live outputs.
75+
skip_jupyter_execute = os.environ.get("DOCS_SKIP_EXECUTE") == "1"
76+
77+
# Some notebook cells use IPython shell escapes (e.g. ``!pip install rocketpy``)
78+
# which the Pygments Python lexer cannot tokenize. These are purely cosmetic
79+
# syntax-highlighting failures, so don't let them fail a warnings-as-errors build.
80+
suppress_warnings = ["misc.highlighting_failure"]
81+
7082
# Add any paths that contain templates here, relative to this directory.
7183
templates_path = ["_templates"]
7284

@@ -150,3 +162,46 @@
150162
html_file_suffix = ".html"
151163

152164
htmlhelp_basename = "rocketpy"
165+
166+
167+
def setup(app):
168+
"""Sphinx entry point for optional build-time customizations."""
169+
if skip_jupyter_execute:
170+
from docutils.parsers.rst import directives
171+
from sphinx.directives.code import CodeBlock
172+
173+
class StaticJupyterExecute(CodeBlock):
174+
"""Render ``jupyter-execute`` as a non-executing Python code block.
175+
176+
Accepts (and ignores) the ``jupyter-execute`` directive options so
177+
existing pages parse unchanged, but produces a plain highlighted
178+
code block instead of a live-executed cell.
179+
"""
180+
181+
required_arguments = 0
182+
optional_arguments = 1
183+
option_spec = dict(CodeBlock.option_spec)
184+
option_spec.update(
185+
{
186+
"hide-code": directives.flag,
187+
"hide-output": directives.flag,
188+
"code-below": directives.flag,
189+
"stderr": directives.flag,
190+
"raises": directives.unchanged,
191+
}
192+
)
193+
194+
def run(self):
195+
for key in (
196+
"hide-code",
197+
"hide-output",
198+
"code-below",
199+
"stderr",
200+
"raises",
201+
):
202+
self.options.pop(key, None)
203+
if not self.arguments:
204+
self.arguments = ["python3"]
205+
return super().run()
206+
207+
app.add_directive("jupyter-execute", StaticJupyterExecute, override=True)

docs/notebooks/getting_started.ipynb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,9 @@
15711571
}
15721572
],
15731573
"metadata": {
1574+
"nbsphinx": {
1575+
"orphan": true
1576+
},
15741577
"colab": {
15751578
"name": "getting_started.ipynb",
15761579
"provenance": [],

docs/notebooks/getting_started_colab.ipynb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,9 @@
813813
}
814814
],
815815
"metadata": {
816+
"nbsphinx": {
817+
"orphan": true
818+
},
816819
"colab": {
817820
"name": "getting_started.ipynb",
818821
"provenance": [],

docs/reference/classes/aero_surfaces/_BaseFin.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
:orphan:
2+
13
_BaseFin Class
24
--------------
35

docs/user/environment/1-atm-models/soundings.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@ http://weather.uwyo.edu/cgi-bin/sounding?region=samer&TYPE=TEXT%3ALIST&YEAR=2019
2222

2323
Initialize a new Environment instance:
2424

25-
.. jupyter-execute::
25+
.. note::
26+
27+
The example below is shown as static code (it is not executed during the
28+
documentation build) because it requires a live network request to an
29+
external University of Wyoming service. Run it locally to fetch the
30+
sounding and see the resulting atmospheric plots.
31+
32+
.. code-block:: python
2633
2734
from rocketpy import Environment
2835

docs/user/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ RocketPy's User Guide
2424
:caption: Special Case Simulations
2525

2626
Compare Flights Class<compare_flights.rst>
27+
Flight Comparator Class <flight_comparator.rst>
2728
Parachute Triggers (Acceleration-Based) <parachute_triggers.rst>
2829
Deployable Payload <deployable.rst>
2930
Air Brakes Example <airbrakes.rst>

0 commit comments

Comments
 (0)