diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4b31915 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: Copyright (c) <2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 10 + container: + image: python:3.10-slim + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Install lint dependencies + env: + PIP_BREAK_SYSTEM_PACKAGES: 1 + run: pip install --no-cache-dir flake8==7.3.0 reuse==5.1.0 + + - name: Run flake8 + run: flake8 + + - name: Run cpplint + run: python ci/cpplint.py + + - name: Check license headers (REUSE) + run: ci/scripts/check_license.sh + + - name: Check inline samples are up to date + run: python test/tools/inline_samples.py --check diff --git a/ci/cpplint.py b/ci/cpplint.py new file mode 100755 index 0000000..8606b76 --- /dev/null +++ b/ci/cpplint.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: Copyright (c) <2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import sys + +file_extensions = [ + ".h", + ".hpp", + ".hh", + ".c", + ".C", + ".cpp", + ".cxx", + ".cc", + ".pyx", + ".pxd", +] +max_line_len = 100 + + +def should_lint(filename: str): + return any(filename.endswith(x) for x in file_extensions) + + +def lint(paths): + num_errors = 0 + num_files = 0 + + def report_error(message: str): + nonlocal num_errors + print(f"{full_name[len(path) + 1:]}:{i + 1}: {message}", file=sys.stderr) + num_errors += 1 + + for path in paths: + for root, dirs, files in os.walk(path): + for filename in files: + if not should_lint(filename): + continue + full_name = os.path.join(root, filename) + with open(full_name, "r") as f: + for i, line in enumerate(f): + if "noqa" in line: + continue + if "SPDX" in line: + continue + + length = len(line) + if line.endswith("\n"): + length -= 1 + if length > max_line_len: + report_error( + f"Line is longer than {max_line_len} characters" + ) + if length > 0 and line[length - 1].isspace(): + report_error("Trailing whitespace at the end of the line") + num_files += 1 + + if num_errors > 0: + print(f"Found {num_errors} errors", file=sys.stderr) + sys.exit(1) + elif num_files == 0: + print("No input files found!", file=sys.stderr) + sys.exit(2) + else: + print(f"Checked {num_files} files, all OK") + + +if __name__ == "__main__": + script_dir = os.path.dirname(__file__) + project_root = os.getcwd() + dirs = ["cext", "src"] + paths = [os.path.join(project_root, d) for d in dirs] + lint(paths) diff --git a/ci/scripts/check_license.sh b/ci/scripts/check_license.sh new file mode 100755 index 0000000..c894005 --- /dev/null +++ b/ci/scripts/check_license.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# SPDX-FileCopyrightText: Copyright (c) <2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +ignore_files=("src/cuda/tile/VERSION") +outputs=$(reuse lint --lines | grep -v ${ignore_files[@]/#/-e }) +if [ -n "$outputs" ]; then + echo -e "License check failed\n${outputs}" + exit 1 +fi