[clang-tools-extra] [llvm] [Github][CI] Introduce `doc8` to `code-lint-helper.py` (PR #172123)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 13 21:47:42 PST 2025
https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/172123
>From 4b0b1ee150ea820f00564667e734ddd225665d53 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Fri, 12 Dec 2025 22:39:40 +0800
Subject: [PATCH 1/7] [Github][CI] Introduce `doc8` to `code-lint-helper.py`
---
.../github-action-ci-tooling/Dockerfile | 5 +-
.github/workflows/pr-code-lint.yml | 6 +-
llvm/utils/git/code-lint-helper.py | 61 ++++++++++++++++++-
3 files changed, 67 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/containers/github-action-ci-tooling/Dockerfile b/.github/workflows/containers/github-action-ci-tooling/Dockerfile
index b78c99efb9be3..47dedba5194e2 100644
--- a/.github/workflows/containers/github-action-ci-tooling/Dockerfile
+++ b/.github/workflows/containers/github-action-ci-tooling/Dockerfile
@@ -94,6 +94,10 @@ COPY --from=llvm-downloader /llvm-extract/LLVM-${LLVM_VERSION}-Linux-X64/bin/cla
COPY clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py ${LLVM_SYSROOT}/bin/clang-tidy-diff.py
# Install dependencies for 'pr-code-lint.yml' job
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y python3-doc8 && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
COPY llvm/utils/git/requirements_linting.txt requirements_linting.txt
RUN pip install -r requirements_linting.txt --break-system-packages && \
rm requirements_linting.txt
@@ -119,4 +123,3 @@ RUN git clone https://github.com/universal-ctags/ctags.git && \
./configure && \
sudo make install && \
rm -Rf ../ctags
-
diff --git a/.github/workflows/pr-code-lint.yml b/.github/workflows/pr-code-lint.yml
index ea4f8217cd003..ed0b371064b80 100644
--- a/.github/workflows/pr-code-lint.yml
+++ b/.github/workflows/pr-code-lint.yml
@@ -20,7 +20,7 @@ jobs:
run:
shell: bash
container:
- image: 'ghcr.io/llvm/ci-ubuntu-24.04-lint'
+ image: 'ghcr.io/llvm/ci-ubuntu-24.04-lint-doc8'
timeout-minutes: 60
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -71,12 +71,12 @@ jobs:
-DLLVM_INCLUDE_TESTS=OFF \
-DCLANG_INCLUDE_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release
-
+
ninja -C build \
clang-tablegen-targets \
genconfusable # for "ConfusableIdentifierCheck.h"
- - name: Run code linter
+ - name: Run code linters
env:
GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py
index a53549fb69a77..aca88e2be5a8c 100644
--- a/llvm/utils/git/code-lint-helper.py
+++ b/llvm/utils/git/code-lint-helper.py
@@ -36,6 +36,7 @@ class LintArgs:
issue_number: int = 0
build_path: str = "build"
clang_tidy_binary: str = "clang-tidy"
+ doc8_binary: str = "doc8"
def __init__(self, args: argparse.Namespace) -> None:
if args is not None:
@@ -50,6 +51,7 @@ def __init__(self, args: argparse.Namespace) -> None:
self.verbose = args.verbose
self.build_path = args.build_path
self.clang_tidy_binary = args.clang_tidy_binary
+ self.doc8_binary = args.doc8_binary
class LintHelper:
@@ -289,8 +291,59 @@ def _clean_clang_tidy_output(self, output: str) -> str:
return ""
+class Doc8LintHelper(LintHelper):
+ name: Final = "doc8"
+ friendly_name: Final = "documentation linter"
-ALL_LINTERS = (ClangTidyLintHelper(),)
+ def instructions(self, files_to_lint: Sequence[str], args: LintArgs) -> str:
+ files_str = " ".join(files_to_lint)
+ return f"doc8 -q {files_str}"
+
+ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
+ filtered_files = []
+ for filepath in changed_files:
+ _, ext = os.path.splitext(filepath)
+ if ext != ".rst":
+ continue
+ if not filepath.startswith("clang-tools-extra/docs/clang-tidy/"):
+ continue
+ if os.path.exists(filepath):
+ filtered_files.append(filepath)
+ return filtered_files
+
+ def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str:
+ if not files_to_lint:
+ return ""
+
+ doc8_cmd = [args.doc8_binary, "-q"]
+ doc8_cmd.extend(files_to_lint)
+
+ if args.verbose:
+ print(f"Running doc8: {' '.join(doc8_cmd)}")
+
+ proc = subprocess.run(
+ doc8_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ check=False,
+ )
+
+ if proc.returncode == 0:
+ return ""
+
+ output = proc.stdout.strip()
+ if output:
+ return output
+
+ error_output = proc.stderr.strip()
+ if error_output:
+ return error_output
+
+ return f"doc8 exited with return code {proc.returncode} but no output."
+
+
+ALL_LINTERS = (ClangTidyLintHelper(), Doc8LintHelper())
if __name__ == "__main__":
@@ -331,6 +384,12 @@ def _clean_clang_tidy_output(self, output: str) -> str:
default="clang-tidy",
help="Path to clang-tidy binary",
)
+ parser.add_argument(
+ "--doc8-binary",
+ type=str,
+ default="doc8",
+ help="Path to doc8 binary",
+ )
parser.add_argument(
"--verbose", action="store_true", default=True, help="Verbose output"
)
>From d5f45bb1c2d7deed3eb3ed23f0a18cba6e008706 Mon Sep 17 00:00:00 2001
From: mitchell <mitchell.xu2 at gmail.com>
Date: Sat, 13 Dec 2025 20:39:00 +0800
Subject: [PATCH 2/7] Apply suggestions from code review
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
llvm/utils/git/code-lint-helper.py | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py
index aca88e2be5a8c..aabc78f2de033 100644
--- a/llvm/utils/git/code-lint-helper.py
+++ b/llvm/utils/git/code-lint-helper.py
@@ -295,11 +295,10 @@ class Doc8LintHelper(LintHelper):
name: Final = "doc8"
friendly_name: Final = "documentation linter"
- def instructions(self, files_to_lint: Sequence[str], args: LintArgs) -> str:
- files_str = " ".join(files_to_lint)
- return f"doc8 -q {files_str}"
+ def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
+ return f"doc8 -q {' '.join(files_to_lint)}"
- def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
+ def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]:
filtered_files = []
for filepath in changed_files:
_, ext = os.path.splitext(filepath)
@@ -311,7 +310,7 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
filtered_files.append(filepath)
return filtered_files
- def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str:
+ def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
if not files_to_lint:
return ""
@@ -332,12 +331,10 @@ def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str:
if proc.returncode == 0:
return ""
- output = proc.stdout.strip()
- if output:
+ if output := proc.stdout.strip():
return output
- error_output = proc.stderr.strip()
- if error_output:
+ if error_output := proc.stderr.strip():
return error_output
return f"doc8 exited with return code {proc.returncode} but no output."
>From e014eb29350befe49cd99d131f414661d88e3539 Mon Sep 17 00:00:00 2001
From: mitchell <mitchell.xu2 at gmail.com>
Date: Sat, 13 Dec 2025 20:48:40 +0800
Subject: [PATCH 3/7] Update llvm/utils/git/code-lint-helper.py
Co-authored-by: Baranov Victor <bar.victor.2002 at gmail.com>
---
llvm/utils/git/code-lint-helper.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py
index aabc78f2de033..db551204f0c1a 100644
--- a/llvm/utils/git/code-lint-helper.py
+++ b/llvm/utils/git/code-lint-helper.py
@@ -293,7 +293,7 @@ def _clean_clang_tidy_output(self, output: str) -> str:
class Doc8LintHelper(LintHelper):
name: Final = "doc8"
- friendly_name: Final = "documentation linter"
+ friendly_name: Final = "RST documentation linter"
def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
return f"doc8 -q {' '.join(files_to_lint)}"
>From 1188b8dbe36b8cfada478cfa3f3f9e25c3b6c18f Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Sat, 13 Dec 2025 20:45:35 +0800
Subject: [PATCH 4/7] Fix
---
llvm/utils/git/code-lint-helper.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py
index db551204f0c1a..3947bcac7f3b9 100644
--- a/llvm/utils/git/code-lint-helper.py
+++ b/llvm/utils/git/code-lint-helper.py
@@ -23,7 +23,7 @@
import os
import subprocess
import sys
-from typing import Any, Dict, Final, List, Sequence
+from typing import Any, Dict, Final, Iterable, List, Sequence
class LintArgs:
@@ -194,7 +194,7 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
arg for arg in changed_files if "third-party" not in arg
]
- filtered_files = []
+ filtered_files: List[str] = []
for filepath in clang_tidy_changed_files:
_, ext = os.path.splitext(filepath)
if ext not in (".c", ".cpp", ".cxx", ".h", ".hpp", ".hxx"):
@@ -298,8 +298,8 @@ class Doc8LintHelper(LintHelper):
def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
return f"doc8 -q {' '.join(files_to_lint)}"
- def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]:
- filtered_files = []
+ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
+ filtered_files: List[str] = []
for filepath in changed_files:
_, ext = os.path.splitext(filepath)
if ext != ".rst":
>From 03ae3744662c985472aedc387407f7ff5a11194d Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Sat, 13 Dec 2025 20:58:15 +0800
Subject: [PATCH 5/7] Split filter function and refactor error handling
---
llvm/utils/git/code-lint-helper.py | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py
index 3947bcac7f3b9..d89a1e259ed3a 100644
--- a/llvm/utils/git/code-lint-helper.py
+++ b/llvm/utils/git/code-lint-helper.py
@@ -304,12 +304,15 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]:
_, ext = os.path.splitext(filepath)
if ext != ".rst":
continue
- if not filepath.startswith("clang-tools-extra/docs/clang-tidy/"):
+ if not self._should_lint_file(filepath):
continue
if os.path.exists(filepath):
filtered_files.append(filepath)
return filtered_files
+ def _should_lint_file(self, filepath: str) -> bool:
+ return filepath.startswith("clang-tools-extra/docs/clang-tidy/")
+
def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
if not files_to_lint:
return ""
@@ -331,13 +334,19 @@ def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str:
if proc.returncode == 0:
return ""
- if output := proc.stdout.strip():
- return output
+ output = proc.stdout.strip()
+ error_output = proc.stderr.strip()
- if error_output := proc.stderr.strip():
- return error_output
+ parts: List[str] = []
+ if output:
+ parts.append(output)
+ if error_output:
+ parts.append(f"stderr:\n{error_output}")
- return f"doc8 exited with return code {proc.returncode} but no output."
+ if parts:
+ return "\n\n".join(parts)
+ else:
+ return f"doc8 exited with return code {proc.returncode} but no output."
ALL_LINTERS = (ClangTidyLintHelper(), Doc8LintHelper())
>From 5661fef3bc4a93986c3cd64b40547a864300afa6 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Sun, 14 Dec 2025 13:39:14 +0800
Subject: [PATCH 6/7] Fix EOF
---
.../workflows/containers/github-action-ci-tooling/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/containers/github-action-ci-tooling/Dockerfile b/.github/workflows/containers/github-action-ci-tooling/Dockerfile
index ba49c1cbfa245..6ac090e9a3385 100644
--- a/.github/workflows/containers/github-action-ci-tooling/Dockerfile
+++ b/.github/workflows/containers/github-action-ci-tooling/Dockerfile
@@ -116,4 +116,4 @@ RUN apt-get update && \
pkg-config \
universal-ctags && \
apt-get clean && \
- rm -rf /var/lib/apt/lists/*
\ No newline at end of file
+ rm -rf /var/lib/apt/lists/*
>From 89bf56774b92fde5ef78c3b7cb032487236b9d0f Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Sun, 14 Dec 2025 13:44:43 +0800
Subject: [PATCH 7/7] test `doc8` linting
---
.../docs/clang-tidy/checks/bugprone/unsafe-functions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
index cb7ea415c54b2..4ecae979831a6 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
@@ -23,7 +23,7 @@ The following functions are reported if :option:`ReportDefaultFunctions`
is enabled.
If *Annex K.* is available, a replacement from *Annex K.* is suggested for the
-following functions:
+following functions
``asctime``, ``asctime_r``, ``bsearch``, ``ctime``, ``fopen``, ``fprintf``,
``freopen``, ``fscanf``, ``fwprintf``, ``fwscanf``, ``getenv``, ``gets``,
More information about the llvm-commits
mailing list