https://github.com/vbvictor updated https://github.com/llvm/llvm-project/pull/154223
>From b9e917fb7da29c1dc70e0e89b972fc3e2a631b4f Mon Sep 17 00:00:00 2001 From: Victor Baranov <bar.victor.2...@gmail.com> Date: Thu, 21 Aug 2025 21:20:33 +0300 Subject: [PATCH 1/3] Add clang-tidy violations for testing purpose --- .../clang-tidy/performance/MoveConstArgCheck.cpp | 6 +++--- clang-tools-extra/clangd/AST.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp index f458e26d964b0..283063dd69d5f 100644 --- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp @@ -19,7 +19,7 @@ static void replaceCallWithArg(const CallExpr *Call, DiagnosticBuilder &Diag, const LangOptions &LangOpts) { const Expr *Arg = Call->getArg(0); - CharSourceRange BeforeArgumentsRange = Lexer::makeFileCharRange( + CharSourceRange beforeArgumentsRange = Lexer::makeFileCharRange( CharSourceRange::getCharRange(Call->getBeginLoc(), Arg->getBeginLoc()), SM, LangOpts); CharSourceRange AfterArgumentsRange = Lexer::makeFileCharRange( @@ -27,8 +27,8 @@ static void replaceCallWithArg(const CallExpr *Call, DiagnosticBuilder &Diag, Call->getEndLoc().getLocWithOffset(1)), SM, LangOpts); - if (BeforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) { - Diag << FixItHint::CreateRemoval(BeforeArgumentsRange) + if (beforeArgumentsRange.isValid() && AfterArgumentsRange.isValid()) { + Diag << FixItHint::CreateRemoval(beforeArgumentsRange) << FixItHint::CreateRemoval(AfterArgumentsRange); } } diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 82aee4c84d074..1ad7ba3bb4d79 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -141,7 +141,7 @@ std::string getQualification(ASTContext &Context, // Go over the declarations in reverse order, since we stored inner-most // parent first. NestedNameSpecifier Qualifier = std::nullopt; - bool IsFirst = true; + bool isFirst = true; for (const auto *CurD : llvm::reverse(Parents)) { if (auto *TD = llvm::dyn_cast<TagDecl>(CurD)) { QualType T; @@ -155,7 +155,7 @@ std::string getQualification(ASTContext &Context, T = Context.getTemplateSpecializationType( ElaboratedTypeKeyword::None, Context.getQualifiedTemplateName( - Qualifier, /*TemplateKeyword=*/!IsFirst, TemplateName(CTD)), + Qualifier, /*TemplateKeyword=*/!isFirst, TemplateName(CTD)), Args, /*CanonicalArgs=*/{}, Context.getCanonicalTagType(RD)); } else { T = Context.getTagType(ElaboratedTypeKeyword::None, Qualifier, TD, @@ -166,7 +166,7 @@ std::string getQualification(ASTContext &Context, Qualifier = NestedNameSpecifier(Context, cast<NamespaceDecl>(CurD), Qualifier); } - IsFirst = false; + isFirst = false; } if (!Qualifier) return ""; >From 084eee2b06fab2ee9ca50de7c52b1b9942f98428 Mon Sep 17 00:00:00 2001 From: Victor Baranov <bar.victor.2...@gmail.com> Date: Fri, 22 Aug 2025 08:00:16 +0300 Subject: [PATCH 2/3] [GitHub][CI] Add clang-tidy premerge workflow --- .github/workflows/issue-write.yml | 1 + .github/workflows/pr-code-format.yml | 2 +- .github/workflows/pr-code-lint.yml | 126 ++++++++ llvm/utils/git/code-lint-helper.py | 345 +++++++++++++++++++++ llvm/utils/git/requirements_linting.txt | 324 +++++++++++++++++++ llvm/utils/git/requirements_linting.txt.in | 1 + 6 files changed, 798 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pr-code-lint.yml create mode 100755 llvm/utils/git/code-lint-helper.py create mode 100644 llvm/utils/git/requirements_linting.txt create mode 100644 llvm/utils/git/requirements_linting.txt.in diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml index 3036582a64a58..db9389b6afe53 100644 --- a/.github/workflows/issue-write.yml +++ b/.github/workflows/issue-write.yml @@ -6,6 +6,7 @@ on: - "Check code formatting" - "Check for private emails used in PRs" - "PR Request Release Note" + - "Code lint" types: - completed diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index dc55b7e47e111..b85bf14d91b28 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -1,4 +1,4 @@ -name: "Check code formatting" +name: "Code lint" permissions: contents: read diff --git a/.github/workflows/pr-code-lint.yml b/.github/workflows/pr-code-lint.yml new file mode 100644 index 0000000000000..ddf69761b15e6 --- /dev/null +++ b/.github/workflows/pr-code-lint.yml @@ -0,0 +1,126 @@ +name: "Check code formatting" + +permissions: + contents: read + +on: + pull_request: + branches: + - main + - 'users/**' + paths: + - 'clang-tools-extra/clang-tidy/**' + +jobs: + code_linter: + if: github.repository_owner == 'llvm' + runs-on: ubuntu-24.04 + defaults: + run: + shell: bash + container: + image: 'ghcr.io/llvm/ci-ubuntu-24.04:latest' + timeout-minutes: 60 + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + steps: + - name: Fetch LLVM sources + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 2 + + - name: Get changed files + id: changed-files + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1 + with: + separator: "," + skip_initial_fetch: true + base_sha: 'HEAD~1' + sha: 'HEAD' + + - name: Listed files + env: + CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + run: | + echo "Changed files:" + echo "$CHANGED_FILES" + + - name: Fetch code linting utils + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + sparse-checkout: | + llvm/utils/git/code-lint-helper.py + llvm/utils/git/requirements_linting.txt + clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py + sparse-checkout-cone-mode: false + path: code-lint-tools + + - uses: actions/setup-python@v5 + id: setup_python + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python3 -m venv .venv + source .venv/bin/activate + python3 -m pip install -r code-lint-tools/llvm/utils/git/requirements_linting.txt + + - name: Install clang-tidy + uses: aminya/setup-cpp@17c11551771948abc5752bbf3183482567c7caf0 # v1.1.1 + with: + clang-tidy: 20.1.8 + + # FIXME: create special mapping for 'gen' targets, for now build predefined set + - name: Configure and Build + run: | + git config --global --add safe.directory '*' + + source <(git diff --name-only HEAD~1...HEAD | python3 .ci/compute_projects.py) + + if [[ "${projects_to_build}" == "" ]]; then + echo "No projects to analyze" + exit 0 + fi + + cmake -G Ninja \ + -B build \ + -S llvm \ + -DLLVM_ENABLE_ASSERTIONS=OFF \ + -DLLVM_ENABLE_PROJECTS="${projects_to_build}" \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -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 + env: + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} + CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + run: | + source .venv/bin/activate + echo "[]" > comments && + python3 ./code-lint-tools/llvm/utils/git/code-lint-helper.py \ + --token ${{ secrets.GITHUB_TOKEN }} \ + --issue-number $GITHUB_PR_NUMBER \ + --start-rev HEAD~1 \ + --end-rev HEAD \ + --verbose \ + --changed-files "$CHANGED_FILES" + + - name: Upload results + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() + with: + name: workflow-args + path: | + comments diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py new file mode 100755 index 0000000000000..de6d5cb7fc9e3 --- /dev/null +++ b/llvm/utils/git/code-lint-helper.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python3 +# +# ====- clang-tidy-helper, runs clang-tidy from the ci --*- python -*-------==# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ==-------------------------------------------------------------------------==# + +import argparse +import os +import subprocess +import sys +from typing import List, Optional + +""" +This script is run by GitHub actions to ensure that the code in PR's conform to +the coding style of LLVM. The canonical source of this script is in the LLVM +source tree under llvm/utils/git. + +You can learn more about the LLVM coding style on llvm.org: +https://llvm.org/docs/CodingStandards.html +""" + + +class LintArgs: + start_rev: str = None + end_rev: str = None + repo: str = None + changed_files: List[str] = [] + token: str = None + verbose: bool = True + issue_number: int = 0 + build_path: str = "build" + clang_tidy_binary: str = "clang-tidy" + + def __init__(self, args: argparse.Namespace = None) -> None: + if not args is None: + self.start_rev = args.start_rev + self.end_rev = args.end_rev + self.repo = args.repo + self.token = args.token + self.changed_files = args.changed_files + self.issue_number = args.issue_number + self.verbose = args.verbose + self.build_path = args.build_path + self.clang_tidy_binary = args.clang_tidy_binary + + +COMMENT_TAG = "<!--LLVM CODE LINT COMMENT: clang-tidy-->" + + +def get_instructions(cpp_files: List[str]) -> str: + files_str = " ".join(cpp_files) + return f""" +git diff -U0 origin/main..HEAD -- {files_str} | +python3 clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py \\ + -path build -p1 -quiet""" + + +def clean_clang_tidy_output(output: str) -> Optional[str]: + """ + - Remove 'Running clang-tidy in X threads...' line + - Remove 'N warnings generated.' line + - Strip leading workspace path from file paths + """ + if not output or output == "No relevant changes found.": + return None + + lines = output.split("\n") + cleaned_lines = [] + + for line in lines: + if line.startswith("Running clang-tidy in") or line.endswith("generated."): + continue + + # Remove everything up to rightmost "llvm-project/" for correct files names + idx = line.rfind("llvm-project/") + if idx != -1: + line = line[idx + len("llvm-project/") :] + + cleaned_lines.append(line) + + if cleaned_lines: + return "\n".join(cleaned_lines) + return None + + +def should_lint_file(filepath: str) -> bool: + # For add other paths/files to this function + return filepath.startswith("clang-tools-extra/clang-tidy/") + + +def filter_changed_files(changed_files: List[str]) -> List[str]: + filtered_files = [] + for filepath in changed_files: + _, ext = os.path.splitext(filepath) + if ext not in (".cpp", ".c", ".h", ".hpp", ".hxx", ".cxx"): + continue + if not should_lint_file(filepath): + continue + if os.path.exists(filepath): + filtered_files.append(filepath) + + return filtered_files + + +def has_clang_tidy(clang_tidy_binary: str) -> bool: + cmd = [clang_tidy_binary, "--version"] + proc = None + try: + proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except: + return False + return proc.returncode == 0 + + +def create_comment_text(warning: str, cpp_files: List[str]) -> str: + instructions = get_instructions(cpp_files) + return f""" +:warning: C/C++ code linter clang-tidy found issues in your code. :warning: + +<details> +<summary> +You can test this locally with the following command: +</summary> + +```bash +{instructions} +``` + +</details> + +<details> +<summary> +View the output from clang-tidy here. +</summary> + +``` +{warning} +``` + +</details> +""" + + +def find_comment(pr: any) -> any: + for comment in pr.as_issue().get_comments(): + if COMMENT_TAG in comment.body: + return comment + return None + + +def create_comment( + comment_text: str, args: LintArgs, create_new: bool +) -> Optional[dict]: + import github + + repo = github.Github(args.token).get_repo(args.repo) + pr = repo.get_issue(args.issue_number).as_pull_request() + + comment_text = COMMENT_TAG + "\n\n" + comment_text + + existing_comment = find_comment(pr) + + comment = None + if create_new or existing_comment: + comment = {"body": comment_text} + if existing_comment: + comment["id"] = existing_comment.id + return comment + + +def run_clang_tidy(changed_files: List[str], args: LintArgs) -> Optional[str]: + if not changed_files: + print("no c/c++ files found") + return None + + git_diff_cmd = [ + "git", + "diff", + "-U0", + f"{args.start_rev}..{args.end_rev}", + "--", + ] + changed_files + + diff_proc = subprocess.run( + git_diff_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False, + ) + + if diff_proc.returncode != 0: + print(f"Git diff failed: {diff_proc.stderr}") + return None + + diff_content = diff_proc.stdout + if not diff_content.strip(): + print("No diff content found") + return None + + tidy_diff_cmd = [ + "code-lint-tools/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py", + "-path", + args.build_path, + "-p1", + "-quiet", + ] + + if args.verbose: + print(f"Running clang-tidy-diff: {' '.join(tidy_diff_cmd)}") + + proc = subprocess.run( + tidy_diff_cmd, + input=diff_content, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False, + ) + + return clean_clang_tidy_output(proc.stdout.strip()) + + +def run_linter(changed_files: List[str], args: LintArgs) -> tuple[bool, Optional[dict]]: + changed_files = [arg for arg in changed_files if "third-party" not in arg] + + cpp_files = filter_changed_files(changed_files) + + tidy_result = run_clang_tidy(cpp_files, args) + should_update_gh = args.token is not None and args.repo is not None + + comment = None + if tidy_result is None: + if should_update_gh: + comment_text = ( + ":white_check_mark: With the latest revision " + "this PR passed the C/C++ code linter." + ) + comment = create_comment(comment_text, args, create_new=False) + return True, comment + elif len(tidy_result) > 0: + if should_update_gh: + comment_text = create_comment_text(tidy_result, cpp_files) + comment = create_comment(comment_text, args, create_new=True) + else: + print( + "Warning: C/C++ code linter, clang-tidy detected " + "some issues with your code..." + ) + return False, comment + else: + # The linter failed but didn't output a result (e.g. some sort of + # infrastructure failure). + comment_text = ( + ":warning: The C/C++ code linter failed without printing " + "an output. Check the logs for output. :warning:" + ) + comment = create_comment(comment_text, args, create_new=False) + return False, comment + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--token", type=str, required=True, help="GitHub authentication token" + ) + parser.add_argument("--issue-number", type=int, required=True) + parser.add_argument( + "--repo", + type=str, + default=os.getenv("GITHUB_REPOSITORY", "llvm/llvm-project"), + help="The GitHub repository that we are working with in the form of <owner>/<repo> (e.g. llvm/llvm-project)", + ) + parser.add_argument( + "--start-rev", + type=str, + required=True, + help="Compute changes from this revision.", + ) + parser.add_argument( + "--end-rev", type=str, required=True, help="Compute changes to this revision" + ) + parser.add_argument( + "--changed-files", + type=str, + help="Comma separated list of files that has been changed", + ) + parser.add_argument( + "--build-path", + type=str, + default="build", + help="Path to build directory with compile_commands.json", + ) + parser.add_argument( + "--clang-tidy-binary", + type=str, + default="clang-tidy", + help="Path to clang-tidy binary", + ) + parser.add_argument( + "--verbose", action="store_true", default=True, help="Verbose output" + ) + + parsed_args = parser.parse_args() + args = LintArgs(parsed_args) + + changed_files = [] + if args.changed_files: + changed_files = args.changed_files.split(",") + + if args.verbose: + print(f"got changed files: {changed_files}") + + # Check for clang-tidy tool + if not has_clang_tidy(args.clang_tidy_binary): + print("Couldn't find C/C++ code linter: clang-tidy") + sys.exit(1) + + if args.verbose: + print("running linter clang-tidy") + + success, comment = run_linter(changed_files, args) + + if not success: + if args.verbose: + print("linter clang-tidy failed") + + # Write comments file if we have a comment + if comment: + if args.verbose: + print(f"linter clang-tidy has comment: {comment}") + + with open("comments", "w") as f: + import json + + json.dump([comment], f) + + if not success: + print("error: some linters failed: clang-tidy") + # Do not fail job for as it may be unstable + # sys.exit(1) diff --git a/llvm/utils/git/requirements_linting.txt b/llvm/utils/git/requirements_linting.txt new file mode 100644 index 0000000000000..b985b80aa869e --- /dev/null +++ b/llvm/utils/git/requirements_linting.txt @@ -0,0 +1,324 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --generate-hashes --output-file=requirements_linting.txt requirements_linting.txt.in +# +certifi==2025.8.3 \ + --hash=sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407 \ + --hash=sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5 + # via requests +cffi==1.17.1 \ + --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ + --hash=sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8 \ + --hash=sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36 \ + --hash=sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17 \ + --hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \ + --hash=sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702 \ + --hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6 \ + --hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \ + --hash=sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b \ + --hash=sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e \ + --hash=sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be \ + --hash=sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8 \ + --hash=sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1 \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \ + --hash=sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67 \ + --hash=sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595 \ + --hash=sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \ + --hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \ + --hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \ + --hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \ + --hash=sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3 \ + --hash=sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964 \ + --hash=sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c \ + --hash=sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576 \ + --hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \ + --hash=sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3 \ + --hash=sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9 \ + --hash=sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7 \ + --hash=sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382 \ + --hash=sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 \ + --hash=sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87 \ + --hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b + # via + # cryptography + # pynacl +charset-normalizer==3.4.3 \ + --hash=sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91 \ + --hash=sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0 \ + --hash=sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154 \ + --hash=sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601 \ + --hash=sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884 \ + --hash=sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07 \ + --hash=sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c \ + --hash=sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64 \ + --hash=sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe \ + --hash=sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f \ + --hash=sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432 \ + --hash=sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc \ + --hash=sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa \ + --hash=sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9 \ + --hash=sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae \ + --hash=sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19 \ + --hash=sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d \ + --hash=sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e \ + --hash=sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4 \ + --hash=sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7 \ + --hash=sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312 \ + --hash=sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92 \ + --hash=sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31 \ + --hash=sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c \ + --hash=sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f \ + --hash=sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99 \ + --hash=sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b \ + --hash=sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15 \ + --hash=sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392 \ + --hash=sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f \ + --hash=sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8 \ + --hash=sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491 \ + --hash=sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0 \ + --hash=sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc \ + --hash=sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0 \ + --hash=sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f \ + --hash=sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a \ + --hash=sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40 \ + --hash=sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927 \ + --hash=sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849 \ + --hash=sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce \ + --hash=sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14 \ + --hash=sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05 \ + --hash=sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c \ + --hash=sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c \ + --hash=sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a \ + --hash=sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc \ + --hash=sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34 \ + --hash=sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9 \ + --hash=sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096 \ + --hash=sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14 \ + --hash=sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30 \ + --hash=sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b \ + --hash=sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b \ + --hash=sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942 \ + --hash=sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db \ + --hash=sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5 \ + --hash=sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b \ + --hash=sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce \ + --hash=sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669 \ + --hash=sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0 \ + --hash=sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018 \ + --hash=sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93 \ + --hash=sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe \ + --hash=sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049 \ + --hash=sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a \ + --hash=sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef \ + --hash=sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2 \ + --hash=sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca \ + --hash=sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16 \ + --hash=sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f \ + --hash=sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb \ + --hash=sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1 \ + --hash=sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557 \ + --hash=sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37 \ + --hash=sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7 \ + --hash=sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72 \ + --hash=sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c \ + --hash=sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9 + # via requests +cryptography==45.0.6 \ + --hash=sha256:00e8724bdad672d75e6f069b27970883179bd472cd24a63f6e620ca7e41cc0c5 \ + --hash=sha256:048e7ad9e08cf4c0ab07ff7f36cc3115924e22e2266e034450a890d9e312dd74 \ + --hash=sha256:0d9ef57b6768d9fa58e92f4947cea96ade1233c0e236db22ba44748ffedca394 \ + --hash=sha256:18f878a34b90d688982e43f4b700408b478102dd58b3e39de21b5ebf6509c301 \ + --hash=sha256:1b7fa6a1c1188c7ee32e47590d16a5a0646270921f8020efc9a511648e1b2e08 \ + --hash=sha256:20ae4906a13716139d6d762ceb3e0e7e110f7955f3bc3876e3a07f5daadec5f3 \ + --hash=sha256:20d15aed3ee522faac1a39fbfdfee25d17b1284bafd808e1640a74846d7c4d1b \ + --hash=sha256:2384f2ab18d9be88a6e4f8972923405e2dbb8d3e16c6b43f15ca491d7831bd18 \ + --hash=sha256:275ba5cc0d9e320cd70f8e7b96d9e59903c815ca579ab96c1e37278d231fc402 \ + --hash=sha256:2dac5ec199038b8e131365e2324c03d20e97fe214af051d20c49db129844e8b3 \ + --hash=sha256:31a2b9a10530a1cb04ffd6aa1cd4d3be9ed49f7d77a4dafe198f3b382f41545c \ + --hash=sha256:3436128a60a5e5490603ab2adbabc8763613f638513ffa7d311c900a8349a2a0 \ + --hash=sha256:3b5bf5267e98661b9b888a9250d05b063220dfa917a8203744454573c7eb79db \ + --hash=sha256:3de77e4df42ac8d4e4d6cdb342d989803ad37707cf8f3fbf7b088c9cbdd46427 \ + --hash=sha256:44647c5d796f5fc042bbc6d61307d04bf29bccb74d188f18051b635f20a9c75f \ + --hash=sha256:550ae02148206beb722cfe4ef0933f9352bab26b087af00e48fdfb9ade35c5b3 \ + --hash=sha256:599c8d7df950aa68baa7e98f7b73f4f414c9f02d0e8104a30c0182a07732638b \ + --hash=sha256:5b64e668fc3528e77efa51ca70fadcd6610e8ab231e3e06ae2bab3b31c2b8ed9 \ + --hash=sha256:5bd6020c80c5b2b2242d6c48487d7b85700f5e0038e67b29d706f98440d66eb5 \ + --hash=sha256:5c966c732cf6e4a276ce83b6e4c729edda2df6929083a952cc7da973c539c719 \ + --hash=sha256:629127cfdcdc6806dfe234734d7cb8ac54edaf572148274fa377a7d3405b0043 \ + --hash=sha256:705bb7c7ecc3d79a50f236adda12ca331c8e7ecfbea51edd931ce5a7a7c4f012 \ + --hash=sha256:780c40fb751c7d2b0c6786ceee6b6f871e86e8718a8ff4bc35073ac353c7cd02 \ + --hash=sha256:7a3085d1b319d35296176af31c90338eeb2ddac8104661df79f80e1d9787b8b2 \ + --hash=sha256:826b46dae41a1155a0c0e66fafba43d0ede1dc16570b95e40c4d83bfcf0a451d \ + --hash=sha256:833dc32dfc1e39b7376a87b9a6a4288a10aae234631268486558920029b086ec \ + --hash=sha256:cc4d66f5dc4dc37b89cfef1bd5044387f7a1f6f0abb490815628501909332d5d \ + --hash=sha256:d063341378d7ee9c91f9d23b431a3502fc8bfacd54ef0a27baa72a0843b29159 \ + --hash=sha256:e2a21a8eda2d86bb604934b6b37691585bd095c1f788530c1fcefc53a82b3453 \ + --hash=sha256:e40b80ecf35ec265c452eea0ba94c9587ca763e739b8e559c128d23bff7ebbbf \ + --hash=sha256:e5b3dda1b00fb41da3af4c5ef3f922a200e33ee5ba0f0bc9ecf0b0c173958385 \ + --hash=sha256:ea3c42f2016a5bbf71825537c2ad753f2870191134933196bee408aac397b3d9 \ + --hash=sha256:eccddbd986e43014263eda489abbddfbc287af5cddfd690477993dbb31e31016 \ + --hash=sha256:ee411a1b977f40bd075392c80c10b58025ee5c6b47a822a33c1198598a7a5f05 \ + --hash=sha256:f4028f29a9f38a2025abedb2e409973709c660d44319c61762202206ed577c42 \ + --hash=sha256:f68f833a9d445cc49f01097d95c83a850795921b3f7cc6488731e69bde3288da \ + --hash=sha256:fc022c1fa5acff6def2fc6d7819bbbd31ccddfe67d075331a65d9cfb28a20983 + # via pyjwt +deprecated==1.2.18 \ + --hash=sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d \ + --hash=sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec + # via pygithub +idna==3.10 \ + --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ + --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 + # via requests +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc + # via cffi +pygithub==1.59.1 \ + --hash=sha256:3d87a822e6c868142f0c2c4bf16cce4696b5a7a4d142a7bd160e1bdf75bc54a9 \ + --hash=sha256:c44e3a121c15bf9d3a5cc98d94c9a047a5132a9b01d22264627f58ade9ddc217 + # via -r requirements_linting.txt.in +pyjwt[crypto]==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb + # via pygithub +pynacl==1.5.0 \ + --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ + --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ + --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ + --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ + --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ + --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ + --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ + --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ + --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ + --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 + # via pygithub +requests==2.32.5 \ + --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ + --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf + # via pygithub +urllib3==2.5.0 \ + --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \ + --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc + # via requests +wrapt==1.17.3 \ + --hash=sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56 \ + --hash=sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828 \ + --hash=sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f \ + --hash=sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396 \ + --hash=sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77 \ + --hash=sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d \ + --hash=sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139 \ + --hash=sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7 \ + --hash=sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb \ + --hash=sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f \ + --hash=sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f \ + --hash=sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067 \ + --hash=sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f \ + --hash=sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7 \ + --hash=sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b \ + --hash=sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc \ + --hash=sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05 \ + --hash=sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd \ + --hash=sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7 \ + --hash=sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9 \ + --hash=sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81 \ + --hash=sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977 \ + --hash=sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa \ + --hash=sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b \ + --hash=sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe \ + --hash=sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58 \ + --hash=sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8 \ + --hash=sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77 \ + --hash=sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85 \ + --hash=sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c \ + --hash=sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df \ + --hash=sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454 \ + --hash=sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a \ + --hash=sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e \ + --hash=sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c \ + --hash=sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6 \ + --hash=sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5 \ + --hash=sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9 \ + --hash=sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd \ + --hash=sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277 \ + --hash=sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225 \ + --hash=sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22 \ + --hash=sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116 \ + --hash=sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16 \ + --hash=sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc \ + --hash=sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00 \ + --hash=sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2 \ + --hash=sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a \ + --hash=sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804 \ + --hash=sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04 \ + --hash=sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1 \ + --hash=sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba \ + --hash=sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390 \ + --hash=sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0 \ + --hash=sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d \ + --hash=sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22 \ + --hash=sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0 \ + --hash=sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2 \ + --hash=sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18 \ + --hash=sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6 \ + --hash=sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311 \ + --hash=sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89 \ + --hash=sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f \ + --hash=sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39 \ + --hash=sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4 \ + --hash=sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5 \ + --hash=sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa \ + --hash=sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a \ + --hash=sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050 \ + --hash=sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6 \ + --hash=sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235 \ + --hash=sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056 \ + --hash=sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2 \ + --hash=sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418 \ + --hash=sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c \ + --hash=sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a \ + --hash=sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6 \ + --hash=sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0 \ + --hash=sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775 \ + --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ + --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c + # via deprecated diff --git a/llvm/utils/git/requirements_linting.txt.in b/llvm/utils/git/requirements_linting.txt.in new file mode 100644 index 0000000000000..33c997c022315 --- /dev/null +++ b/llvm/utils/git/requirements_linting.txt.in @@ -0,0 +1 @@ +PyGithub==1.59.1 >From 0b26149c9869886fd61b7ec23f7fbefa59bbd23f Mon Sep 17 00:00:00 2001 From: Victor Baranov <bar.victor.2...@gmail.com> Date: Sun, 24 Aug 2025 12:07:26 +0300 Subject: [PATCH 3/3] WIP --- .github/workflows/pr-code-lint.yml | 11 +--- llvm/utils/git/code-lint-helper.py | 92 ++++++++++++------------------ 2 files changed, 40 insertions(+), 63 deletions(-) diff --git a/.github/workflows/pr-code-lint.yml b/.github/workflows/pr-code-lint.yml index ddf69761b15e6..109737d19b899 100644 --- a/.github/workflows/pr-code-lint.yml +++ b/.github/workflows/pr-code-lint.yml @@ -58,16 +58,10 @@ jobs: sparse-checkout-cone-mode: false path: code-lint-tools - - uses: actions/setup-python@v5 - id: setup_python + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: '3.12' - - - name: Install dependencies - run: | - python3 -m venv .venv - source .venv/bin/activate - python3 -m pip install -r code-lint-tools/llvm/utils/git/requirements_linting.txt + - run: pip install --upgrade pip && pip install -r code-lint-tools/llvm/utils/git/requirements_linting.txt - name: Install clang-tidy uses: aminya/setup-cpp@17c11551771948abc5752bbf3183482567c7caf0 # v1.1.1 @@ -107,7 +101,6 @@ jobs: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} run: | - source .venv/bin/activate echo "[]" > comments && python3 ./code-lint-tools/llvm/utils/git/code-lint-helper.py \ --token ${{ secrets.GITHUB_TOKEN }} \ diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index de6d5cb7fc9e3..e012618137998 100755 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -7,14 +7,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # ==-------------------------------------------------------------------------==# +"""A helper script to run linters in GitHub actions -import argparse -import os -import subprocess -import sys -from typing import List, Optional - -""" This script is run by GitHub actions to ensure that the code in PR's conform to the coding style of LLVM. The canonical source of this script is in the LLVM source tree under llvm/utils/git. @@ -23,6 +17,12 @@ https://llvm.org/docs/CodingStandards.html """ +import argparse +import os +import subprocess +import textwrap +from typing import List, Optional + class LintArgs: start_rev: str = None @@ -53,10 +53,10 @@ def __init__(self, args: argparse.Namespace = None) -> None: def get_instructions(cpp_files: List[str]) -> str: files_str = " ".join(cpp_files) - return f""" -git diff -U0 origin/main..HEAD -- {files_str} | -python3 clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py \\ - -path build -p1 -quiet""" + return textwrap.dedent(f"""\ + git diff -U0 origin/main...HEAD -- {files_str} | + python3 clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py \\ + -path build -p1 -quiet""") def clean_clang_tidy_output(output: str) -> Optional[str]: @@ -86,9 +86,8 @@ def clean_clang_tidy_output(output: str) -> Optional[str]: return "\n".join(cleaned_lines) return None - +# TODO: Add more rules when enabling other projects to use clang-tidy in CI. def should_lint_file(filepath: str) -> bool: - # For add other paths/files to this function return filepath.startswith("clang-tools-extra/clang-tidy/") @@ -106,43 +105,33 @@ def filter_changed_files(changed_files: List[str]) -> List[str]: return filtered_files -def has_clang_tidy(clang_tidy_binary: str) -> bool: - cmd = [clang_tidy_binary, "--version"] - proc = None - try: - proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except: - return False - return proc.returncode == 0 - - def create_comment_text(warning: str, cpp_files: List[str]) -> str: instructions = get_instructions(cpp_files) - return f""" -:warning: C/C++ code linter clang-tidy found issues in your code. :warning: - -<details> -<summary> -You can test this locally with the following command: -</summary> - -```bash -{instructions} -``` - -</details> - -<details> -<summary> -View the output from clang-tidy here. -</summary> - -``` -{warning} -``` - -</details> -""" + return textwrap.dedent(f"""\ + :warning: C/C++ code linter clang-tidy found issues in your code. :warning: + + <details> + <summary> + You can test this locally with the following command: + </summary> + + ```bash + {instructions} + ``` + + </details> + + <details> + <summary> + View the output from clang-tidy here. + </summary> + + ``` + {warning} + ``` + + </details> + """) def find_comment(pr: any) -> any: @@ -181,7 +170,7 @@ def run_clang_tidy(changed_files: List[str], args: LintArgs) -> Optional[str]: "git", "diff", "-U0", - f"{args.start_rev}..{args.end_rev}", + f"{args.start_rev}...{args.end_rev}", "--", ] + changed_files @@ -315,11 +304,6 @@ def run_linter(changed_files: List[str], args: LintArgs) -> tuple[bool, Optional if args.verbose: print(f"got changed files: {changed_files}") - # Check for clang-tidy tool - if not has_clang_tidy(args.clang_tidy_binary): - print("Couldn't find C/C++ code linter: clang-tidy") - sys.exit(1) - if args.verbose: print("running linter clang-tidy") _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits