Skip to content

Commit b1c2d2f

Browse files
rwgkjuenglin
andauthored
ci: use pre-commit for documentation Lychee checks (#3142)
* ci: run documentation link checks through pre-commit Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * ci: remove the obsolete Lychee hook update exception Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * docs: clarify Lychee report isolation and cache producers Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * docs: clarify rendered link checks in the docs build Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * ci: share the nightly Python version with its cache prefix Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * ci: clarify the authored Lychee hook display name Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * ci: extend successful link cache lifetime to three days Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * Fix Lychee test paths under symlinked temporary directories Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> * ci: trim the Lychee link-check implementation Reduce the code behind the pre-commit-based link checks without changing which checks run, how they fail, or how results are cached and retried. - Replace ci/tools/lychee_cache.py and its tests with a small composite action, .github/actions/lychee-links. It hashes the policy files with hashFiles(), restores and publishes the URL cache, runs the driver, and uploads reports, so the pre-commit, nightly, and docs-build workflows each make one call instead of repeating five to eight steps. - Drop LYCHEE_CACHE_DIR. The rendered hook always uses the gitignored .lychee-rendered directory. - Make nightly the only producer of the shared baselines. Linux pre-commit runs on the default branch no longer publish the authored cache. - Remove retry branches for native exit codes other than 0 and 2. The driver raises on those before retrying, so they could not run. - Fold the two helpers still in use from prepare_lychee_inputs.py into run_lychee.py and delete the module, whose authored-file selection has been done by the hook configuration since the Lychee action was removed. - Trim tests that duplicated each other or exercised removed paths, and shorten the README section. Signed-off-by: Ralf Juengling <rjuengling@nvidia.com> Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> --------- Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com> Signed-off-by: Ralf Juengling <rjuengling@nvidia.com> Co-authored-by: Ralf Juengling <rjuengling@nvidia.com>
1 parent 5797a44 commit b1c2d2f

18 files changed

Lines changed: 728 additions & 528 deletions

‎.github/actions/check-doc-links/action.yml‎

Lines changed: 0 additions & 114 deletions
This file was deleted.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: Check documentation links
6+
description: Run a configured Lychee pre-commit hook with the shared URL cache and retained reports
7+
8+
inputs:
9+
kind:
10+
description: "Which hook to run: authored or rendered"
11+
required: true
12+
policy:
13+
description: "check accepts up to 10 rate-limited URLs; cache-warm reports every unresolved link as a warning"
14+
default: check
15+
refresh:
16+
description: "Check links afresh and publish the successful results as the new baseline"
17+
default: "false"
18+
19+
# Callers provide Python and the checked-out repository; the build of any
20+
# rendered documentation must already be complete.
21+
runs:
22+
using: composite
23+
steps:
24+
- name: Describe the link cache
25+
id: cache
26+
shell: bash --noprofile --norc -euo pipefail {0}
27+
env:
28+
KIND: ${{ inputs.kind }}
29+
# Anything that can change a check result or the cache's meaning. The
30+
# hook configuration carries the native wheel pin and every hook option.
31+
POLICY_HASH: ${{ hashFiles('.pre-commit-config.yaml', 'lychee.toml', 'ci/tools/run_lychee.py', 'ci/tools/run_lychee_precommit.py', 'ci/tools/retry_lychee.py') }}
32+
run: |
33+
# Authored and rendered results stay apart: only rendered checks validate
34+
# fragments, and Lychee's cache does not record which validation ran.
35+
case "${KIND}" in
36+
authored) path=.lycheecache ;;
37+
rendered) path=.lychee-rendered/.lycheecache ;;
38+
*) echo "::error::Unknown link-check kind: ${KIND}"; exit 1 ;;
39+
esac
40+
prefix="lychee-v1-${KIND}-${POLICY_HASH}-baseline-"
41+
echo "path=${path}" >> "${GITHUB_OUTPUT}"
42+
echo "prefix=${prefix}" >> "${GITHUB_OUTPUT}"
43+
echo "key=${prefix}${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" >> "${GITHUB_OUTPUT}"
44+
45+
- name: Restore successful link checks
46+
# Refresh mode deliberately skips earlier URL results.
47+
if: ${{ inputs.refresh != 'true' }}
48+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
49+
with:
50+
path: ${{ steps.cache.outputs.path }}
51+
key: ${{ steps.cache.outputs.key }}
52+
restore-keys: ${{ steps.cache.outputs.prefix }}
53+
enableCrossOsArchive: true
54+
55+
- name: Check links through the configured pre-commit hook
56+
shell: bash --noprofile --norc -euo pipefail {0}
57+
env:
58+
KIND: ${{ inputs.kind }}
59+
POLICY: ${{ inputs.policy }}
60+
GITHUB_TOKEN: ${{ github.token }}
61+
run: |
62+
# Install into the interpreter that runs the driver, whatever shell
63+
# profile the caller's other steps use.
64+
python -m pip install pre-commit
65+
python ci/tools/run_lychee_precommit.py "${KIND}" --policy "${POLICY}" --max-attempts 3 \
66+
--report "${RUNNER_TEMP}/lychee-reports/lychee-${KIND}.json"
67+
68+
- name: Publish fresh successful link checks
69+
# Only nightly refreshes publish, so every pull request restores the same
70+
# baseline. Saving keeps original timestamps and never caches failures.
71+
if: ${{ !cancelled() && inputs.refresh == 'true' }}
72+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
73+
with:
74+
path: ${{ steps.cache.outputs.path }}
75+
key: ${{ steps.cache.outputs.key }}
76+
enableCrossOsArchive: true
77+
78+
- name: Upload link-check reports
79+
if: ${{ always() }}
80+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
81+
with:
82+
name: lychee-${{ inputs.kind }}-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}
83+
path: ${{ runner.temp }}/lychee-reports/
84+
if-no-files-found: ignore
85+
retention-days: 7

‎.github/dependabot.yml‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ updates:
3636
# Match hook repositories, leaving additional_dependencies pins unchanged.
3737
allow:
3838
- dependency-name: "https://github.com/*"
39-
# Lychee's hook revision, LYCHEE_VERSION argument, and CI binary pin must
40-
# be upgraded together in a coordinated manual update.
41-
ignore:
42-
- dependency-name: "https://github.com/lycheeverse/lychee"
4339

4440
groups:
4541
pre-commit-monthly:

‎.github/workflows/build-docs.yml‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,19 +284,21 @@ jobs:
284284
fi
285285
mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET}
286286
287-
# Keep link checks in the existing PR docs build, using the same revision
288-
# as its wheels. Nightly supplies shared caches for both kinds of inputs.
289-
- name: Check authored documentation links
287+
# Check links and anchors in the rendered HTML built above.
288+
# Links in authored Markdown and reST files are checked separately by the
289+
# ordinary Linux/Windows pre-commit jobs.
290+
# The link-check action runs in a non-login shell, so give it a known
291+
# interpreter instead of the conda environment used above.
292+
- name: Set up Python for link checks
290293
if: ${{ !inputs.is-release && startsWith(github.ref_name, 'pull-request/') }}
291-
timeout-minutes: 60
292-
uses: ./.github/actions/check-doc-links
294+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
293295
with:
294-
kind: authored
296+
python-version: "3.14"
295297

296-
- name: Check rendered documentation links
298+
- name: Check rendered documentation links through pre-commit
297299
if: ${{ !inputs.is-release && startsWith(github.ref_name, 'pull-request/') }}
298300
timeout-minutes: 60
299-
uses: ./.github/actions/check-doc-links
301+
uses: ./.github/actions/lychee-links
300302
with:
301303
kind: rendered
302304

‎.github/workflows/lychee.yml‎

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5-
# Build documentation nightly and warm the link cache, reporting unresolved links
6-
# as warnings. Full PR CI reuses successful checks in build-docs.yml.
7-
# Ordinary PR updates run pre-commit without Lychee and do not build docs here.
5+
# Warm authored and rendered link caches through the configured pre-commit
6+
# hooks. Ordinary PRs reuse authored results; full docs CI reuses rendered
7+
# results. Nightly starts afresh, reports unresolved links as warnings, and is
8+
# the only producer of both shared baselines.
89

910
name: "CI: Documentation links"
1011

@@ -50,6 +51,10 @@ jobs:
5051
fail-fast: false
5152
matrix:
5253
kind: [authored, rendered]
54+
env:
55+
PYTHONUTF8: "1"
56+
# Reuse the same minor version for Python setup and cache fallback.
57+
PYTHON_VERSION: "3.14"
5358
steps:
5459
- name: Checkout checked revision
5560
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -62,9 +67,20 @@ jobs:
6267
submodules: ${{ matrix.kind == 'rendered' }}
6368

6469
- name: Set up Python
70+
id: python
6571
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
6672
with:
67-
python-version: "3.14"
73+
python-version: ${{ env.PYTHON_VERSION }}
74+
75+
- name: Set pre-commit cache location
76+
run: echo "PRE_COMMIT_HOME=${RUNNER_TEMP}/pre-commit" >> "${GITHUB_ENV}"
77+
78+
- name: Restore pre-commit environments
79+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
80+
with:
81+
path: ${{ env.PRE_COMMIT_HOME }}
82+
key: pre-commit-${{ runner.os }}-py${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
83+
restore-keys: pre-commit-${{ runner.os }}-py${{ env.PYTHON_VERSION }}
6884

6985
- name: Setup pixi
7086
if: ${{ matrix.kind == 'rendered' }}
@@ -74,9 +90,9 @@ jobs:
7490
if: ${{ matrix.kind == 'rendered' }}
7591
run: pixi run --manifest-path cuda_core/pixi.toml -e docs docs-build-all-latest
7692

77-
- name: Check documentation links
78-
uses: ./.github/actions/check-doc-links
93+
- name: Check documentation links through pre-commit
94+
uses: ./.github/actions/lychee-links
7995
with:
8096
kind: ${{ matrix.kind }}
81-
refresh-cache: ${{ inputs.refresh-cache || false }}
82-
failure-policy: ${{ inputs.refresh-cache && 'cache-warm' || 'check' }}
97+
policy: ${{ inputs.refresh-cache && 'cache-warm' || 'check' }}
98+
refresh: ${{ inputs.refresh-cache || false }}

‎.github/workflows/pre-commit.yml‎

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
push:
1111
# PR events cover draft and fork PRs without also checking copy-pr-bot's
1212
# pull-request/N mirrors. Only the default branch needs a push check, and
13-
# it is the only ref that refreshes the saved cache (see the save step).
13+
# it is the only ref that saves the pre-commit environment cache.
1414
branches:
1515
- "main"
1616
- "ctk-next"
@@ -41,9 +41,10 @@ jobs:
4141
- name: Windows
4242
os: windows-latest
4343
env:
44-
# Full-CI docs builds and nightly check links. The installation reminder
45-
# is for developer machines; CI does not install a Git commit hook.
46-
SKIP: lychee,check-precommit-installed
44+
# The installation reminder is for developer machines; CI does not
45+
# install a Git commit hook. All other hooks, including Lychee, run.
46+
SKIP: check-precommit-installed
47+
PYTHONUTF8: "1"
4748
# Minor version used by setup-python and as the cache restore-key prefix.
4849
PYTHON_VERSION: "3.14"
4950
steps:
@@ -138,7 +139,19 @@ jobs:
138139
LYCHEE_SMOKE_DIR: ${{ steps.lychee-smoke.outputs.directory }}
139140
run: python ci/tools/smoke_test_lychee_precommit.py --cleanup "$LYCHEE_SMOKE_DIR"
140141

142+
# Warm only Lychee from the shared nightly baseline, retaining successful
143+
# checks between up to three attempts. The full suite below runs once:
144+
# formatter changes must remain failures. A missing baseline is supported;
145+
# the first pass then checks afresh.
146+
- name: Warm the Lychee cache
147+
uses: ./.github/actions/lychee-links
148+
with:
149+
kind: authored
150+
policy: cache-warm
151+
141152
- name: Run pre-commit
153+
env:
154+
GITHUB_TOKEN: ${{ github.token }}
142155
run: pre-commit run --all-files --show-diff-on-failure
143156

144157
- name: Save pre-commit cache

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ __pycache__/
1111
.cython-stdlib
1212
.cython-bindings
1313
.lycheecache
14+
.lychee-rendered/
1415
.pytest_cache/
1516
.benchmarks/
1617
*.cpp

0 commit comments

Comments
 (0)