From 8e2d1db0f0eb735f723bff01561bdf74982d5c0a Mon Sep 17 00:00:00 2001 From: Benjamin Pettit Date: Tue, 29 Sep 2026 23:36:36 +1000 Subject: [PATCH] ci(docs): cache the gallery execution stamps, and publish a PR docs artifact The cache stores `doc/_build/html`, which does not make a docs build cheaper. sphinx-gallery skips an example only when `.py.md5` sits beside its generated rst in `doc/auto_examples`, and Sphinx tracks staleness in `doc/_build/doctrees`. The current cache holds neither directory, so every example re-executes on every run. On master push [33301489918](https://github.com/NeuroTechX/EEG-ExPy/actions/runs/33301489918/attempts/1) the cache hit, yet the examples still took 155 s to execute in total. Cache those two directories instead, so unchanged examples are skipped. Locally, a build drops from 145 s (every run today) to 28 s when no example changed. The key has two parts because each example's md5 covers only that example's file, so it is not affected by changes to the library, docs sources or docs environment. The prefix hashes `eegnb/**`, `doc/**`, the docs environment, `requirements.txt` and `setup.py`; the examples hash follows. A `restore-keys` fallback therefore only matches an entry built with the same prefix: an examples-only PR reuses the other examples' output, and a change to any file in the prefix triggers a full rebuild. Also adds `upload-artifact`, so reviewers can download a PR's rendered docs; `docs.yml` otherwise only publishes on push to `master`. The `master` deploy is unchanged. Related: #322 (draft) also adds an artifact step and deploys a live preview to `gh-pages/pr-preview/`. That push needs a write token, which fork `pull_request` runs don't get, so the artifact is the part that works everywhere. --- .github/workflows/docs.yml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index fa939a5a..1c4076e5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -48,20 +48,37 @@ jobs: echo "Changed examples: $CHANGED_EXAMPLES" fi - - name: Cache built documentation + - name: Cache executed gallery examples id: cache-docs if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' uses: actions/cache@v4 + env: + KEY_PREFIX: ${{ runner.os }}-sphinx-${{ hashFiles('eegnb/**/*.py', 'doc/**/*', 'environments/eeg-expy-docsbuild.yml', 'requirements.txt', 'setup.py') }} with: + # sphinx-gallery decides whether to re-run an example by comparing the + # example's md5 against `.py.md5` beside its generated rst in + # doc/auto_examples. path: | - doc/_build/html - key: ${{ runner.os }}-sphinx-${{ hashFiles('examples/**/*.py', 'doc/**/*', 'conf.py') }} + doc/auto_examples + doc/_build/doctrees + # Two-part key. The per-example md5 covers only the example's file, so + # the prefix pins what it is not affected by -- library, docs sources, + # docs environment. A prefix fallback only reuses stamps built with all + # of those unchanged. + key: ${{ env.KEY_PREFIX }}-${{ hashFiles('examples/**/*.py') }} restore-keys: | - ${{ runner.os }}-sphinx- + ${{ env.KEY_PREFIX }}- - name: Build docs run: make docs + - name: Upload built docs + uses: actions/upload-artifact@v4 + with: + name: docs-build-preview + path: doc/_build/html + retention-days: 14 + - name: Deploy Docs uses: peaceiris/actions-gh-pages@v3 if: github.event_name == 'push' && github.ref == 'refs/heads/master' # TODO: Deploy seperate develop-version of docs?