Skip to content

ci: never publish a documentation build that produced no site - #67

Closed
snesmaeili wants to merge 1 commit into
mainfrom
ci/resilient-docs-build
Closed

ci: never publish a documentation build that produced no site#67
snesmaeili wants to merge 1 commit into
mainfrom
ci/resilient-docs-build

Conversation

@snesmaeili

@snesmaeili snesmaeili commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Complementary to #62, not a replacement. #62 fixes why the documentation build currently fails (the NoiseTools 503, the sys.exit(0) false-success paths, the broken citation target). This PR addresses how a failed or empty build reaches the live site. The two touch ci.yml and conf.py in different, non-conflicting hunks and can merge in either order.

1. Refuse to deploy a build that produced no site

https://mne.tools/mne-denoise/ returns 404 for every page right now. The reason is not just that recent builds failed — it is that the last successful deploy published nothing.

gh-pages at 0d1ff4b (deploy: cc22e2e, 2026-08-04) contains exactly two entries:

.nojekyll
_sphinx_design_static/

Zero index.html files. Because the deploy step uses force_orphan: true, that empty tree replaced the entire published site.

This adds a check between the build and the deploy:

- name: Verify the build produced a site
  run: |
    set -e
    test -s docs/_build/html/index.html
    test -s docs/_build/html/auto_examples/index.html

A build that did not produce a site can no longer replace a working one. This is worth having independently of any particular build fix — it converts a silent site-wipe into a loud CI failure.

2. Wildcard the gallery subsection order

Adding any new examples/ subdirectory containing .py files currently fails the entire documentation build:

sphinx.errors.ConfigError: The subsection folder '../examples/<name>' was not
found in the 'subsection_order' config. If you use an explicit
'subsection_order', you must specify all subsection folders or add '*' as a
wildcard to collect all not-listed subsection folders.

examples/tutorials and examples/output escape this today only because neither contains a .py file — so the trap is invisible until someone adds a directory. A trailing "*" sorts unlisted folders to the end instead.

Verification

Ran the CI invocation locally (sphinx -b html -W --keep-going, examples executing):

build succeeded.
194 HTML pages
36 gallery examples — asr 15, dss 12, zapline 6, sns 2, spectrum_interpolation 1
0 warnings

Changed from the first version of this PR

Originally this also carried a dataset-caching approach and the temporal.py citation fix. Both are already handled by #62 — and #62's render-without-executing policy is the better answer, since it avoids downloading ~1.5 GB in CI. Those commits have been dropped so there is no overlap.

Two small guards, complementary to #62 (which fixes why the build currently
fails). These address how a failed or empty build reaches the live site.

Refuse to deploy a build with no index.html. The GitHub Pages deploy uses
force_orphan, so it replaces the entire published tree. The last successful
deploy (2026-08-04) published a tree containing only .nojekyll and
_sphinx_design_static -- no index.html anywhere -- which is why
https://mne.tools/mne-denoise/ currently returns 404 for every page. A build
that did not produce index.html and auto_examples/index.html should never be
allowed to replace a working site.

Add a "*" wildcard to the sphinx-gallery subsection_order. Adding any new
examples/ subdirectory that contains .py files currently raises

    sphinx.errors.ConfigError: The subsection folder '../examples/<name>'
    was not found in the 'subsection_order' config.

and fails the entire documentation build. The wildcard sorts unlisted folders
to the end instead. (examples/tutorials and examples/output escape this today
only because neither contains a .py file.)

Verified with the CI invocation locally, sphinx -b html -W --keep-going:
build succeeded, 194 HTML pages, 0 warnings, 36 gallery examples.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6GFfnt85ZSjuRaDrETwpU
@snesmaeili
snesmaeili force-pushed the ci/resilient-docs-build branch from 129b164 to 1de102f Compare August 10, 2026 17:38
@snesmaeili snesmaeili changed the title ci: stop a transient upstream outage from taking the docs site down ci: never publish a documentation build that produced no site Aug 10, 2026
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.77%. Comparing base (f5b821c) to head (1de102f).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main      #67   +/-   ##
=======================================
  Coverage   95.77%   95.77%           
=======================================
  Files          68       68           
  Lines        8565     8565           
  Branches     1512     1512           
=======================================
  Hits         8203     8203           
  Misses        175      175           
  Partials      187      187           
Flag Coverage Δ
unittests 95.77% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@BabaSanfour
BabaSanfour deleted the ci/resilient-docs-build branch August 13, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants