diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81ea4f054..a7cda7f91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,13 +54,39 @@ jobs: run: | python -m pip install --upgrade nox virtualenv + - name: Restore linkcheck baseline + if: matrix.noxenv == 'linkcheck' && github.event_name == 'pull_request' + uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + with: + path: .linkcheck-baseline/output.json + key: linkcheck-output-${{ github.event.pull_request.base.sha }} + restore-keys: | + linkcheck-output- + - name: Nox ${{ matrix.noxenv }} env: # Authenticate github.com requests during linkcheck to avoid rate limits. GITHUB_TOKEN: ${{ matrix.noxenv == 'linkcheck' && github.token || '' }} + # Ignore links that were already reported by the baseline linkcheck run. + LINKCHECK_IGNORE_FILE: >- + ${{ matrix.noxenv == 'linkcheck' && '.linkcheck-baseline/output.json' || '' }} run: | python -m nox -s ${{ matrix.noxenv }} + - name: Prepare linkcheck baseline + if: matrix.noxenv == 'linkcheck' && github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + mkdir -p .linkcheck-baseline + cp build/output.json .linkcheck-baseline/output.json + + - name: Save linkcheck baseline + if: matrix.noxenv == 'linkcheck' && github.event_name == 'push' && github.ref == 'refs/heads/main' + continue-on-error: true + uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + with: + path: .linkcheck-baseline/output.json + key: linkcheck-output-${{ github.sha }} + check: # This job does nothing and is only used for the branch protection diff --git a/source/conf.py b/source/conf.py index 22b0e5e36..f4922242e 100644 --- a/source/conf.py +++ b/source/conf.py @@ -1,8 +1,10 @@ # -- Project information --------------------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import json import os import pathlib +import re import sys _ROOT = pathlib.Path(__file__).resolve().parent.parent @@ -163,6 +165,20 @@ # Temporarily ignored due to expired TLS cert. r"https://kivy.org/.*", ] + +if _linkcheck_ignore_file := os.getenv("LINKCHECK_IGNORE_FILE"): + linkcheck_ignore_path = pathlib.Path(_linkcheck_ignore_file) + if linkcheck_ignore_path.is_file(): + with linkcheck_ignore_path.open(encoding="utf-8") as linkcheck_ignore_file: + for line in linkcheck_ignore_file: + try: + linkcheck_entry = json.loads(line) + except json.JSONDecodeError: + continue + + if linkcheck_uri := linkcheck_entry.get("uri"): + linkcheck_ignore.append(rf"^{re.escape(linkcheck_uri)}$") + linkcheck_retries = 2 linkcheck_timeout = 30 # Ignore anchors for common targets when we know they likely won't be found