From deec047a6ba740580f8014c711b2c1cc5d58ce9d Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Mon, 1 Jun 2026 15:35:06 -0400 Subject: [PATCH 01/22] Check versioned docs example links --- .github/workflows/build-docs.yml | 20 +++++++++++++------- cuda_bindings/docs/build_docs.sh | 16 ++++++++++++++-- cuda_bindings/docs/source/conf.py | 2 ++ cuda_core/docs/build_docs.sh | 14 ++++++++++++-- cuda_core/docs/source/conf.py | 2 ++ 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e95a50b2a0..62895ff2a9 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -91,14 +91,20 @@ jobs: if [[ ${{ inputs.is-release }} == "true" ]]; then FILE_HASH="*" - COMMIT_HASH="${{ inputs.git-tag }}" + DOCS_GITHUB_REF="${{ inputs.git-tag }}" + if [[ -z "${DOCS_GITHUB_REF}" ]]; then + DOCS_GITHUB_REF="${GITHUB_REF_NAME}" + fi + COMMIT_HASH="${DOCS_GITHUB_REF}" else FILE_HASH="${{ github.sha }}" - COMMIT_HASH="${{ github.sha }}" + DOCS_GITHUB_REF="${{ github.sha }}" + COMMIT_HASH="${DOCS_GITHUB_REF}" fi # make outputs from the previous job as env vars CUDA_CORE_ARTIFACT_BASENAME="cuda-core-python${PYTHON_VERSION_FORMATTED}-linux-64" + echo "CUDA_PYTHON_DOCS_GITHUB_REF=${DOCS_GITHUB_REF}" >> $GITHUB_ENV echo "COMMIT_HASH=${COMMIT_HASH}" >> $GITHUB_ENV echo "CUDA_CORE_ARTIFACT_BASENAME=${CUDA_CORE_ARTIFACT_BASENAME}" >> $GITHUB_ENV echo "CUDA_CORE_ARTIFACT_NAME=${CUDA_CORE_ARTIFACT_BASENAME}-${FILE_HASH}" >> $GITHUB_ENV @@ -210,9 +216,9 @@ jobs: run: | pushd cuda_python/docs/ if [[ "${{ inputs.is-release }}" == "false" ]]; then - ./build_all_docs.sh latest-only + DOCS_LINKCHECK=1 ./build_all_docs.sh latest-only else - ./build_all_docs.sh + DOCS_LINKCHECK=1 ./build_all_docs.sh # At release time, we don't want to update the latest docs rm -rf build/html/latest fi @@ -226,9 +232,9 @@ jobs: COMPONENT=$(echo "${{ inputs.component }}" | tr '-' '_') pushd ${COMPONENT}/docs/ if [[ "${{ inputs.is-release }}" == "false" ]]; then - ./build_docs.sh latest-only + DOCS_LINKCHECK=1 ./build_docs.sh latest-only else - ./build_docs.sh + DOCS_LINKCHECK=1 ./build_docs.sh # At release time, we don't want to update the latest docs rm -rf build/html/latest fi diff --git a/cuda_bindings/docs/build_docs.sh b/cuda_bindings/docs/build_docs.sh index 15a42b9346..ab52431c09 100755 --- a/cuda_bindings/docs/build_docs.sh +++ b/cuda_bindings/docs/build_docs.sh @@ -1,6 +1,6 @@ #!/bin/bash -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE set -ex @@ -30,7 +30,19 @@ if [[ "${LATEST_ONLY}" == "1" && -z "${BUILD_PREVIEW:-}" && -z "${BUILD_LATEST:- fi # build the docs (in parallel) -SPHINXOPTS="-j 4 -d build/.doctrees" make html +if [[ -z "${SPHINXOPTS:-}" ]]; then + HTML_SPHINXOPTS="-j 4 -d build/.doctrees" +else + HTML_SPHINXOPTS="${SPHINXOPTS}" +fi +SPHINXOPTS="${HTML_SPHINXOPTS}" make html + +if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then + if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then + LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + fi + SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_BINDINGS_VER}" +fi # for debugging/developing (conf.py), please comment out the above line and # use the line below instead, as we must build in serial to avoid getting diff --git a/cuda_bindings/docs/source/conf.py b/cuda_bindings/docs/source/conf.py index 69a05d6e52..45344cc471 100644 --- a/cuda_bindings/docs/source/conf.py +++ b/cuda_bindings/docs/source/conf.py @@ -27,6 +27,8 @@ def _github_examples_ref(): + if ref := os.environ.get("CUDA_PYTHON_DOCS_GITHUB_REF"): + return ref if int(os.environ.get("BUILD_PREVIEW", 0)) or int(os.environ.get("BUILD_LATEST", 0)): return "main" return f"v{release}" diff --git a/cuda_core/docs/build_docs.sh b/cuda_core/docs/build_docs.sh index 78038438bc..d723a8bdbf 100755 --- a/cuda_core/docs/build_docs.sh +++ b/cuda_core/docs/build_docs.sh @@ -1,6 +1,6 @@ #!/bin/bash -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 set -ex @@ -30,10 +30,20 @@ fi # build the docs. Allow callers to override SPHINXOPTS for serial/debug runs. if [[ -z "${SPHINXOPTS:-}" ]]; then - SPHINXOPTS="-W --keep-going -j 4 -d build/.doctrees" + HTML_SPHINXOPTS="-W --keep-going -j 4 -d build/.doctrees" +else + HTML_SPHINXOPTS="${SPHINXOPTS}" fi +SPHINXOPTS="${HTML_SPHINXOPTS}" make html +if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then + if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then + LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + fi + SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_CORE_VER}" +fi + # to support version dropdown menu cp ./versions.json build/html cp ./nv-versions.json build/html diff --git a/cuda_core/docs/source/conf.py b/cuda_core/docs/source/conf.py index 14d9329793..0549d3f0dc 100644 --- a/cuda_core/docs/source/conf.py +++ b/cuda_core/docs/source/conf.py @@ -28,6 +28,8 @@ def _github_examples_ref(): + if ref := os.environ.get("CUDA_PYTHON_DOCS_GITHUB_REF"): + return ref if int(os.environ.get("BUILD_PREVIEW", 0)) or int(os.environ.get("BUILD_LATEST", 0)): return "main" return f"cuda-core-v{release}" From 8c67216f81f726a98550a947867e0f30a27e4c92 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Mon, 1 Jun 2026 16:19:26 -0400 Subject: [PATCH 02/22] Add pathfinder docs linkcheck --- cuda_pathfinder/docs/build_docs.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/cuda_pathfinder/docs/build_docs.sh b/cuda_pathfinder/docs/build_docs.sh index a7889b58dd..7e1ae3992c 100755 --- a/cuda_pathfinder/docs/build_docs.sh +++ b/cuda_pathfinder/docs/build_docs.sh @@ -1,6 +1,6 @@ #!/bin/bash -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 set -ex @@ -25,8 +25,24 @@ if [[ -z "${SPHINX_CUDA_PATHFINDER_VER}" ]]; then | awk -F'+' '{print $1}') fi +if [[ "${LATEST_ONLY}" == "1" && -z "${BUILD_PREVIEW:-}" && -z "${BUILD_LATEST:-}" ]]; then + export BUILD_LATEST=1 +fi + # build the docs (in parallel) -SPHINXOPTS="-W --keep-going -j 4 -d build/.doctrees" make html +if [[ -z "${SPHINXOPTS:-}" ]]; then + HTML_SPHINXOPTS="-W --keep-going -j 4 -d build/.doctrees" +else + HTML_SPHINXOPTS="${SPHINXOPTS}" +fi +SPHINXOPTS="${HTML_SPHINXOPTS}" make html + +if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then + if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then + LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + fi + SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_PATHFINDER_VER}" +fi # for debugging/developing (conf.py), please comment out the above line and # use the line below instead, as we must build in serial to avoid getting From bad8f0f79e9e7b602ed55d1ca37df912545fd5ca Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Mon, 1 Jun 2026 16:58:56 -0400 Subject: [PATCH 03/22] Check docs example links locally --- cuda_bindings/docs/build_docs.sh | 14 +- cuda_bindings/docs/source/conf.py | 1 + cuda_core/docs/build_docs.sh | 14 +- cuda_core/docs/source/conf.py | 5 + cuda_core/docs/source/release/0.3.1-notes.rst | 6 +- cuda_pathfinder/docs/build_docs.sh | 14 +- cuda_python/docs/check_example_links.py | 125 ++++++++++++++++++ 7 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 cuda_python/docs/check_example_links.py diff --git a/cuda_bindings/docs/build_docs.sh b/cuda_bindings/docs/build_docs.sh index ab52431c09..ca2f49b103 100755 --- a/cuda_bindings/docs/build_docs.sh +++ b/cuda_bindings/docs/build_docs.sh @@ -38,10 +38,18 @@ fi SPHINXOPTS="${HTML_SPHINXOPTS}" make html if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then - LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then + DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" + elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then + DOCS_EXAMPLES_REF="main" + else + DOCS_EXAMPLES_REF="v${SPHINX_CUDA_BINDINGS_VER}" fi - SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_BINDINGS_VER}" + python ../../cuda_python/docs/check_example_links.py \ + --source-dir source \ + --examples-root cuda_bindings/examples \ + --expected-ref "${DOCS_EXAMPLES_REF}" \ + --placeholder cuda_bindings_github_ref fi # for debugging/developing (conf.py), please comment out the above line and diff --git a/cuda_bindings/docs/source/conf.py b/cuda_bindings/docs/source/conf.py index 45344cc471..297815a295 100644 --- a/cuda_bindings/docs/source/conf.py +++ b/cuda_bindings/docs/source/conf.py @@ -133,6 +133,7 @@ def _github_examples_ref(): def rewrite_source(app, docname, source): text = source[0] + text = text.replace("|cuda_bindings_github_ref|", GITHUB_EXAMPLES_REF) if docname.startswith("release/"): text = text.replace(".. module:: cuda.bindings\n\n", "", 1) diff --git a/cuda_core/docs/build_docs.sh b/cuda_core/docs/build_docs.sh index d723a8bdbf..0b14c3f436 100755 --- a/cuda_core/docs/build_docs.sh +++ b/cuda_core/docs/build_docs.sh @@ -38,10 +38,18 @@ SPHINXOPTS="${HTML_SPHINXOPTS}" make html if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then - LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then + DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" + elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then + DOCS_EXAMPLES_REF="main" + else + DOCS_EXAMPLES_REF="cuda-core-v${SPHINX_CUDA_CORE_VER}" fi - SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_CORE_VER}" + python ../../cuda_python/docs/check_example_links.py \ + --source-dir source \ + --examples-root cuda_core/examples \ + --expected-ref "${DOCS_EXAMPLES_REF}" \ + --placeholder cuda_core_github_ref fi # to support version dropdown menu diff --git a/cuda_core/docs/source/conf.py b/cuda_core/docs/source/conf.py index 0549d3f0dc..28d0f6add6 100644 --- a/cuda_core/docs/source/conf.py +++ b/cuda_core/docs/source/conf.py @@ -200,6 +200,11 @@ def skip_member(app, what, name, obj, skip, options): return None +def rewrite_source(app, docname, source): + source[0] = source[0].replace("|cuda_core_github_ref|", GITHUB_EXAMPLES_REF) + + def setup(app): app.connect("autodoc-process-docstring", autodoc_process_docstring) app.connect("autodoc-skip-member", skip_member) + app.connect("source-read", rewrite_source) diff --git a/cuda_core/docs/source/release/0.3.1-notes.rst b/cuda_core/docs/source/release/0.3.1-notes.rst index 82138763db..6783011d73 100644 --- a/cuda_core/docs/source/release/0.3.1-notes.rst +++ b/cuda_core/docs/source/release/0.3.1-notes.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: Apache-2.0 .. currentmodule:: cuda.core.experimental @@ -31,8 +31,8 @@ None. New examples ------------ -- Add a `CUDA graph `_ example. -- Add a `memory resource `_ example. +- Add a `CUDA graph `_ example. +- Add a `memory resource `_ example. Fixes and enhancements diff --git a/cuda_pathfinder/docs/build_docs.sh b/cuda_pathfinder/docs/build_docs.sh index 7e1ae3992c..598a51249b 100755 --- a/cuda_pathfinder/docs/build_docs.sh +++ b/cuda_pathfinder/docs/build_docs.sh @@ -38,10 +38,18 @@ fi SPHINXOPTS="${HTML_SPHINXOPTS}" make html if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -z "${LINKCHECK_SPHINXOPTS:-}" ]]; then - LINKCHECK_SPHINXOPTS="-W --keep-going -j 4 -d build/.linkcheck-doctrees" + if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then + DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" + elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then + DOCS_EXAMPLES_REF="main" + else + DOCS_EXAMPLES_REF="cuda-pathfinder-v${SPHINX_CUDA_PATHFINDER_VER}" fi - SPHINXOPTS="${LINKCHECK_SPHINXOPTS}" make linkcheck BUILDDIR="build/linkcheck/${SPHINX_CUDA_PATHFINDER_VER}" + python ../../cuda_python/docs/check_example_links.py \ + --source-dir source \ + --examples-root cuda_pathfinder/examples \ + --expected-ref "${DOCS_EXAMPLES_REF}" \ + --allow-empty fi # for debugging/developing (conf.py), please comment out the above line and diff --git a/cuda_python/docs/check_example_links.py b/cuda_python/docs/check_example_links.py new file mode 100644 index 0000000000..5f76c412ea --- /dev/null +++ b/cuda_python/docs/check_example_links.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +from __future__ import annotations + +import argparse +import re +import sys +from pathlib import Path +from urllib.parse import unquote + +CUDA_PYTHON_URL_RE = re.compile( + r"https://github\.com/NVIDIA/cuda-python/" + r"(?Pblob|tree)/" + r"(?P[^/\s<>`]+)/" + r"(?P[^\s<>`)]+)" +) +SOURCE_SUFFIXES = {".md", ".rst"} + + +def _source_files(source_dir: Path): + for path in sorted(source_dir.rglob("*")): + if path.suffix in SOURCE_SUFFIXES and path.is_file(): + yield path + + +def _normalize_url_path(url_path: str) -> str: + path = unquote(url_path) + for separator in ("#", "?"): + path = path.split(separator, 1)[0] + return path.rstrip(".") + + +def _is_within(path: str, root: str) -> bool: + return path == root or path.startswith(f"{root}/") + + +def _display_path(path: Path, repo_root: Path) -> str: + try: + return str(path.relative_to(repo_root)) + except ValueError: + return str(path) + + +def check_links(args: argparse.Namespace) -> int: + repo_root = args.repo_root.resolve() + source_dir = args.source_dir.resolve() + examples_root = args.examples_root.strip("/") + placeholder_ref = f"|{args.placeholder}|" if args.placeholder else None + checked = 0 + failures: list[str] = [] + + for source_path in _source_files(source_dir): + text = source_path.read_text(encoding="utf-8") + for match in CUDA_PYTHON_URL_RE.finditer(text): + url_path = _normalize_url_path(match.group("path")) + if not _is_within(url_path, examples_root): + continue + + checked += 1 + ref = match.group("ref") + kind = match.group("kind") + location = _display_path(source_path, repo_root) + target_path = Path(url_path) + target = repo_root / target_path + + if target_path.is_absolute() or ".." in target_path.parts: + failures.append(f"{location}: invalid repository path in {match.group(0)}") + continue + + if placeholder_ref and ref == placeholder_ref: + rendered_ref = args.expected_ref + elif ref == args.expected_ref: + rendered_ref = ref + else: + expected = placeholder_ref or args.expected_ref + failures.append(f"{location}: {match.group(0)} uses ref {ref!r}; expected {expected!r}") + rendered_ref = ref + + if kind == "blob" and not target.is_file(): + failures.append( + f"{location}: {match.group(0)} resolves to missing file " + f"{target.relative_to(repo_root)} at ref {rendered_ref}" + ) + elif kind == "tree" and not target.is_dir(): + failures.append( + f"{location}: {match.group(0)} resolves to missing directory " + f"{target.relative_to(repo_root)} at ref {rendered_ref}" + ) + + if checked == 0 and not args.allow_empty: + failures.append(f"No example links under {examples_root!r} found in {source_dir}") + + if failures: + sys.stderr.write("Example link check failed:\n") + for failure in failures: + sys.stderr.write(f" - {failure}\n") + return 1 + + sys.stdout.write(f"Checked {checked} example link(s) under {examples_root} against ref {args.expected_ref}\n") + return 0 + + +def parse_args(argv: list[str]) -> argparse.Namespace: + repo_root = Path(__file__).resolve().parents[2] + + parser = argparse.ArgumentParser(description="Validate cuda-python example links without probing GitHub.") + parser.add_argument("--source-dir", type=Path, required=True) + parser.add_argument("--examples-root", required=True) + parser.add_argument("--expected-ref", required=True) + parser.add_argument("--placeholder") + parser.add_argument("--repo-root", type=Path, default=repo_root) + parser.add_argument("--allow-empty", action="store_true") + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(sys.argv[1:] if argv is None else argv) + return check_links(args) + + +if __name__ == "__main__": + raise SystemExit(main()) From 3c880e665ca02f3866ee6af2683bb0775b6662e1 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 11:03:23 -0400 Subject: [PATCH 04/22] Add lychee docs link checking --- .gitignore | 1 + .pre-commit-config.yaml | 12 ++++++++++++ cuda_bindings/docs/source/conduct.rst | 4 ++-- cuda_bindings/docs/source/motivation.rst | 4 ++-- cuda_bindings/docs/source/overview.rst | 8 +++++--- cuda_bindings/docs/source/release/11.7.1-notes.rst | 4 +++- cuda_bindings/docs/source/release/11.8.0-notes.rst | 4 ++-- cuda_bindings/docs/source/release/12.9.6-notes.rst | 2 +- cuda_bindings/docs/source/release/13.1.1-notes.rst | 4 ++-- cuda_bindings/docs/source/release/13.2.0-notes.rst | 2 +- cuda_bindings/docs/source/support.rst | 4 ++-- cuda_core/docs/source/conduct.rst | 4 ++-- cuda_python/docs/source/release/12.9.5-notes.rst | 4 ++-- cuda_python/docs/source/release/12.9.6-notes.rst | 2 +- 14 files changed, 38 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 26f13b1d17..e15f36ccc4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ __pycache__/ # CUDA Python specific .cache/ +.lycheecache .pytest_cache/ .benchmarks/ *.cpp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 25fb48eca3..2fd4e8d836 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,6 +53,18 @@ repos: - stubgen-pyx==0.2.6 - Cython==3.2.4 + # Link checking for authored documentation files + - repo: https://github.com/lycheeverse/lychee + rev: 2bba271688c1abb1503097a064e6c3bc1d1b6a9b # frozen: lychee-v0.24.2 + hooks: + - id: lychee + args: + - --cache + - --max-concurrency=4 + - --max-retries=3 + - --no-progress + files: '\.(md|rst)$' + # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks rev: "3e8a8703264a2f4a69428a0aa4dcb512790b2c8c" # frozen: v6.0.0 diff --git a/cuda_bindings/docs/source/conduct.rst b/cuda_bindings/docs/source/conduct.rst index b70d9dd7ce..26d3f1e59f 100644 --- a/cuda_bindings/docs/source/conduct.rst +++ b/cuda_bindings/docs/source/conduct.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE Code of Conduct @@ -85,7 +85,7 @@ Attribution ----------- This Code of Conduct is adapted from the `Contributor Covenant `_, version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct/ For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq diff --git a/cuda_bindings/docs/source/motivation.rst b/cuda_bindings/docs/source/motivation.rst index 433cc16619..16bfd9745a 100644 --- a/cuda_bindings/docs/source/motivation.rst +++ b/cuda_bindings/docs/source/motivation.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE Motivation @@ -31,7 +31,7 @@ you get the best of both worlds: rapid iterative development with Python and the speed of a compiled language targeting both CPUs and NVIDIA GPUs. `CuPy `_ is a -`NumPy `_/`SciPy `_ compatible Array +`NumPy `_/`SciPy `_ compatible Array library, from `Preferred Networks `_, for GPU-accelerated computing with Python. CUDA Python simplifies the CuPy build and allows for a faster and smaller memory footprint when importing the CuPy diff --git a/cuda_bindings/docs/source/overview.rst b/cuda_bindings/docs/source/overview.rst index e0d269cb6b..8ada38bfd2 100644 --- a/cuda_bindings/docs/source/overview.rst +++ b/cuda_bindings/docs/source/overview.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE Overview @@ -38,8 +38,8 @@ The first thing to do is import the `Driver API `_ and `NVRTC `_ modules from the ``cuda.bindings`` package. Next, we consider how to store host data and pass it to the device. Different -approaches can be used to accomplish this and are described in `Preparing kernel -arguments `_. +approaches can be used to accomplish this and are described in +:ref:`Preparing kernel arguments `. In this example, we will use NumPy to store host data and pass it to the device, so let's import this dependency as well. @@ -308,6 +308,8 @@ maximize performance ({numref}``Figure 1``). Screenshot of Nsight Compute CLI output of ``cuda.bindings`` example. +.. _preparing-kernel-arguments: + Preparing kernel arguments -------------------------- diff --git a/cuda_bindings/docs/source/release/11.7.1-notes.rst b/cuda_bindings/docs/source/release/11.7.1-notes.rst index 0fbea248e3..385cfb6e23 100644 --- a/cuda_bindings/docs/source/release/11.7.1-notes.rst +++ b/cuda_bindings/docs/source/release/11.7.1-notes.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE CUDA Python 11.7.1 Release notes @@ -14,6 +14,8 @@ Highlights Limitations ----------- +.. _cuda-bindings-11-7-1-source-builds: + Source builds ^^^^^^^^^^^^^ diff --git a/cuda_bindings/docs/source/release/11.8.0-notes.rst b/cuda_bindings/docs/source/release/11.8.0-notes.rst index e24022142d..68e40bc325 100644 --- a/cuda_bindings/docs/source/release/11.8.0-notes.rst +++ b/cuda_bindings/docs/source/release/11.8.0-notes.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE CUDA Python 11.8.0 Release notes @@ -16,7 +16,7 @@ Highlights Source Builds ^^^^^^^^^^^^^ -CUDA Python source builds now parse CUDA headers located in $CUDA_HOME directory, enabling/disabling types and APIs if defined. Therefore this removes the need for CTK headers to have all types defined. By allowing minor variations, previous `11.7.1 mobile platform workaround `_ is no longer needed. +CUDA Python source builds now parse CUDA headers located in $CUDA_HOME directory, enabling/disabling types and APIs if defined. Therefore this removes the need for CTK headers to have all types defined. By allowing minor variations, previous :ref:`11.7.1 mobile platform workaround ` is no longer needed. It's still required that source builds use the latest CTK headers (i.e. “$CUDA_HOME/include” has latest CTK headers). diff --git a/cuda_bindings/docs/source/release/12.9.6-notes.rst b/cuda_bindings/docs/source/release/12.9.6-notes.rst index dd508ff147..2ba5f3d96f 100644 --- a/cuda_bindings/docs/source/release/12.9.6-notes.rst +++ b/cuda_bindings/docs/source/release/12.9.6-notes.rst @@ -31,7 +31,7 @@ Bugfixes * Fixed an issue where the ``CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL`` attribute was retrieved as an unsigned int, rather than a signed int. - (`PR #1336 `_) + (`PR #1336 `_) * Fixed a use-after-free in ``_HelperInputVoidPtr`` properties when backed by Python buffer objects. (`PR #1629 `_) diff --git a/cuda_bindings/docs/source/release/13.1.1-notes.rst b/cuda_bindings/docs/source/release/13.1.1-notes.rst index 37353cbe14..d4ef6af2d9 100644 --- a/cuda_bindings/docs/source/release/13.1.1-notes.rst +++ b/cuda_bindings/docs/source/release/13.1.1-notes.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE .. module:: cuda.bindings @@ -12,7 +12,7 @@ Highlights ---------- * Add missing driver & runtime bindings for functions new in CTK 13.1.0 - (`PR #1321 `_) + (`PR #1321 `_) Experimental ------------ diff --git a/cuda_bindings/docs/source/release/13.2.0-notes.rst b/cuda_bindings/docs/source/release/13.2.0-notes.rst index 4ea580c9c5..e470b896d5 100644 --- a/cuda_bindings/docs/source/release/13.2.0-notes.rst +++ b/cuda_bindings/docs/source/release/13.2.0-notes.rst @@ -39,7 +39,7 @@ Bugfixes * Fixed an issue where the ``CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL`` attribute was retrieved as an unsigned int, rather than a signed int. - (`PR #1336 `_) + (`PR #1336 `_) * Fixed ABI incompatibility bugs in cuFILE bindings introduced in v13.1.0. (`PR #1468 `_) * Fixed a use-after-free in ``_HelperInputVoidPtr`` properties when backed by diff --git a/cuda_bindings/docs/source/support.rst b/cuda_bindings/docs/source/support.rst index 4439d963c0..0ed4d023ef 100644 --- a/cuda_bindings/docs/source/support.rst +++ b/cuda_bindings/docs/source/support.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE .. _support: @@ -38,7 +38,7 @@ The NVIDIA CUDA Python team reserves rights to amend the above support policy. A however, will be announced to the users in advance. -.. _CUDA minor version compatibility: https://docs.nvidia.com/deploy/cuda-compatibility/#minor-version-compatibility +.. _CUDA minor version compatibility: https://docs.nvidia.com/deploy/cuda-compatibility/minor-version-compatibility.html .. _CPython EOL schedule: https://devguide.python.org/versions/ .. _built-in modules that are known to be thread-unsafe: https://github.com/python/cpython/issues/116738 .. _free-threaded interpreter: https://docs.python.org/3/howto/free-threading-python.html diff --git a/cuda_core/docs/source/conduct.rst b/cuda_core/docs/source/conduct.rst index 1c00f5c343..d6df40945a 100644 --- a/cuda_core/docs/source/conduct.rst +++ b/cuda_core/docs/source/conduct.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: Apache-2.0 Code of Conduct @@ -85,7 +85,7 @@ Attribution ----------- This Code of Conduct is adapted from the `Contributor Covenant `_, version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct/ For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq diff --git a/cuda_python/docs/source/release/12.9.5-notes.rst b/cuda_python/docs/source/release/12.9.5-notes.rst index a134a36f00..aac1dfa792 100644 --- a/cuda_python/docs/source/release/12.9.5-notes.rst +++ b/cuda_python/docs/source/release/12.9.5-notes.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE CUDA Python 12.9.5 Release notes @@ -8,7 +8,7 @@ CUDA Python 12.9.5 Release notes Included components ------------------- -* `cuda.bindings 12.9.5 `_ +* `cuda.bindings 12.9.5 `_ * `cuda.pathfinder 1.3.3 `_ diff --git a/cuda_python/docs/source/release/12.9.6-notes.rst b/cuda_python/docs/source/release/12.9.6-notes.rst index 86ed747cfc..b66e1e9ad5 100644 --- a/cuda_python/docs/source/release/12.9.6-notes.rst +++ b/cuda_python/docs/source/release/12.9.6-notes.rst @@ -7,7 +7,7 @@ CUDA Python 12.9.6 Release notes Included components ------------------- -* `cuda.bindings 12.9.6 `_ +* `cuda.bindings 12.9.6 `_ * `cuda.pathfinder 1.4.2 `_ Known issues From d6466e94800127f6b0cd2f4e521f6228945959b6 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 11:06:53 -0400 Subject: [PATCH 05/22] Skip lychee on pre-commit.ci --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2fd4e8d836..40121b6f0f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,6 +9,7 @@ ci: autoupdate_branch: '' autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate' autoupdate_schedule: quarterly + skip: [lychee] submodules: false # Please update the rev: SHAs below with this command: From ed504843b20f8ce88ebee058ffcecc7e77a68dc3 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 11:27:52 -0400 Subject: [PATCH 06/22] Check rendered doc preview links with lychee --- .github/workflows/build-docs.yml | 76 +++++++++++++- cuda_bindings/docs/build_docs.sh | 15 --- cuda_core/docs/build_docs.sh | 15 --- cuda_pathfinder/docs/build_docs.sh | 15 --- cuda_python/docs/check_example_links.py | 125 ------------------------ 5 files changed, 72 insertions(+), 174 deletions(-) delete mode 100644 cuda_python/docs/check_example_links.py diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 62895ff2a9..eb7197ccc9 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -216,9 +216,9 @@ jobs: run: | pushd cuda_python/docs/ if [[ "${{ inputs.is-release }}" == "false" ]]; then - DOCS_LINKCHECK=1 ./build_all_docs.sh latest-only + ./build_all_docs.sh latest-only else - DOCS_LINKCHECK=1 ./build_all_docs.sh + ./build_all_docs.sh # At release time, we don't want to update the latest docs rm -rf build/html/latest fi @@ -232,9 +232,9 @@ jobs: COMPONENT=$(echo "${{ inputs.component }}" | tr '-' '_') pushd ${COMPONENT}/docs/ if [[ "${{ inputs.is-release }}" == "false" ]]; then - DOCS_LINKCHECK=1 ./build_docs.sh latest-only + ./build_docs.sh latest-only else - DOCS_LINKCHECK=1 ./build_docs.sh + ./build_docs.sh # At release time, we don't want to update the latest docs rm -rf build/html/latest fi @@ -248,6 +248,11 @@ jobs: fi mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET} + - name: Write doc preview marker + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + run: | + echo "${{ github.sha }}" > artifacts/docs/.preview-commit + # TODO: Consider removing this step? - name: Upload doc artifacts uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 @@ -263,6 +268,69 @@ jobs: 'artifacts/empty_docs' }} pr-number: ${{ env.PR_NUMBER }} + - name: Wait for doc preview deployment + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + env: + PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} + run: | + marker_url="${PREVIEW_URL}/.preview-commit" + for attempt in {1..60}; do + marker=$(curl -fsSL "${marker_url}" || true) + if [[ "${marker}" == "${{ github.sha }}" ]]; then + echo "Doc preview is available at ${PREVIEW_URL}" + exit 0 + fi + echo "Waiting for doc preview marker ${marker_url} (${attempt}/60)" + sleep 10 + done + echo "error: doc preview marker did not update to ${{ github.sha }}" >&2 + exit 1 + + - name: Restore lychee cache + id: restore-lychee-cache + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: .lycheecache + key: docs-preview-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} + restore-keys: | + docs-preview-lychee-${{ env.PR_NUMBER }}- + + - name: Check doc preview links + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2 + with: + args: >- + --base-url https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }}/ + --root-dir ${{ github.workspace }}/artifacts/docs + --index-files index.html + --fallback-extensions html,htm + --include-fragments full + --cache + --max-cache-age 1d + --max-concurrency 16 + --host-concurrency 2 + --host-request-interval 250ms + --max-retries 3 + --retry-wait-time 5 + --timeout 30 + --no-progress + '${{ github.workspace }}/artifacts/docs/**/*.html' + fail: true + failIfEmpty: true + format: markdown + jobSummary: true + lycheeVersion: v0.24.2 + output: lychee-preview.md + token: ${{ github.token }} + + - name: Save lychee cache + if: ${{ always() && !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') && steps.restore-lychee-cache.outputs.cache-hit != 'true' && steps.restore-lychee-cache.outputs.cache-primary-key != '' }} + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: .lycheecache + key: ${{ steps.restore-lychee-cache.outputs.cache-primary-key }} + - name: Deploy doc update if: ${{ github.ref_name == 'main' || inputs.is-release }} uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0 diff --git a/cuda_bindings/docs/build_docs.sh b/cuda_bindings/docs/build_docs.sh index ca2f49b103..2ab1f08601 100755 --- a/cuda_bindings/docs/build_docs.sh +++ b/cuda_bindings/docs/build_docs.sh @@ -37,21 +37,6 @@ else fi SPHINXOPTS="${HTML_SPHINXOPTS}" make html -if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then - DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" - elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then - DOCS_EXAMPLES_REF="main" - else - DOCS_EXAMPLES_REF="v${SPHINX_CUDA_BINDINGS_VER}" - fi - python ../../cuda_python/docs/check_example_links.py \ - --source-dir source \ - --examples-root cuda_bindings/examples \ - --expected-ref "${DOCS_EXAMPLES_REF}" \ - --placeholder cuda_bindings_github_ref -fi - # for debugging/developing (conf.py), please comment out the above line and # use the line below instead, as we must build in serial to avoid getting # obsecure Sphinx errors diff --git a/cuda_core/docs/build_docs.sh b/cuda_core/docs/build_docs.sh index 0b14c3f436..28ae6dd07f 100755 --- a/cuda_core/docs/build_docs.sh +++ b/cuda_core/docs/build_docs.sh @@ -37,21 +37,6 @@ fi SPHINXOPTS="${HTML_SPHINXOPTS}" make html -if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then - DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" - elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then - DOCS_EXAMPLES_REF="main" - else - DOCS_EXAMPLES_REF="cuda-core-v${SPHINX_CUDA_CORE_VER}" - fi - python ../../cuda_python/docs/check_example_links.py \ - --source-dir source \ - --examples-root cuda_core/examples \ - --expected-ref "${DOCS_EXAMPLES_REF}" \ - --placeholder cuda_core_github_ref -fi - # to support version dropdown menu cp ./versions.json build/html cp ./nv-versions.json build/html diff --git a/cuda_pathfinder/docs/build_docs.sh b/cuda_pathfinder/docs/build_docs.sh index 598a51249b..4720cd458f 100755 --- a/cuda_pathfinder/docs/build_docs.sh +++ b/cuda_pathfinder/docs/build_docs.sh @@ -37,21 +37,6 @@ else fi SPHINXOPTS="${HTML_SPHINXOPTS}" make html -if [[ "${DOCS_LINKCHECK:-0}" == "1" ]]; then - if [[ -n "${CUDA_PYTHON_DOCS_GITHUB_REF:-}" ]]; then - DOCS_EXAMPLES_REF="${CUDA_PYTHON_DOCS_GITHUB_REF}" - elif [[ "${BUILD_PREVIEW:-0}" == "1" || "${BUILD_LATEST:-0}" == "1" ]]; then - DOCS_EXAMPLES_REF="main" - else - DOCS_EXAMPLES_REF="cuda-pathfinder-v${SPHINX_CUDA_PATHFINDER_VER}" - fi - python ../../cuda_python/docs/check_example_links.py \ - --source-dir source \ - --examples-root cuda_pathfinder/examples \ - --expected-ref "${DOCS_EXAMPLES_REF}" \ - --allow-empty -fi - # for debugging/developing (conf.py), please comment out the above line and # use the line below instead, as we must build in serial to avoid getting # obsecure Sphinx errors diff --git a/cuda_python/docs/check_example_links.py b/cuda_python/docs/check_example_links.py deleted file mode 100644 index 5f76c412ea..0000000000 --- a/cuda_python/docs/check_example_links.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 - -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE - -from __future__ import annotations - -import argparse -import re -import sys -from pathlib import Path -from urllib.parse import unquote - -CUDA_PYTHON_URL_RE = re.compile( - r"https://github\.com/NVIDIA/cuda-python/" - r"(?Pblob|tree)/" - r"(?P[^/\s<>`]+)/" - r"(?P[^\s<>`)]+)" -) -SOURCE_SUFFIXES = {".md", ".rst"} - - -def _source_files(source_dir: Path): - for path in sorted(source_dir.rglob("*")): - if path.suffix in SOURCE_SUFFIXES and path.is_file(): - yield path - - -def _normalize_url_path(url_path: str) -> str: - path = unquote(url_path) - for separator in ("#", "?"): - path = path.split(separator, 1)[0] - return path.rstrip(".") - - -def _is_within(path: str, root: str) -> bool: - return path == root or path.startswith(f"{root}/") - - -def _display_path(path: Path, repo_root: Path) -> str: - try: - return str(path.relative_to(repo_root)) - except ValueError: - return str(path) - - -def check_links(args: argparse.Namespace) -> int: - repo_root = args.repo_root.resolve() - source_dir = args.source_dir.resolve() - examples_root = args.examples_root.strip("/") - placeholder_ref = f"|{args.placeholder}|" if args.placeholder else None - checked = 0 - failures: list[str] = [] - - for source_path in _source_files(source_dir): - text = source_path.read_text(encoding="utf-8") - for match in CUDA_PYTHON_URL_RE.finditer(text): - url_path = _normalize_url_path(match.group("path")) - if not _is_within(url_path, examples_root): - continue - - checked += 1 - ref = match.group("ref") - kind = match.group("kind") - location = _display_path(source_path, repo_root) - target_path = Path(url_path) - target = repo_root / target_path - - if target_path.is_absolute() or ".." in target_path.parts: - failures.append(f"{location}: invalid repository path in {match.group(0)}") - continue - - if placeholder_ref and ref == placeholder_ref: - rendered_ref = args.expected_ref - elif ref == args.expected_ref: - rendered_ref = ref - else: - expected = placeholder_ref or args.expected_ref - failures.append(f"{location}: {match.group(0)} uses ref {ref!r}; expected {expected!r}") - rendered_ref = ref - - if kind == "blob" and not target.is_file(): - failures.append( - f"{location}: {match.group(0)} resolves to missing file " - f"{target.relative_to(repo_root)} at ref {rendered_ref}" - ) - elif kind == "tree" and not target.is_dir(): - failures.append( - f"{location}: {match.group(0)} resolves to missing directory " - f"{target.relative_to(repo_root)} at ref {rendered_ref}" - ) - - if checked == 0 and not args.allow_empty: - failures.append(f"No example links under {examples_root!r} found in {source_dir}") - - if failures: - sys.stderr.write("Example link check failed:\n") - for failure in failures: - sys.stderr.write(f" - {failure}\n") - return 1 - - sys.stdout.write(f"Checked {checked} example link(s) under {examples_root} against ref {args.expected_ref}\n") - return 0 - - -def parse_args(argv: list[str]) -> argparse.Namespace: - repo_root = Path(__file__).resolve().parents[2] - - parser = argparse.ArgumentParser(description="Validate cuda-python example links without probing GitHub.") - parser.add_argument("--source-dir", type=Path, required=True) - parser.add_argument("--examples-root", required=True) - parser.add_argument("--expected-ref", required=True) - parser.add_argument("--placeholder") - parser.add_argument("--repo-root", type=Path, default=repo_root) - parser.add_argument("--allow-empty", action="store_true") - return parser.parse_args(argv) - - -def main(argv: list[str] | None = None) -> int: - args = parse_args(sys.argv[1:] if argv is None else argv) - return check_links(args) - - -if __name__ == "__main__": - raise SystemExit(main()) From 4a90b21636b0c8bfa0b1bd66e8cb3b45ee89cb2f Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 12:00:24 -0400 Subject: [PATCH 07/22] Fix doc preview wait step --- .github/workflows/build-docs.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index eb7197ccc9..493b6c1015 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -272,19 +272,24 @@ jobs: if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} env: PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} + EXPECTED_SHA: ${{ github.sha }} run: | + preview_ready=0 marker_url="${PREVIEW_URL}/.preview-commit" for attempt in {1..60}; do marker=$(curl -fsSL "${marker_url}" || true) - if [[ "${marker}" == "${{ github.sha }}" ]]; then - echo "Doc preview is available at ${PREVIEW_URL}" - exit 0 + if [[ "${marker}" == "${EXPECTED_SHA}" ]]; then + preview_ready=1 + break fi echo "Waiting for doc preview marker ${marker_url} (${attempt}/60)" sleep 10 done - echo "error: doc preview marker did not update to ${{ github.sha }}" >&2 - exit 1 + if [[ "${preview_ready}" != "1" ]]; then + echo "error: doc preview marker did not update to ${EXPECTED_SHA}" >&2 + exit 1 + fi + echo "Doc preview is available at ${PREVIEW_URL}" - name: Restore lychee cache id: restore-lychee-cache From 8833364aece48cf2f9fb77a97933285deb73e43d Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 12:30:30 -0400 Subject: [PATCH 08/22] Use lychee-action default binary --- .github/workflows/build-docs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 493b6c1015..97900262e3 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -325,7 +325,6 @@ jobs: failIfEmpty: true format: markdown jobSummary: true - lycheeVersion: v0.24.2 output: lychee-preview.md token: ${{ github.token }} From 451cdb1120f4e1b5e0b0c2ce732a83cf5e27879a Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 12:42:07 -0400 Subject: [PATCH 09/22] Address docs review comments --- cuda_bindings/docs/source/conf.py | 7 +------ cuda_bindings/docs/source/release/12.9.6-notes.rst | 2 +- cuda_bindings/docs/source/release/13.1.1-notes.rst | 2 +- cuda_bindings/docs/source/release/13.2.0-notes.rst | 2 +- cuda_core/docs/source/conf.py | 5 ----- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/cuda_bindings/docs/source/conf.py b/cuda_bindings/docs/source/conf.py index 297815a295..1e27205fee 100644 --- a/cuda_bindings/docs/source/conf.py +++ b/cuda_bindings/docs/source/conf.py @@ -132,13 +132,8 @@ def _github_examples_ref(): def rewrite_source(app, docname, source): - text = source[0] - text = text.replace("|cuda_bindings_github_ref|", GITHUB_EXAMPLES_REF) - if docname.startswith("release/"): - text = text.replace(".. module:: cuda.bindings\n\n", "", 1) - - source[0] = text + source[0] = source[0].replace(".. module:: cuda.bindings\n\n", "", 1) suppress_warnings = [ diff --git a/cuda_bindings/docs/source/release/12.9.6-notes.rst b/cuda_bindings/docs/source/release/12.9.6-notes.rst index 2ba5f3d96f..d24671700b 100644 --- a/cuda_bindings/docs/source/release/12.9.6-notes.rst +++ b/cuda_bindings/docs/source/release/12.9.6-notes.rst @@ -31,7 +31,7 @@ Bugfixes * Fixed an issue where the ``CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL`` attribute was retrieved as an unsigned int, rather than a signed int. - (`PR #1336 `_) + (`PR #1451 `_) * Fixed a use-after-free in ``_HelperInputVoidPtr`` properties when backed by Python buffer objects. (`PR #1629 `_) diff --git a/cuda_bindings/docs/source/release/13.1.1-notes.rst b/cuda_bindings/docs/source/release/13.1.1-notes.rst index d4ef6af2d9..4725fe570c 100644 --- a/cuda_bindings/docs/source/release/13.1.1-notes.rst +++ b/cuda_bindings/docs/source/release/13.1.1-notes.rst @@ -12,7 +12,7 @@ Highlights ---------- * Add missing driver & runtime bindings for functions new in CTK 13.1.0 - (`PR #1321 `_) + (`PR #1337 `_) Experimental ------------ diff --git a/cuda_bindings/docs/source/release/13.2.0-notes.rst b/cuda_bindings/docs/source/release/13.2.0-notes.rst index e470b896d5..71d2e13e56 100644 --- a/cuda_bindings/docs/source/release/13.2.0-notes.rst +++ b/cuda_bindings/docs/source/release/13.2.0-notes.rst @@ -39,7 +39,7 @@ Bugfixes * Fixed an issue where the ``CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL`` attribute was retrieved as an unsigned int, rather than a signed int. - (`PR #1336 `_) + (`PR #1451 `_) * Fixed ABI incompatibility bugs in cuFILE bindings introduced in v13.1.0. (`PR #1468 `_) * Fixed a use-after-free in ``_HelperInputVoidPtr`` properties when backed by diff --git a/cuda_core/docs/source/conf.py b/cuda_core/docs/source/conf.py index 28d0f6add6..0549d3f0dc 100644 --- a/cuda_core/docs/source/conf.py +++ b/cuda_core/docs/source/conf.py @@ -200,11 +200,6 @@ def skip_member(app, what, name, obj, skip, options): return None -def rewrite_source(app, docname, source): - source[0] = source[0].replace("|cuda_core_github_ref|", GITHUB_EXAMPLES_REF) - - def setup(app): app.connect("autodoc-process-docstring", autodoc_process_docstring) app.connect("autodoc-skip-member", skip_member) - app.connect("source-read", rewrite_source) From fbc91e29f9beb7a436008017561fb03107f2a2f1 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 13:26:39 -0400 Subject: [PATCH 10/22] Use fixed lychee-action revision --- .github/workflows/build-docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 97900262e3..4d36691783 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -303,7 +303,7 @@ jobs: - name: Check doc preview links if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2 + uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout with: args: >- --base-url https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }}/ @@ -325,6 +325,7 @@ jobs: failIfEmpty: true format: markdown jobSummary: true + lycheeVersion: v0.24.2 output: lychee-preview.md token: ${{ github.token }} From a1ff9845ea50877323fdf2507422f917d0faf495 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 13:56:47 -0400 Subject: [PATCH 11/22] Fix lychee fragment option syntax --- .github/workflows/build-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 4d36691783..d013b3536c 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -310,7 +310,7 @@ jobs: --root-dir ${{ github.workspace }}/artifacts/docs --index-files index.html --fallback-extensions html,htm - --include-fragments full + --include-fragments=full --cache --max-cache-age 1d --max-concurrency 16 From 1bbd30a7d7ab2572224f9535cd8ff8a038995296 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 16:07:41 -0400 Subject: [PATCH 12/22] Check deployed docs preview links --- .github/workflows/build-docs.yml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index d013b3536c..a43de8b704 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -301,15 +301,26 @@ jobs: restore-keys: | docs-preview-lychee-${{ env.PR_NUMBER }}- + - name: Write lychee doc preview URL list + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + env: + PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} + run: | + find "${GITHUB_WORKSPACE}/artifacts/docs" -type f -name '*.html' -printf '%P\n' \ + | LC_ALL=C sort \ + | sed "s#^#${PREVIEW_URL}/#" > lychee-preview-urls.txt + if [[ ! -s lychee-preview-urls.txt ]]; then + echo "error: no rendered HTML pages found for lychee" >&2 + exit 1 + fi + wc -l lychee-preview-urls.txt + - name: Check doc preview links if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout with: args: >- - --base-url https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }}/ - --root-dir ${{ github.workspace }}/artifacts/docs - --index-files index.html - --fallback-extensions html,htm + --files-from ${{ github.workspace }}/lychee-preview-urls.txt --include-fragments=full --cache --max-cache-age 1d @@ -320,11 +331,10 @@ jobs: --retry-wait-time 5 --timeout 30 --no-progress - '${{ github.workspace }}/artifacts/docs/**/*.html' fail: true failIfEmpty: true format: markdown - jobSummary: true + jobSummary: false lycheeVersion: v0.24.2 output: lychee-preview.md token: ${{ github.token }} From 14c70d0ec19abb70f74cbe6c5be3c11b96fb826d Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 2 Jun 2026 17:03:19 -0400 Subject: [PATCH 13/22] Fix rendered docs linkcheck failures --- .github/workflows/build-docs.yml | 2 +- cuda_bindings/docs/source/conf.py | 11 +++++++- cuda_bindings/docs/source/install.rst | 4 +-- cuda_bindings/docs/source/module/driver.rst | 14 +++++----- cuda_bindings/docs/source/module/runtime.rst | 10 +++---- cuda_core/docs/source/conf.py | 12 ++++++++- cuda_core/docs/source/examples.rst | 26 +++++++++---------- cuda_core/docs/source/getting-started.rst | 4 +-- cuda_core/docs/source/interoperability.rst | 6 ++--- cuda_core/docs/source/release/0.3.1-notes.rst | 4 +-- cuda_pathfinder/docs/source/conf.py | 13 ++++++++-- cuda_python/docs/build_docs.sh | 6 ++++- cuda_python/docs/source/conf.py | 13 ++++++++-- 13 files changed, 83 insertions(+), 42 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index a43de8b704..4f03020639 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -306,7 +306,7 @@ jobs: env: PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} run: | - find "${GITHUB_WORKSPACE}/artifacts/docs" -type f -name '*.html' -printf '%P\n' \ + find "${GITHUB_WORKSPACE}/artifacts/docs" -type f -name '*.html' ! -path '*/_static/*' -printf '%P\n' \ | LC_ALL=C sort \ | sed "s#^#${PREVIEW_URL}/#" > lychee-preview-urls.txt if [[ ! -s lychee-preview-urls.txt ]]; then diff --git a/cuda_bindings/docs/source/conf.py b/cuda_bindings/docs/source/conf.py index 1e27205fee..64f28ace24 100644 --- a/cuda_bindings/docs/source/conf.py +++ b/cuda_bindings/docs/source/conf.py @@ -37,6 +37,15 @@ def _github_examples_ref(): GITHUB_EXAMPLES_REF = _github_examples_ref() +def _html_baseurl(): + docs_domain = os.environ.get("CUDA_PYTHON_DOCS_DOMAIN", "https://nvidia.github.io/cuda-python") + if int(os.environ.get("BUILD_PREVIEW", 0)): + return f"{docs_domain}/pr-preview/pr-{os.environ['PR_NUMBER']}/cuda-bindings/latest/" + if int(os.environ.get("BUILD_LATEST", 0)): + return f"{docs_domain}/cuda-bindings/latest/" + return f"{docs_domain}/cuda-bindings/{release}/" + + # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -76,7 +85,7 @@ def _github_examples_ref(): # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_baseurl = "docs" +html_baseurl = _html_baseurl() html_theme = "nvidia_sphinx_theme" html_theme_options = { "switcher": { diff --git a/cuda_bindings/docs/source/install.rst b/cuda_bindings/docs/source/install.rst index bb5a858525..ce99255c13 100644 --- a/cuda_bindings/docs/source/install.rst +++ b/cuda_bindings/docs/source/install.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE Installation @@ -99,7 +99,7 @@ Source builds require that the provided CUDA headers are of the same major.minor $ export CUDA_PATH=/usr/local/cuda -See `Environment Variables `_ for a description of other build-time environment variables. +See :doc:`Environment Variables ` for a description of other build-time environment variables. .. note:: diff --git a/cuda_bindings/docs/source/module/driver.rst b/cuda_bindings/docs/source/module/driver.rst index 49c633aa07..020633665b 100644 --- a/cuda_bindings/docs/source/module/driver.rst +++ b/cuda_bindings/docs/source/module/driver.rst @@ -406,25 +406,25 @@ Data types used by CUDA driver .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_GEQ - Wait until (int32_t)(*addr - value) >= 0 (or int64_t for 64 bit values). Note this is a cyclic comparison which ignores wraparound. (Default behavior.) + Wait until (int32_t)(\*addr - value) >= 0 (or int64_t for 64 bit values). Note this is a cyclic comparison which ignores wraparound. (Default behavior.) .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_EQ - Wait until *addr == value. + Wait until \*addr == value. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_AND - Wait until (*addr & value) != 0. + Wait until (\*addr & value) != 0. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_NOR - Wait until ~(*addr | value) != 0. Support for this operation can be queried with :py:obj:`~.cuDeviceGetAttribute()` and :py:obj:`~.CU_DEVICE_ATTRIBUTE_CAN_USE_STREAM_WAIT_VALUE_NOR`. + Wait until ~(\*addr | value) != 0. Support for this operation can be queried with :py:obj:`~.cuDeviceGetAttribute()` and :py:obj:`~.CU_DEVICE_ATTRIBUTE_CAN_USE_STREAM_WAIT_VALUE_NOR`. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_FLUSH @@ -506,19 +506,19 @@ Data types used by CUDA driver .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_OR - Performs an atomic OR: *(address) = *(address) | value + Performs an atomic OR: \*(address) = \*(address) | value .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_AND - Performs an atomic AND: *(address) = *(address) & value + Performs an atomic AND: \*(address) = \*(address) & value .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_ADD - Performs an atomic ADD: *(address) = *(address) + value + Performs an atomic ADD: \*(address) = \*(address) + value .. autoclass:: cuda.bindings.driver.CUstreamAtomicReductionDataType diff --git a/cuda_bindings/docs/source/module/runtime.rst b/cuda_bindings/docs/source/module/runtime.rst index 5f7b517756..4714cf8f13 100644 --- a/cuda_bindings/docs/source/module/runtime.rst +++ b/cuda_bindings/docs/source/module/runtime.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. .. SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE ------- @@ -299,7 +299,7 @@ Data types used by CUDA Runtime .. autoattribute:: cuda.bindings.runtime.cudaError_t.cudaErrorIncompatibleDriverContext - This indicates that the current context is not compatible with this the CUDA Runtime. This can only occur if you are using CUDA Runtime/Driver interoperability and have created an existing Driver context using the driver API. The Driver context may be incompatible either because the Driver context was created using an older version of the API, because the Runtime API call expects a primary driver context and the Driver context is not primary, or because the Driver context has been destroyed. Please see :py:obj:`~.Interactions`with the CUDA Driver API" for more information. + This indicates that the current context is not compatible with this the CUDA Runtime. This can only occur if you are using CUDA Runtime/Driver interoperability and have created an existing Driver context using the driver API. The Driver context may be incompatible either because the Driver context was created using an older version of the API, because the Runtime API call expects a primary driver context and the Driver context is not primary, or because the Driver context has been destroyed. Please see `Interactions with the CUDA Driver API`_ for more information. .. autoattribute:: cuda.bindings.runtime.cudaError_t.cudaErrorMissingConfiguration @@ -6403,11 +6403,11 @@ The types ::CUevent and cudaEvent_t are identical and may be used interchangeabl -The types ::CUarray and struct ::cudaArray * represent the same data type and may be used interchangeably by casting the two types between each other. +The types ``CUarray`` and ``struct cudaArray *`` represent the same data type and may be used interchangeably by casting the two types between each other. -In order to use a ::CUarray in a CUDA Runtime API function which takes a struct ::cudaArray *, it is necessary to explicitly cast the ::CUarray to a struct ::cudaArray *. +In order to use a ``CUarray`` in a CUDA Runtime API function which takes a ``struct cudaArray *``, it is necessary to explicitly cast the ``CUarray`` to a ``struct cudaArray *``. -In order to use a struct ::cudaArray * in a CUDA Driver API function which takes a ::CUarray, it is necessary to explicitly cast the struct ::cudaArray * to a ::CUarray . +In order to use a ``struct cudaArray *`` in a CUDA Driver API function which takes a ``CUarray``, it is necessary to explicitly cast the ``struct cudaArray *`` to a ``CUarray``. diff --git a/cuda_core/docs/source/conf.py b/cuda_core/docs/source/conf.py index 0549d3f0dc..451eb8b445 100644 --- a/cuda_core/docs/source/conf.py +++ b/cuda_core/docs/source/conf.py @@ -38,6 +38,15 @@ def _github_examples_ref(): GITHUB_EXAMPLES_REF = _github_examples_ref() +def _html_baseurl(): + docs_domain = os.environ.get("CUDA_PYTHON_DOCS_DOMAIN", "https://nvidia.github.io/cuda-python") + if int(os.environ.get("BUILD_PREVIEW", 0)): + return f"{docs_domain}/pr-preview/pr-{os.environ['PR_NUMBER']}/cuda-core/latest/" + if int(os.environ.get("BUILD_LATEST", 0)): + return f"{docs_domain}/cuda-core/latest/" + return f"{docs_domain}/cuda-core/{release}/" + + # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -46,6 +55,7 @@ def _github_examples_ref(): extensions = [ "sphinx.ext.autodoc", "sphinx.ext.autosummary", + "sphinx.ext.extlinks", "sphinx.ext.napoleon", "sphinx.ext.intersphinx", "sphinx.ext.extlinks", @@ -75,7 +85,7 @@ def _github_examples_ref(): # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_baseurl = "docs" +html_baseurl = _html_baseurl() html_theme = "nvidia_sphinx_theme" html_theme_options = { "switcher": { diff --git a/cuda_core/docs/source/examples.rst b/cuda_core/docs/source/examples.rst index e3b2ef8f3f..cf13961c6d 100644 --- a/cuda_core/docs/source/examples.rst +++ b/cuda_core/docs/source/examples.rst @@ -12,48 +12,48 @@ workflow. Compilation and kernel launch ----------------------------- -- :cuda-core-example:`vector_add.py` +- :cuda-core-example:`vector_add.py ` compiles and launches a simple vector-add kernel with CuPy arrays. -- :cuda-core-example:`saxpy.py` +- :cuda-core-example:`saxpy.py ` JIT-compiles a templated SAXPY kernel and launches both float and double instantiations. -- :cuda-core-example:`pytorch_example.py` +- :cuda-core-example:`pytorch_example.py ` launches a CUDA kernel with PyTorch tensors and a wrapped PyTorch stream. Multi-device and advanced launch configuration ---------------------------------------------- -- :cuda-core-example:`simple_multi_gpu_example.py` +- :cuda-core-example:`simple_multi_gpu_example.py ` compiles and launches kernels across multiple GPUs. -- :cuda-core-example:`thread_block_cluster.py` +- :cuda-core-example:`thread_block_cluster.py ` demonstrates thread block cluster launch configuration on Hopper-class GPUs. -- :cuda-core-example:`tma_tensor_map.py` +- :cuda-core-example:`tma_tensor_map.py ` demonstrates Tensor Memory Accelerator descriptors and TMA-based bulk copies. Linking and graphs ------------------ -- :cuda-core-example:`jit_lto_fractal.py` +- :cuda-core-example:`jit_lto_fractal.py ` uses JIT link-time optimization to link user-provided device code into a fractal workflow at runtime. -- :cuda-core-example:`cuda_graphs.py` +- :cuda-core-example:`cuda_graphs.py ` captures and replays a multi-kernel CUDA graph to reduce launch overhead. Interoperability and memory access ---------------------------------- -- :cuda-core-example:`memory_ops.py` +- :cuda-core-example:`memory_ops.py ` covers memory resources, pinned memory, device transfers, and DLPack interop. -- :cuda-core-example:`strided_memory_view_cpu.py` +- :cuda-core-example:`strided_memory_view_cpu.py ` uses ``StridedMemoryView`` with JIT-compiled CPU code via ``cffi``. -- :cuda-core-example:`strided_memory_view_gpu.py` +- :cuda-core-example:`strided_memory_view_gpu.py ` uses ``StridedMemoryView`` with JIT-compiled GPU code and foreign GPU buffers. -- :cuda-core-example:`gl_interop_plasma.py` +- :cuda-core-example:`gl_interop_plasma.py ` renders a CUDA-generated plasma effect through OpenGL interop without CPU copies. System inspection ----------------- -- :cuda-core-example:`show_device_properties.py` +- :cuda-core-example:`show_device_properties.py ` prints a detailed report of the CUDA devices available on the system. diff --git a/cuda_core/docs/source/getting-started.rst b/cuda_core/docs/source/getting-started.rst index fb2f0b22fc..e03ce23782 100644 --- a/cuda_core/docs/source/getting-started.rst +++ b/cuda_core/docs/source/getting-started.rst @@ -32,7 +32,7 @@ Example: Compiling and Launching a CUDA kernel ---------------------------------------------- To get a taste for ``cuda.core``, let's walk through a simple example that compiles and launches a vector addition kernel. -You can find the complete example in :cuda-core-example:`vector_add.py` +You can find the complete example in :cuda-core-example:`vector_add.py ` and browse the :doc:`examples page ` for the rest of the shipped workflows. @@ -80,7 +80,7 @@ Note the use of the ``name_expressions`` parameter to the :meth:`Program.compile Next, we retrieve the compiled kernel from the CUBIN and prepare the arguments and kernel configuration. We're using `CuPy `_ arrays as inputs for this example, but you can use PyTorch tensors too (see -:cuda-core-example:`pytorch_example.py` +:cuda-core-example:`pytorch_example.py ` and the :doc:`examples page `). .. code-block:: python diff --git a/cuda_core/docs/source/interoperability.rst b/cuda_core/docs/source/interoperability.rst index 4aa155ce5f..87347eb9d2 100644 --- a/cuda_core/docs/source/interoperability.rst +++ b/cuda_core/docs/source/interoperability.rst @@ -70,11 +70,11 @@ a few iterations to ensure correctness. for extracting the metadata (such as pointer address, shape, strides, and dtype) from any Python objects supporting either CAI or DLPack and returning a :class:`~utils.StridedMemoryView` object. See the -:cuda-core-example:`strided_memory_view_constructors.py` +:cuda-core-example:`strided_memory_view_constructors.py ` example for the explicit constructors, or -:cuda-core-example:`strided_memory_view_cpu.py` +:cuda-core-example:`strided_memory_view_cpu.py ` and -:cuda-core-example:`strided_memory_view_gpu.py` +:cuda-core-example:`strided_memory_view_gpu.py ` for decorator-based workflows. This provides a *concrete implementation* to both protocols that is **array-library-agnostic**, so that all Python projects can just rely on this without either re-implementing (the consumer-side of) diff --git a/cuda_core/docs/source/release/0.3.1-notes.rst b/cuda_core/docs/source/release/0.3.1-notes.rst index 6783011d73..8360d1b9eb 100644 --- a/cuda_core/docs/source/release/0.3.1-notes.rst +++ b/cuda_core/docs/source/release/0.3.1-notes.rst @@ -31,8 +31,8 @@ None. New examples ------------ -- Add a `CUDA graph `_ example. -- Add a `memory resource `_ example. +- Add a :cuda-core-example:`CUDA graph ` example. +- Add a :cuda-core-example:`memory resource ` example. Fixes and enhancements diff --git a/cuda_pathfinder/docs/source/conf.py b/cuda_pathfinder/docs/source/conf.py index f794eb9ee2..aa6cd964b5 100644 --- a/cuda_pathfinder/docs/source/conf.py +++ b/cuda_pathfinder/docs/source/conf.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2012-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2012-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # Configuration file for the Sphinx documentation builder. @@ -26,6 +26,15 @@ release = os.environ["SPHINX_CUDA_PATHFINDER_VER"] +def _html_baseurl(): + docs_domain = os.environ.get("CUDA_PYTHON_DOCS_DOMAIN", "https://nvidia.github.io/cuda-python") + if int(os.environ.get("BUILD_PREVIEW", 0)): + return f"{docs_domain}/pr-preview/pr-{os.environ['PR_NUMBER']}/cuda-pathfinder/latest/" + if int(os.environ.get("BUILD_LATEST", 0)): + return f"{docs_domain}/cuda-pathfinder/latest/" + return f"{docs_domain}/cuda-pathfinder/{release}/" + + # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -65,7 +74,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_baseurl = "docs" +html_baseurl = _html_baseurl() html_theme = "nvidia_sphinx_theme" html_theme_options = { "switcher": { diff --git a/cuda_python/docs/build_docs.sh b/cuda_python/docs/build_docs.sh index 97be962a1a..528b1c15c3 100755 --- a/cuda_python/docs/build_docs.sh +++ b/cuda_python/docs/build_docs.sh @@ -1,6 +1,6 @@ #!/bin/bash -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE set -ex @@ -25,6 +25,10 @@ if [[ -z "${SPHINX_CUDA_PYTHON_VER}" ]]; then | awk -F'+' '{print $1}') fi +if [[ "${LATEST_ONLY}" == "1" && -z "${BUILD_PREVIEW:-}" && -z "${BUILD_LATEST:-}" ]]; then + export BUILD_LATEST=1 +fi + # build the docs (in parallel) SPHINXOPTS="-j 4 -d build/.doctrees" make html diff --git a/cuda_python/docs/source/conf.py b/cuda_python/docs/source/conf.py index 454cec4973..1b1932be71 100644 --- a/cuda_python/docs/source/conf.py +++ b/cuda_python/docs/source/conf.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE # Configuration file for the Sphinx documentation builder. @@ -26,6 +26,15 @@ release = os.environ["SPHINX_CUDA_PYTHON_VER"] +def _html_baseurl(): + docs_domain = os.environ.get("CUDA_PYTHON_DOCS_DOMAIN", "https://nvidia.github.io/cuda-python") + if int(os.environ.get("BUILD_PREVIEW", 0)): + return f"{docs_domain}/pr-preview/pr-{os.environ['PR_NUMBER']}/latest/" + if int(os.environ.get("BUILD_LATEST", 0)): + return f"{docs_domain}/latest/" + return f"{docs_domain}/{release}/" + + # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -58,7 +67,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_baseurl = "docs" +html_baseurl = _html_baseurl() html_theme = "nvidia_sphinx_theme" html_theme_options = { "switcher": { From e7c5bac296eb2a4b7268ccc0abe5ecd66a5c317a Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Thu, 4 Jun 2026 12:50:32 -0400 Subject: [PATCH 14/22] Split rendered docs link check workflow --- .github/workflows/build-docs.yml | 97 ++++++------------------- .github/workflows/check-doc-links.yml | 100 ++++++++++++++++++++++++++ .github/workflows/ci.yml | 16 +++++ 3 files changed, 137 insertions(+), 76 deletions(-) create mode 100644 .github/workflows/check-doc-links.yml diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 4f03020639..0fa08246eb 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -253,55 +253,7 @@ jobs: run: | echo "${{ github.sha }}" > artifacts/docs/.preview-commit - # TODO: Consider removing this step? - - name: Upload doc artifacts - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 - with: - path: artifacts/ - retention-days: 3 - - - name: Deploy or clean up doc preview - if: ${{ !inputs.is-release }} - uses: ./.github/actions/doc_preview - with: - source-folder: ${{ (github.ref_name != 'main' && 'artifacts/docs') || - 'artifacts/empty_docs' }} - pr-number: ${{ env.PR_NUMBER }} - - - name: Wait for doc preview deployment - if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - env: - PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} - EXPECTED_SHA: ${{ github.sha }} - run: | - preview_ready=0 - marker_url="${PREVIEW_URL}/.preview-commit" - for attempt in {1..60}; do - marker=$(curl -fsSL "${marker_url}" || true) - if [[ "${marker}" == "${EXPECTED_SHA}" ]]; then - preview_ready=1 - break - fi - echo "Waiting for doc preview marker ${marker_url} (${attempt}/60)" - sleep 10 - done - if [[ "${preview_ready}" != "1" ]]; then - echo "error: doc preview marker did not update to ${EXPECTED_SHA}" >&2 - exit 1 - fi - echo "Doc preview is available at ${PREVIEW_URL}" - - - name: Restore lychee cache - id: restore-lychee-cache - if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 - with: - path: .lycheecache - key: docs-preview-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} - restore-keys: | - docs-preview-lychee-${{ env.PR_NUMBER }}- - - - name: Write lychee doc preview URL list + - name: Write doc preview link-check URL list if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} env: PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} @@ -315,36 +267,29 @@ jobs: fi wc -l lychee-preview-urls.txt - - name: Check doc preview links + - name: Upload doc preview link-check URL list if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: docs-preview-linkcheck-urls + path: lychee-preview-urls.txt + if-no-files-found: error + retention-days: 3 + + # TODO: Consider removing this step? + - name: Upload doc artifacts + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: - args: >- - --files-from ${{ github.workspace }}/lychee-preview-urls.txt - --include-fragments=full - --cache - --max-cache-age 1d - --max-concurrency 16 - --host-concurrency 2 - --host-request-interval 250ms - --max-retries 3 - --retry-wait-time 5 - --timeout 30 - --no-progress - fail: true - failIfEmpty: true - format: markdown - jobSummary: false - lycheeVersion: v0.24.2 - output: lychee-preview.md - token: ${{ github.token }} - - - name: Save lychee cache - if: ${{ always() && !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') && steps.restore-lychee-cache.outputs.cache-hit != 'true' && steps.restore-lychee-cache.outputs.cache-primary-key != '' }} - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + path: artifacts/ + retention-days: 3 + + - name: Deploy or clean up doc preview + if: ${{ !inputs.is-release }} + uses: ./.github/actions/doc_preview with: - path: .lycheecache - key: ${{ steps.restore-lychee-cache.outputs.cache-primary-key }} + source-folder: ${{ (github.ref_name != 'main' && 'artifacts/docs') || + 'artifacts/empty_docs' }} + pr-number: ${{ env.PR_NUMBER }} - name: Deploy doc update if: ${{ github.ref_name == 'main' || inputs.is-release }} diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml new file mode 100644 index 0000000000..b7a12ee08e --- /dev/null +++ b/.github/workflows/check-doc-links.yml @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +name: "CI: Check rendered docs links" + +on: + workflow_call: + inputs: + url-artifact: + description: "Artifact containing the rendered doc preview URL list" + required: false + default: docs-preview-linkcheck-urls + type: string + +jobs: + check: + name: Check rendered docs links + if: ${{ github.repository_owner == 'nvidia' && startsWith(github.ref_name, 'pull-request/') }} + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + pull-requests: read + defaults: + run: + shell: bash -el {0} + steps: + - name: Checkout ${{ github.event.repository.name }} + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Get PR number + uses: ./.github/actions/get_pr_number + + - name: Download doc preview link-check URL list + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ inputs.url-artifact }} + path: linkcheck-input + + - name: Wait for doc preview deployment + env: + PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} + EXPECTED_SHA: ${{ github.sha }} + run: | + preview_ready=0 + marker_url="${PREVIEW_URL}/.preview-commit" + for attempt in {1..60}; do + marker=$(curl -fsSL "${marker_url}" || true) + if [[ "${marker}" == "${EXPECTED_SHA}" ]]; then + preview_ready=1 + break + fi + echo "Waiting for doc preview marker ${marker_url} (${attempt}/60)" + sleep 10 + done + if [[ "${preview_ready}" != "1" ]]; then + echo "error: doc preview marker did not update to ${EXPECTED_SHA}" >&2 + exit 1 + fi + echo "Doc preview is available at ${PREVIEW_URL}" + + - name: Restore lychee cache + id: restore-lychee-cache + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: .lycheecache + key: docs-preview-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} + restore-keys: | + docs-preview-lychee-${{ env.PR_NUMBER }}- + + - name: Check doc preview links + uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout + with: + args: >- + --files-from ${{ github.workspace }}/linkcheck-input/lychee-preview-urls.txt + --include-fragments=full + --cache + --max-cache-age 1d + --max-concurrency 16 + --host-concurrency 2 + --host-request-interval 250ms + --max-retries 3 + --retry-wait-time 5 + --timeout 30 + --no-progress + fail: true + failIfEmpty: true + format: markdown + jobSummary: false + lycheeVersion: v0.24.2 + output: lychee-preview.md + token: ${{ github.token }} + + - name: Save lychee cache + if: ${{ always() && steps.restore-lychee-cache.outputs.cache-hit != 'true' && steps.restore-lychee-cache.outputs.cache-primary-key != '' }} + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: .lycheecache + key: ${{ steps.restore-lychee-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b510ecffc..0d52821c84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -415,6 +415,18 @@ jobs: with: is-release: ${{ github.ref_type == 'tag' }} + doc-linkcheck: + name: Docs link check + if: ${{ github.repository_owner == 'nvidia' && startsWith(github.ref_name, 'pull-request/') && needs.doc.result == 'success' }} + permissions: + actions: read + contents: read + pull-requests: read + needs: + - doc + secrets: inherit + uses: ./.github/workflows/check-doc-links.yml + checks: name: Check job status if: always() @@ -428,6 +440,7 @@ jobs: - test-linux-aarch64 - test-windows - doc + - doc-linkcheck steps: - name: Exit run: | @@ -463,6 +476,9 @@ jobs: if ${{ needs.doc.result == 'cancelled' || needs.doc.result == 'failure' }}; then exit 1 fi + if ${{ needs.doc-linkcheck.result == 'cancelled' || needs.doc-linkcheck.result == 'failure' }}; then + exit 1 + fi if ${{ needs.test-sdist-linux.result == 'cancelled' || needs.test-sdist-linux.result == 'failure' || needs.test-sdist-windows.result == 'cancelled' || From 7f7bfa6116443a6b47d31aed7f0987b750fa2f92 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Thu, 4 Jun 2026 12:57:08 -0400 Subject: [PATCH 15/22] Check rendered docs links locally --- .github/workflows/build-docs.yml | 20 ++------- .github/workflows/check-doc-links.yml | 59 ++++++++++++--------------- 2 files changed, 28 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 0fa08246eb..63eb04b898 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -253,26 +253,12 @@ jobs: run: | echo "${{ github.sha }}" > artifacts/docs/.preview-commit - - name: Write doc preview link-check URL list - if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - env: - PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} - run: | - find "${GITHUB_WORKSPACE}/artifacts/docs" -type f -name '*.html' ! -path '*/_static/*' -printf '%P\n' \ - | LC_ALL=C sort \ - | sed "s#^#${PREVIEW_URL}/#" > lychee-preview-urls.txt - if [[ ! -s lychee-preview-urls.txt ]]; then - echo "error: no rendered HTML pages found for lychee" >&2 - exit 1 - fi - wc -l lychee-preview-urls.txt - - - name: Upload doc preview link-check URL list + - name: Upload rendered docs for link checking if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: docs-preview-linkcheck-urls - path: lychee-preview-urls.txt + name: docs-rendered-html + path: artifacts/docs/ if-no-files-found: error retention-days: 3 diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml index b7a12ee08e..89366422c3 100644 --- a/.github/workflows/check-doc-links.yml +++ b/.github/workflows/check-doc-links.yml @@ -7,10 +7,10 @@ name: "CI: Check rendered docs links" on: workflow_call: inputs: - url-artifact: - description: "Artifact containing the rendered doc preview URL list" + docs-artifact: + description: "Artifact containing the rendered docs HTML tree" required: false - default: docs-preview-linkcheck-urls + default: docs-rendered-html type: string jobs: @@ -26,54 +26,45 @@ jobs: run: shell: bash -el {0} steps: - - name: Checkout ${{ github.event.repository.name }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Get PR number - uses: ./.github/actions/get_pr_number + - name: Extract PR number + run: | + PR_NUMBER="${GITHUB_REF_NAME#pull-request/}" + if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then + echo "error: cannot extract PR number from ref ${GITHUB_REF_NAME}" >&2 + exit 1 + fi + echo "PR_NUMBER=${PR_NUMBER}" >> "${GITHUB_ENV}" - - name: Download doc preview link-check URL list + - name: Download rendered docs uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: ${{ inputs.url-artifact }} - path: linkcheck-input + name: ${{ inputs.docs-artifact }} + path: rendered-docs - - name: Wait for doc preview deployment - env: - PREVIEW_URL: https://nvidia.github.io/cuda-python/pr-preview/pr-${{ env.PR_NUMBER }} - EXPECTED_SHA: ${{ github.sha }} + - name: Write rendered docs file list run: | - preview_ready=0 - marker_url="${PREVIEW_URL}/.preview-commit" - for attempt in {1..60}; do - marker=$(curl -fsSL "${marker_url}" || true) - if [[ "${marker}" == "${EXPECTED_SHA}" ]]; then - preview_ready=1 - break - fi - echo "Waiting for doc preview marker ${marker_url} (${attempt}/60)" - sleep 10 - done - if [[ "${preview_ready}" != "1" ]]; then - echo "error: doc preview marker did not update to ${EXPECTED_SHA}" >&2 + find "${GITHUB_WORKSPACE}/rendered-docs" -type f -name '*.html' ! -path '*/_static/*' \ + | LC_ALL=C sort > lychee-rendered-html-files.txt + if [[ ! -s lychee-rendered-html-files.txt ]]; then + echo "error: no rendered HTML pages found for lychee" >&2 exit 1 fi - echo "Doc preview is available at ${PREVIEW_URL}" + wc -l lychee-rendered-html-files.txt - name: Restore lychee cache id: restore-lychee-cache uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: .lycheecache - key: docs-preview-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} + key: docs-rendered-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} restore-keys: | - docs-preview-lychee-${{ env.PR_NUMBER }}- + docs-rendered-lychee-${{ env.PR_NUMBER }}- - - name: Check doc preview links + - name: Check rendered docs links uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout with: args: >- - --files-from ${{ github.workspace }}/linkcheck-input/lychee-preview-urls.txt + --files-from ${{ github.workspace }}/lychee-rendered-html-files.txt --include-fragments=full --cache --max-cache-age 1d @@ -89,7 +80,7 @@ jobs: format: markdown jobSummary: false lycheeVersion: v0.24.2 - output: lychee-preview.md + output: lychee-rendered-html.md token: ${{ github.token }} - name: Save lychee cache From d16f283a26c18ec1482c4aabc8b7c128affb1880 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Thu, 4 Jun 2026 13:09:58 -0400 Subject: [PATCH 16/22] Clarify rendered docs artifact uploads --- .github/workflows/build-docs.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 63eb04b898..1b79ea80ae 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -248,11 +248,6 @@ jobs: fi mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET} - - name: Write doc preview marker - if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - run: | - echo "${{ github.sha }}" > artifacts/docs/.preview-commit - - name: Upload rendered docs for link checking if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -262,8 +257,9 @@ jobs: if-no-files-found: error retention-days: 3 - # TODO: Consider removing this step? - - name: Upload doc artifacts + # This is the GitHub Pages artifact format; the link checker needs a + # normal workflow artifact with the rendered HTML tree above. + - name: Upload docs GitHub Pages artifact uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: artifacts/ From 1ace33e60de4ef8a7c33aee99e724960af2bed78 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Thu, 4 Jun 2026 13:56:40 -0400 Subject: [PATCH 17/22] Handle rendered docs linkcheck exclusions --- .github/workflows/check-doc-links.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml index 89366422c3..c00730b660 100644 --- a/.github/workflows/check-doc-links.yml +++ b/.github/workflows/check-doc-links.yml @@ -63,6 +63,9 @@ jobs: - name: Check rendered docs links uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout with: + # PR-preview canonical URLs are checked by the preview deployment workflow. + # The cuda-bindings #id links are docutils "problematic" anchors from generated API docs. + # Preferred Networks rejects hosted-runner GETs, but the URL is browser reachable. args: >- --files-from ${{ github.workspace }}/lychee-rendered-html-files.txt --include-fragments=full @@ -75,6 +78,9 @@ jobs: --retry-wait-time 5 --timeout 30 --no-progress + --exclude '^https://nvidia\.github\.io/cuda-python/pr-preview/pr-[0-9]+/' + --exclude '^file://.*/cuda-bindings/latest/module/(driver|runtime)\.html#id[0-9]+$' + --exclude '^https://www\.preferred\.jp/en/?$' fail: true failIfEmpty: true format: markdown From d1af8874fb43dfcd3305550a13be2fc10c38b138 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Fri, 5 Jun 2026 22:26:12 -0400 Subject: [PATCH 18/22] Defer generated pointer docs cleanup --- cuda_bindings/docs/source/module/driver.rst | 14 +++++++------- cuda_bindings/docs/source/module/runtime.rst | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cuda_bindings/docs/source/module/driver.rst b/cuda_bindings/docs/source/module/driver.rst index 020633665b..49c633aa07 100644 --- a/cuda_bindings/docs/source/module/driver.rst +++ b/cuda_bindings/docs/source/module/driver.rst @@ -406,25 +406,25 @@ Data types used by CUDA driver .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_GEQ - Wait until (int32_t)(\*addr - value) >= 0 (or int64_t for 64 bit values). Note this is a cyclic comparison which ignores wraparound. (Default behavior.) + Wait until (int32_t)(*addr - value) >= 0 (or int64_t for 64 bit values). Note this is a cyclic comparison which ignores wraparound. (Default behavior.) .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_EQ - Wait until \*addr == value. + Wait until *addr == value. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_AND - Wait until (\*addr & value) != 0. + Wait until (*addr & value) != 0. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_NOR - Wait until ~(\*addr | value) != 0. Support for this operation can be queried with :py:obj:`~.cuDeviceGetAttribute()` and :py:obj:`~.CU_DEVICE_ATTRIBUTE_CAN_USE_STREAM_WAIT_VALUE_NOR`. + Wait until ~(*addr | value) != 0. Support for this operation can be queried with :py:obj:`~.cuDeviceGetAttribute()` and :py:obj:`~.CU_DEVICE_ATTRIBUTE_CAN_USE_STREAM_WAIT_VALUE_NOR`. .. autoattribute:: cuda.bindings.driver.CUstreamWaitValue_flags.CU_STREAM_WAIT_VALUE_FLUSH @@ -506,19 +506,19 @@ Data types used by CUDA driver .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_OR - Performs an atomic OR: \*(address) = \*(address) | value + Performs an atomic OR: *(address) = *(address) | value .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_AND - Performs an atomic AND: \*(address) = \*(address) & value + Performs an atomic AND: *(address) = *(address) & value .. autoattribute:: cuda.bindings.driver.CUstreamAtomicReductionOpType.CU_STREAM_ATOMIC_REDUCTION_OP_ADD - Performs an atomic ADD: \*(address) = \*(address) + value + Performs an atomic ADD: *(address) = *(address) + value .. autoclass:: cuda.bindings.driver.CUstreamAtomicReductionDataType diff --git a/cuda_bindings/docs/source/module/runtime.rst b/cuda_bindings/docs/source/module/runtime.rst index 4714cf8f13..29da14b40d 100644 --- a/cuda_bindings/docs/source/module/runtime.rst +++ b/cuda_bindings/docs/source/module/runtime.rst @@ -6403,11 +6403,11 @@ The types ::CUevent and cudaEvent_t are identical and may be used interchangeabl -The types ``CUarray`` and ``struct cudaArray *`` represent the same data type and may be used interchangeably by casting the two types between each other. +The types ::CUarray and struct ::cudaArray * represent the same data type and may be used interchangeably by casting the two types between each other. -In order to use a ``CUarray`` in a CUDA Runtime API function which takes a ``struct cudaArray *``, it is necessary to explicitly cast the ``CUarray`` to a ``struct cudaArray *``. +In order to use a ::CUarray in a CUDA Runtime API function which takes a struct ::cudaArray *, it is necessary to explicitly cast the ::CUarray to a struct ::cudaArray *. -In order to use a ``struct cudaArray *`` in a CUDA Driver API function which takes a ``CUarray``, it is necessary to explicitly cast the ``struct cudaArray *`` to a ``CUarray``. +In order to use a struct ::cudaArray * in a CUDA Driver API function which takes a ::CUarray, it is necessary to explicitly cast the struct ::cudaArray * to a ::CUarray . From 809534b20afc431bb76c35b1da920463212a7da4 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Sat, 6 Jun 2026 00:33:50 -0400 Subject: [PATCH 19/22] Remove redundant docs commit hash env --- .github/workflows/build-docs.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 1b79ea80ae..167fd7062e 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -95,17 +95,14 @@ jobs: if [[ -z "${DOCS_GITHUB_REF}" ]]; then DOCS_GITHUB_REF="${GITHUB_REF_NAME}" fi - COMMIT_HASH="${DOCS_GITHUB_REF}" else FILE_HASH="${{ github.sha }}" DOCS_GITHUB_REF="${{ github.sha }}" - COMMIT_HASH="${DOCS_GITHUB_REF}" fi # make outputs from the previous job as env vars CUDA_CORE_ARTIFACT_BASENAME="cuda-core-python${PYTHON_VERSION_FORMATTED}-linux-64" echo "CUDA_PYTHON_DOCS_GITHUB_REF=${DOCS_GITHUB_REF}" >> $GITHUB_ENV - echo "COMMIT_HASH=${COMMIT_HASH}" >> $GITHUB_ENV echo "CUDA_CORE_ARTIFACT_BASENAME=${CUDA_CORE_ARTIFACT_BASENAME}" >> $GITHUB_ENV echo "CUDA_CORE_ARTIFACT_NAME=${CUDA_CORE_ARTIFACT_BASENAME}-${FILE_HASH}" >> $GITHUB_ENV echo "CUDA_CORE_ARTIFACTS_DIR=$(realpath "$REPO_DIR/cuda_core/dist")" >> $GITHUB_ENV @@ -281,5 +278,5 @@ jobs: git-config-email: cuda-python-bot@users.noreply.github.com folder: artifacts/docs/ target-folder: docs/ - commit-message: "Deploy ${{ (inputs.is-release && 'release') || 'latest' }} docs: ${{ env.COMMIT_HASH }}" + commit-message: "Deploy ${{ (inputs.is-release && 'release') || 'latest' }} docs: ${{ env.CUDA_PYTHON_DOCS_GITHUB_REF }}" clean: false From f6adcfbe6a39375453dc83aa7c2afcc1fbf285ec Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 9 Jun 2026 12:29:44 -0400 Subject: [PATCH 20/22] Note temporary rendered docs link exclusion --- .github/workflows/check-doc-links.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml index c00730b660..3d45231dea 100644 --- a/.github/workflows/check-doc-links.yml +++ b/.github/workflows/check-doc-links.yml @@ -65,6 +65,7 @@ jobs: with: # PR-preview canonical URLs are checked by the preview deployment workflow. # The cuda-bindings #id links are docutils "problematic" anchors from generated API docs. + # TODO: Remove this exclusion after cybind stops emitting those problematic anchors. # Preferred Networks rejects hosted-runner GETs, but the URL is browser reachable. args: >- --files-from ${{ github.workspace }}/lychee-rendered-html-files.txt From 22dde0aabe45f3d6be62012fba955294ac2a6b8d Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 9 Jun 2026 13:29:25 -0400 Subject: [PATCH 21/22] Use lychee release tag for pre-commit hook --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 40121b6f0f..f9a79df944 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: # Link checking for authored documentation files - repo: https://github.com/lycheeverse/lychee - rev: 2bba271688c1abb1503097a064e6c3bc1d1b6a9b # frozen: lychee-v0.24.2 + rev: lychee-v0.24.2 hooks: - id: lychee args: From 0a319ad1ffc67fa9ac538aa855d9bf3919c73f36 Mon Sep 17 00:00:00 2001 From: Keith Kraus Date: Tue, 9 Jun 2026 13:38:32 -0400 Subject: [PATCH 22/22] Inline rendered docs link check --- .github/workflows/build-docs.yml | 64 ++++++++++++++--- .github/workflows/check-doc-links.yml | 98 --------------------------- .github/workflows/ci.yml | 16 ----- .pre-commit-config.yaml | 2 +- 4 files changed, 57 insertions(+), 123 deletions(-) delete mode 100644 .github/workflows/check-doc-links.yml diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 167fd7062e..45fa53ab1b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -245,17 +245,65 @@ jobs: fi mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET} - - name: Upload rendered docs for link checking + - name: Write rendered docs file list if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + run: | + find "${GITHUB_WORKSPACE}/artifacts/docs" -type f -name '*.html' ! -path '*/_static/*' \ + | LC_ALL=C sort > lychee-rendered-html-files.txt + if [[ ! -s lychee-rendered-html-files.txt ]]; then + echo "error: no rendered HTML pages found for lychee" >&2 + exit 1 + fi + wc -l lychee-rendered-html-files.txt + + - name: Restore lychee cache + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + id: restore-lychee-cache + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: - name: docs-rendered-html - path: artifacts/docs/ - if-no-files-found: error - retention-days: 3 + path: .lycheecache + key: docs-rendered-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} + restore-keys: | + docs-rendered-lychee-${{ env.PR_NUMBER }}- + + - name: Check rendered docs links + if: ${{ !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }} + uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout + with: + # PR-preview canonical URLs are checked by the preview deployment workflow. + # The cuda-bindings #id links are docutils "problematic" anchors from generated API docs. + # TODO: Remove this exclusion after cybind stops emitting those problematic anchors. + # Preferred Networks rejects hosted-runner GETs, but the URL is browser reachable. + args: >- + --files-from ${{ github.workspace }}/lychee-rendered-html-files.txt + --include-fragments=full + --cache + --max-cache-age 1d + --max-concurrency 16 + --host-concurrency 2 + --host-request-interval 250ms + --max-retries 3 + --retry-wait-time 5 + --timeout 30 + --no-progress + --exclude '^https://nvidia\.github\.io/cuda-python/pr-preview/pr-[0-9]+/' + --exclude '^file://.*/cuda-bindings/latest/module/(driver|runtime)\.html#id[0-9]+$' + --exclude '^https://www\.preferred\.jp/en/?$' + fail: true + failIfEmpty: true + format: markdown + jobSummary: false + lycheeVersion: v0.24.2 + output: lychee-rendered-html.md + token: ${{ github.token }} + + - name: Save lychee cache + if: ${{ always() && !inputs.is-release && github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') && steps.restore-lychee-cache.outputs.cache-hit != 'true' && steps.restore-lychee-cache.outputs.cache-primary-key != '' }} + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: .lycheecache + key: ${{ steps.restore-lychee-cache.outputs.cache-primary-key }} - # This is the GitHub Pages artifact format; the link checker needs a - # normal workflow artifact with the rendered HTML tree above. - name: Upload docs GitHub Pages artifact uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml deleted file mode 100644 index 3d45231dea..0000000000 --- a/.github/workflows/check-doc-links.yml +++ /dev/null @@ -1,98 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 - -name: "CI: Check rendered docs links" - -on: - workflow_call: - inputs: - docs-artifact: - description: "Artifact containing the rendered docs HTML tree" - required: false - default: docs-rendered-html - type: string - -jobs: - check: - name: Check rendered docs links - if: ${{ github.repository_owner == 'nvidia' && startsWith(github.ref_name, 'pull-request/') }} - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - pull-requests: read - defaults: - run: - shell: bash -el {0} - steps: - - name: Extract PR number - run: | - PR_NUMBER="${GITHUB_REF_NAME#pull-request/}" - if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then - echo "error: cannot extract PR number from ref ${GITHUB_REF_NAME}" >&2 - exit 1 - fi - echo "PR_NUMBER=${PR_NUMBER}" >> "${GITHUB_ENV}" - - - name: Download rendered docs - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: ${{ inputs.docs-artifact }} - path: rendered-docs - - - name: Write rendered docs file list - run: | - find "${GITHUB_WORKSPACE}/rendered-docs" -type f -name '*.html' ! -path '*/_static/*' \ - | LC_ALL=C sort > lychee-rendered-html-files.txt - if [[ ! -s lychee-rendered-html-files.txt ]]; then - echo "error: no rendered HTML pages found for lychee" >&2 - exit 1 - fi - wc -l lychee-rendered-html-files.txt - - - name: Restore lychee cache - id: restore-lychee-cache - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 - with: - path: .lycheecache - key: docs-rendered-lychee-${{ env.PR_NUMBER }}-${{ github.sha }} - restore-keys: | - docs-rendered-lychee-${{ env.PR_NUMBER }}- - - - name: Check rendered docs links - uses: lycheeverse/lychee-action@6da1d14f3a43098a294b7696d93d938aa8d20fc0 # unreleased: supports v0.24.x archive layout - with: - # PR-preview canonical URLs are checked by the preview deployment workflow. - # The cuda-bindings #id links are docutils "problematic" anchors from generated API docs. - # TODO: Remove this exclusion after cybind stops emitting those problematic anchors. - # Preferred Networks rejects hosted-runner GETs, but the URL is browser reachable. - args: >- - --files-from ${{ github.workspace }}/lychee-rendered-html-files.txt - --include-fragments=full - --cache - --max-cache-age 1d - --max-concurrency 16 - --host-concurrency 2 - --host-request-interval 250ms - --max-retries 3 - --retry-wait-time 5 - --timeout 30 - --no-progress - --exclude '^https://nvidia\.github\.io/cuda-python/pr-preview/pr-[0-9]+/' - --exclude '^file://.*/cuda-bindings/latest/module/(driver|runtime)\.html#id[0-9]+$' - --exclude '^https://www\.preferred\.jp/en/?$' - fail: true - failIfEmpty: true - format: markdown - jobSummary: false - lycheeVersion: v0.24.2 - output: lychee-rendered-html.md - token: ${{ github.token }} - - - name: Save lychee cache - if: ${{ always() && steps.restore-lychee-cache.outputs.cache-hit != 'true' && steps.restore-lychee-cache.outputs.cache-primary-key != '' }} - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 - with: - path: .lycheecache - key: ${{ steps.restore-lychee-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d52821c84..6b510ecffc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -415,18 +415,6 @@ jobs: with: is-release: ${{ github.ref_type == 'tag' }} - doc-linkcheck: - name: Docs link check - if: ${{ github.repository_owner == 'nvidia' && startsWith(github.ref_name, 'pull-request/') && needs.doc.result == 'success' }} - permissions: - actions: read - contents: read - pull-requests: read - needs: - - doc - secrets: inherit - uses: ./.github/workflows/check-doc-links.yml - checks: name: Check job status if: always() @@ -440,7 +428,6 @@ jobs: - test-linux-aarch64 - test-windows - doc - - doc-linkcheck steps: - name: Exit run: | @@ -476,9 +463,6 @@ jobs: if ${{ needs.doc.result == 'cancelled' || needs.doc.result == 'failure' }}; then exit 1 fi - if ${{ needs.doc-linkcheck.result == 'cancelled' || needs.doc-linkcheck.result == 'failure' }}; then - exit 1 - fi if ${{ needs.test-sdist-linux.result == 'cancelled' || needs.test-sdist-linux.result == 'failure' || needs.test-sdist-windows.result == 'cancelled' || diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f9a79df944..40121b6f0f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: # Link checking for authored documentation files - repo: https://github.com/lycheeverse/lychee - rev: lychee-v0.24.2 + rev: 2bba271688c1abb1503097a064e6c3bc1d1b6a9b # frozen: lychee-v0.24.2 hooks: - id: lychee args: