Skip to content

Commit c3d63c9

Browse files
committed
Check only new links in pull requests
1 parent ab49948 commit c3d63c9

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

.github/workflows/test.yml

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,11 @@ jobs:
2525
if: ${{ github.repository_owner == 'pypa' || github.event_name != 'schedule' }}
2626
runs-on: ubuntu-latest
2727
timeout-minutes: 20
28-
continue-on-error: >-
29-
${{ fromJSON(matrix.continue-on-error) }}
3028
strategy:
3129
matrix:
3230
noxenv:
3331
- build
34-
continue-on-error:
35-
- false
36-
include:
37-
- noxenv: linkcheck
38-
continue-on-error: >- # Don't block PRs on linkcheck unrelated failures
39-
${{ toJSON(github.event_name == 'pull_request') }}
32+
- linkcheck
4033

4134
steps:
4235
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -50,17 +43,44 @@ jobs:
5043
cache: 'pip'
5144
cache-dependency-path: 'requirements.txt'
5245

46+
- name: Restore linkcheck report
47+
if: matrix.noxenv == 'linkcheck' && github.event_name == 'pull_request'
48+
id: linkcheck-cache
49+
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
50+
with:
51+
path: build/output.json
52+
key: linkcheck-${{ github.event.pull_request.base.sha }}
53+
restore-keys: |
54+
linkcheck-
55+
5356
- name: Install dependencies
5457
run: |
5558
python -m pip install --upgrade nox virtualenv
5659
5760
- name: Nox ${{ matrix.noxenv }}
61+
id: nox
62+
continue-on-error: ${{ matrix.noxenv == 'linkcheck' && github.event_name == 'pull_request' }}
5863
env:
5964
# Authenticate github.com requests during linkcheck to avoid rate limits.
6065
GITHUB_TOKEN: ${{ matrix.noxenv == 'linkcheck' && github.token || '' }}
6166
run: |
6267
python -m nox -s ${{ matrix.noxenv }}
6368
69+
- name: Fail on newly added broken links
70+
if: >-
71+
matrix.noxenv == 'linkcheck' &&
72+
github.event_name == 'pull_request' &&
73+
steps.linkcheck-cache.outputs.cache-hit != '' &&
74+
steps.nox.outcome == 'failure'
75+
run: exit 1
76+
77+
- name: Save linkcheck report
78+
if: matrix.noxenv == 'linkcheck' && github.event_name != 'pull_request' && success()
79+
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
80+
with:
81+
path: build/output.json
82+
key: linkcheck-${{ github.sha }}
83+
6484

6585
check:
6686
# This job does nothing and is only used for the branch protection

source/conf.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# -- Project information ---------------------------------------------------------------
22
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
33

4+
import json
45
import os
56
import pathlib
7+
import re
68
import sys
79

810
_ROOT = pathlib.Path(__file__).resolve().parent.parent
@@ -167,6 +169,21 @@
167169
]
168170
linkcheck_retries = 2
169171
linkcheck_timeout = 30
172+
173+
# On pull requests, ignore links that were already checked on the default
174+
# branch. The cached JSONL report is refreshed after successful default-branch
175+
# linkcheck runs, so newly introduced links remain blocking.
176+
if os.getenv("GITHUB_EVENT_NAME") == "pull_request":
177+
previous_linkcheck_report = pathlib.Path("build/output.json")
178+
if previous_linkcheck_report.exists():
179+
for line in previous_linkcheck_report.read_text(encoding="utf-8").splitlines():
180+
try:
181+
uri = json.loads(line)["uri"]
182+
except (json.JSONDecodeError, KeyError, TypeError):
183+
continue
184+
if isinstance(uri, str):
185+
linkcheck_ignore.append(rf"^{re.escape(uri)}$")
186+
170187
# Ignore anchors for common targets when we know they likely won't be found
171188
linkcheck_anchors_ignore_for_url = [
172189
# GitHub synthesises anchors in JavaScript, so Sphinx can't find them in the HTML

0 commit comments

Comments
 (0)