diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81ea4f054..ae7f0660e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,13 +54,45 @@ jobs: run: | python -m pip install --upgrade nox virtualenv + - name: Restore linkcheck baseline + if: >- + ${{ matrix.noxenv == 'linkcheck' && + (github.event_name == 'pull_request' || github.event_name == 'merge_group') }} + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: build/linkcheck-baseline.json + key: linkcheck-${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }} + restore-keys: | + linkcheck- + - name: Nox ${{ matrix.noxenv }} env: # Authenticate github.com requests during linkcheck to avoid rate limits. GITHUB_TOKEN: ${{ matrix.noxenv == 'linkcheck' && github.token || '' }} + LINKCHECK_BASELINE: >- + ${{ matrix.noxenv == 'linkcheck' && + (github.event_name == 'pull_request' || github.event_name == 'merge_group') && + 'build/linkcheck-baseline.json' || '' }} run: | python -m nox -s ${{ matrix.noxenv }} + - name: Prepare linkcheck baseline + if: >- + ${{ always() && matrix.noxenv == 'linkcheck' && + github.event_name == 'push' && github.ref == 'refs/heads/main' && + hashFiles('build/output.json') != '' }} + run: cp build/output.json build/linkcheck-baseline.json + + - name: Save linkcheck baseline + if: >- + ${{ always() && matrix.noxenv == 'linkcheck' && + github.event_name == 'push' && github.ref == 'refs/heads/main' && + hashFiles('build/linkcheck-baseline.json') != '' }} + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: build/linkcheck-baseline.json + key: linkcheck-${{ 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 4516880ec..daa744e71 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 @@ -165,6 +167,18 @@ # Temporarily ignored due to expired TLS cert. r"https://kivy.org/.*", ] + +if _linkcheck_baseline := os.getenv("LINKCHECK_BASELINE"): + _baseline_path = pathlib.Path(_linkcheck_baseline) + if _baseline_path.is_file(): + for _record in _baseline_path.read_text(encoding="utf-8").splitlines(): + try: + _uri = json.loads(_record).get("uri") + except json.JSONDecodeError: + continue + if _uri: + linkcheck_ignore.append(rf"^{re.escape(_uri)}$") + linkcheck_retries = 2 linkcheck_timeout = 30 # Ignore anchors for common targets when we know they likely won't be found