├── LICENCE ├── README.md ├── action.yaml └── entrypoint.py /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Puneet Matharu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cmake-format lint action 2 | 3 | Formats CMake-specific files to the desired format using [`cmake-format`](https://github.com/cheshirekow/cmake_format). To control the style of formatting, make sure to add a configuration file to the root of your project. For details on how to do this, see [Configuration](https://cmake-format.readthedocs.io/en/latest/configuration.html#configuration). 4 | 5 | **Note:** The current version of this action will format all `CMakeLists.txt` and `*.cmake` files in your project. If you require finer granularity, please request this feature (or any other features) by creating an Issue on the repository page. 6 | 7 | ## Usage 8 | 9 | To use this action, pass arguments to the `args` element as you would to `cmake-format` - these arguments will be used to format each CMake file. For example 10 | 11 | ```yaml 12 | - name: Format CMake files 13 | id: cmake-format 14 | uses: puneetmatharu/cmake-format-lint-action@v1.0.6 15 | with: 16 | # Arguments to be passed to cmake-format. 17 | # 18 | # Options: 19 | # -h, --help show this help message and exit 20 | # -v, --version show program's version number and exit 21 | # -l {error,warning,info,debug}, --log-level {error,warning,info,debug} 22 | # --dump-config [{yaml,json,python}] 23 | # If specified, print the default configuration to stdout and exit 24 | # --dump {lex,parse,parsedb,layout,markup} 25 | # --no-help When used with --dump-config, will omit helptext comments in the output 26 | # --no-default When used with --dump-config, will omit any unmodified configuration value. 27 | # -i, --in-place 28 | # --check Exit with status code 0 if formatting would not change file contents, or status code 1 if it would 29 | # -o OUTFILE_PATH, --outfile-path OUTFILE_PATH 30 | # Where to write the formatted file. Default is stdout. 31 | # -c CONFIG_FILES [CONFIG_FILES ...], --config-files CONFIG_FILES [CONFIG_FILES ...] 32 | # path to configuration file(s) 33 | args: --config-files .cmake-format.json --in-place 34 | 35 | # Regex to select which files to apply cmake-format on. 36 | # 37 | # Defaults to '(.*\.cmake$|CMakeLists.txt$)' 38 | file-regex: '(.*\.cmake$|.*\.cmake\.in$|CMakeLists.txt$)' 39 | ``` 40 | 41 | You will probably want to pair this with a GitHub Action (such as 42 | [`stefanzweifel/git-auto-commit-action`](https://github.com/stefanzweifel/git-auto-commit-action)) 43 | to commit any modified files. For example: 44 | 45 | ```yaml 46 | name: Run cmake-format linter 47 | 48 | on: [push] 49 | 50 | jobs: 51 | build: 52 | runs-on: ubuntu-latest 53 | 54 | steps: 55 | - name: Checkout repository 56 | uses: actions/checkout@v4 57 | 58 | - name: Format CMake files 59 | id: cmake-format 60 | uses: puneetmatharu/cmake-format-lint-action@v1.0.6 61 | with: 62 | args: --config-files .cmake-format.json --in-place 63 | file-regex: '(.*\.cmake$|.*\.cmake\.in$|CMakeLists.txt$)' 64 | 65 | - name: Commit changes 66 | uses: stefanzweifel/git-auto-commit-action@v5 67 | with: 68 | commit_user_name: cmake-format-bot 69 | commit_message: 'Automated commit of cmake-format changes.' 70 | ``` 71 | 72 | ## Licence 73 | 74 | The files distributed with this Action are provided under the blanket of an [MIT licence](LICENCE). 75 | -------------------------------------------------------------------------------- /action.yaml: -------------------------------------------------------------------------------- 1 | name: "cmake-format lint action" 2 | author: "Puneet Matharu" 3 | description: "A GitHub Action to format CMake-specific files using cmake-format (v0.6.13)" 4 | branding: 5 | icon: "code" 6 | color: "blue" 7 | 8 | inputs: 9 | args: 10 | description: | 11 | Arguments to supply to cmake-format. 12 | 13 | Options: 14 | -h, --help show this help message and exit 15 | -v, --version show program's version number and exit 16 | -l {error,warning,info,debug}, --log-level {error,warning,info,debug} 17 | --dump-config [{yaml,json,python}] 18 | If specified, print the default configuration to stdout and exit 19 | --dump {lex,parse,parsedb,layout,markup} 20 | --no-help When used with --dump-config, will omit helptext comments in the output 21 | --no-default When used with --dump-config, will omit any unmodified configuration value. 22 | -i, --in-place 23 | --check Exit with status code 0 if formatting would not change file contents, or status code 1 if it would 24 | -o OUTFILE_PATH, --outfile-path OUTFILE_PATH 25 | Where to write the formatted file. Default is stdout. 26 | -c CONFIG_FILES [CONFIG_FILES ...], --config-files CONFIG_FILES [CONFIG_FILES ...] 27 | path to configuration file(s) 28 | required: true 29 | default: "--help" 30 | 31 | file-regex: 32 | description: | 33 | Regex to select which files to apply cmake-format on. 34 | 35 | Defaults to '(.*\.cmake$|CMakeLists.txt$)' 36 | required: false 37 | default: '(.*\.cmake$|CMakeLists.txt$)' 38 | 39 | runs: 40 | using: "composite" 41 | steps: 42 | - name: Set up python3 43 | uses: actions/setup-python@v5 44 | with: 45 | python-version: 3.9 46 | 47 | - name: Install cmake-format 48 | shell: bash 49 | run: python3 -m pip install --no-cache-dir "Cython<3" "cmakelang[YAML]==0.6.13" 50 | 51 | - name: Format CMake files 52 | shell: bash 53 | run: python3 ${{ github.action_path }}/entrypoint.py --cmake-format-args='${{ inputs.args }}' --file-regex='${{ inputs.file-regex }}' 54 | -------------------------------------------------------------------------------- /entrypoint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import re 6 | import subprocess 7 | from pathlib import Path 8 | from multiprocessing import Pool 9 | from typing import Tuple, Optional 10 | 11 | 12 | def format_cmake_file(file_and_args: Tuple[Path, str]) -> Optional[str]: 13 | (file_path, cmake_format_args) = file_and_args 14 | cmake_command = f"cmake-format {cmake_format_args} {file_path}" 15 | cmake_format_result = subprocess.run(cmake_command, shell=True, capture_output=True, text=True) 16 | if cmake_format_result.returncode != 0: 17 | return f"Error formatting {file_path}: {cmake_format_result.stderr}" 18 | return f"Successfully formatted {file_path}!" 19 | 20 | 21 | def parse_args() -> argparse.Namespace: 22 | parser = argparse.ArgumentParser(description="Format CMake files using cmake-format.") 23 | parser.add_argument('--file-regex', required=True, help="Regex pattern to match filenames.") 24 | parser.add_argument('--cmake-format-args', required=True, help="Additional arguments for cmake-format.") 25 | args = parser.parse_args() 26 | if len(args.file_regex) == 0: 27 | parser.error("The --file-regex argument cannot be empty.") 28 | return args 29 | 30 | 31 | if __name__ == "__main__": 32 | args = parse_args() 33 | 34 | file_regex = re.compile(args.file_regex) 35 | workspace_path = Path(os.environ['GITHUB_WORKSPACE']) 36 | 37 | matched_files = [ 38 | (file_path, args.cmake_format_args) 39 | for file_path in workspace_path.rglob('*') 40 | if file_path.is_file() and file_regex.match(file_path.name) 41 | ] 42 | 43 | if len(matched_files) > 0: 44 | with Pool() as pool: 45 | format_results = pool.map(format_cmake_file, matched_files) 46 | for result in format_results: 47 | print(result) 48 | else: 49 | print("No files matched the given regex.") --------------------------------------------------------------------------------