Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 0 additions & 114 deletions .github/actions/check-doc-links/action.yml

This file was deleted.

85 changes: 85 additions & 0 deletions .github/actions/lychee-links/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0

name: Check documentation links
description: Run a configured Lychee pre-commit hook with the shared URL cache and retained reports

inputs:
kind:
description: "Which hook to run: authored or rendered"
required: true
policy:
description: "check accepts up to 10 rate-limited URLs; cache-warm reports every unresolved link as a warning"
default: check
refresh:
description: "Check links afresh and publish the successful results as the new baseline"
default: "false"

# Callers provide Python and the checked-out repository; the build of any
# rendered documentation must already be complete.
runs:
using: composite
steps:
- name: Describe the link cache
id: cache
shell: bash --noprofile --norc -euo pipefail {0}
env:
KIND: ${{ inputs.kind }}
# Anything that can change a check result or the cache's meaning. The
# hook configuration carries the native wheel pin and every hook option.
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') }}
run: |
# Authored and rendered results stay apart: only rendered checks validate
# fragments, and Lychee's cache does not record which validation ran.
case "${KIND}" in
authored) path=.lycheecache ;;
rendered) path=.lychee-rendered/.lycheecache ;;
*) echo "::error::Unknown link-check kind: ${KIND}"; exit 1 ;;
esac
prefix="lychee-v1-${KIND}-${POLICY_HASH}-baseline-"
echo "path=${path}" >> "${GITHUB_OUTPUT}"
echo "prefix=${prefix}" >> "${GITHUB_OUTPUT}"
echo "key=${prefix}${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" >> "${GITHUB_OUTPUT}"

- name: Restore successful link checks
# Refresh mode deliberately skips earlier URL results.
if: ${{ inputs.refresh != 'true' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.cache.outputs.path }}
key: ${{ steps.cache.outputs.key }}
restore-keys: ${{ steps.cache.outputs.prefix }}
enableCrossOsArchive: true

- name: Check links through the configured pre-commit hook
shell: bash --noprofile --norc -euo pipefail {0}
env:
KIND: ${{ inputs.kind }}
POLICY: ${{ inputs.policy }}
GITHUB_TOKEN: ${{ github.token }}
run: |
# Install into the interpreter that runs the driver, whatever shell
# profile the caller's other steps use.
python -m pip install pre-commit
python ci/tools/run_lychee_precommit.py "${KIND}" --policy "${POLICY}" --max-attempts 3 \
--report "${RUNNER_TEMP}/lychee-reports/lychee-${KIND}.json"

- name: Publish fresh successful link checks
# Only nightly refreshes publish, so every pull request restores the same
# baseline. Saving keeps original timestamps and never caches failures.
if: ${{ !cancelled() && inputs.refresh == 'true' }}
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.cache.outputs.path }}
key: ${{ steps.cache.outputs.key }}
enableCrossOsArchive: true

- name: Upload link-check reports
if: ${{ always() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: lychee-${{ inputs.kind }}-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/lychee-reports/
if-no-files-found: ignore
retention-days: 7
4 changes: 0 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ updates:
# Match hook repositories, leaving additional_dependencies pins unchanged.
allow:
- dependency-name: "https://github.com/*"
# Lychee's hook revision, LYCHEE_VERSION argument, and CI binary pin must
# be upgraded together in a coordinated manual update.
ignore:
- dependency-name: "https://github.com/lycheeverse/lychee"

groups:
pre-commit-monthly:
Expand Down
18 changes: 10 additions & 8 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -284,19 +284,21 @@ jobs:
fi
mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET}

# Keep link checks in the existing PR docs build, using the same revision
# as its wheels. Nightly supplies shared caches for both kinds of inputs.
- name: Check authored documentation links
# Check links and anchors in the rendered HTML built above.
# Links in authored Markdown and reST files are checked separately by the
# ordinary Linux/Windows pre-commit jobs.
# The link-check action runs in a non-login shell, so give it a known
# interpreter instead of the conda environment used above.
- name: Set up Python for link checks
if: ${{ !inputs.is-release && startsWith(github.ref_name, 'pull-request/') }}
timeout-minutes: 60
uses: ./.github/actions/check-doc-links
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
kind: authored
python-version: "3.14"

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

Expand Down
32 changes: 24 additions & 8 deletions .github/workflows/lychee.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
#
# SPDX-License-Identifier: Apache-2.0

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

name: "CI: Documentation links"

Expand Down Expand Up @@ -50,6 +51,10 @@ jobs:
fail-fast: false
matrix:
kind: [authored, rendered]
env:
PYTHONUTF8: "1"
# Reuse the same minor version for Python setup and cache fallback.
PYTHON_VERSION: "3.14"
steps:
- name: Checkout checked revision
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -62,9 +67,20 @@ jobs:
submodules: ${{ matrix.kind == 'rendered' }}

- name: Set up Python
id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
python-version: ${{ env.PYTHON_VERSION }}

- name: Set pre-commit cache location
run: echo "PRE_COMMIT_HOME=${RUNNER_TEMP}/pre-commit" >> "${GITHUB_ENV}"

- name: Restore pre-commit environments
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: pre-commit-${{ runner.os }}-py${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: pre-commit-${{ runner.os }}-py${{ env.PYTHON_VERSION }}

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

- name: Check documentation links
uses: ./.github/actions/check-doc-links
- name: Check documentation links through pre-commit
uses: ./.github/actions/lychee-links
with:
kind: ${{ matrix.kind }}
refresh-cache: ${{ inputs.refresh-cache || false }}
failure-policy: ${{ inputs.refresh-cache && 'cache-warm' || 'check' }}
policy: ${{ inputs.refresh-cache && 'cache-warm' || 'check' }}
refresh: ${{ inputs.refresh-cache || false }}
21 changes: 17 additions & 4 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
push:
# PR events cover draft and fork PRs without also checking copy-pr-bot's
# pull-request/N mirrors. Only the default branch needs a push check, and
# it is the only ref that refreshes the saved cache (see the save step).
# it is the only ref that saves the pre-commit environment cache.
branches:
- "main"
- "ctk-next"
Expand Down Expand Up @@ -41,9 +41,10 @@ jobs:
- name: Windows
os: windows-latest
env:
# Full-CI docs builds and nightly check links. The installation reminder
# is for developer machines; CI does not install a Git commit hook.
SKIP: lychee,check-precommit-installed
# The installation reminder is for developer machines; CI does not
# install a Git commit hook. All other hooks, including Lychee, run.
SKIP: check-precommit-installed
PYTHONUTF8: "1"
# Minor version used by setup-python and as the cache restore-key prefix.
PYTHON_VERSION: "3.14"
steps:
Expand Down Expand Up @@ -138,7 +139,19 @@ jobs:
LYCHEE_SMOKE_DIR: ${{ steps.lychee-smoke.outputs.directory }}
run: python ci/tools/smoke_test_lychee_precommit.py --cleanup "$LYCHEE_SMOKE_DIR"

# Warm only Lychee from the shared nightly baseline, retaining successful
# checks between up to three attempts. The full suite below runs once:
# formatter changes must remain failures. A missing baseline is supported;
# the first pass then checks afresh.
- name: Warm the Lychee cache
uses: ./.github/actions/lychee-links
with:
kind: authored
policy: cache-warm

- name: Run pre-commit
env:
GITHUB_TOKEN: ${{ github.token }}
run: pre-commit run --all-files --show-diff-on-failure

- name: Save pre-commit cache
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __pycache__/
.cython-stdlib
.cython-bindings
.lycheecache
.lychee-rendered/
.pytest_cache/
.benchmarks/
*.cpp
Expand Down
Loading
Loading