├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── dependabot.yml ├── release-drafter.yml └── workflows │ ├── cpp-linter.yml │ ├── labeler.yml │ ├── mkdocs-deploy.yml │ ├── pre-commit.yml │ ├── release-drafter.yml │ ├── release.yml │ ├── self-test.yml │ └── stale.yml ├── .gitignore ├── .gitpod.yml ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── action.yml ├── docs ├── README.rst ├── action.yml ├── badge_hook.py ├── contributing-guidelines.md ├── examples │ ├── demo │ │ ├── .clang-format │ │ ├── .clang-tidy │ │ ├── CMakeLists.txt │ │ ├── compile_flags.txt │ │ ├── demo.cpp │ │ └── demo.hpp │ ├── index.md │ ├── only-PR-comments.yml │ ├── only-clang-format.yml │ └── only-clang-tidy.yml ├── gen_io_doc.py ├── images │ ├── annotations-clang-format.png │ ├── annotations-clang-tidy.png │ ├── comment.png │ ├── favicon.ico │ ├── format-review.png │ ├── format-suggestion.png │ ├── logo.png │ ├── step-summary.png │ └── tidy-review.png ├── index.md ├── permissions.md ├── pr-review-caveats.md ├── requirements.txt └── stylesheets │ └── extra.css ├── mkdocs.yml └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.py text eol=lf 7 | *.rst text eol=lf 8 | *.sh text eol=lf 9 | *.cpp text eol=lf 10 | *.hpp text eol=lf 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Report a problem 2 | description: Create a report to let us help you 3 | body: 4 | - type: textarea 5 | attributes: 6 | label: What events trigger your workflow? 7 | id: ci-triggers 8 | description: >- 9 | Please copy and paste the workflow triggers. 10 | If you are using a resuable workflow (`workflow_dispatch` event), 11 | then please also include the workflow triggers that the calling workflow uses. 12 | placeholder: |- 13 | on: 14 | pull_request: 15 | branches: [main, master, develop] 16 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 17 | push: 18 | branches: [main, master, develop] 19 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 20 | render: yml 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | id: runner-os 26 | attributes: 27 | label: What OS does your workflow use? 28 | description: >- 29 | Please tell us what OS the workflow [`runs-on`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on). 30 | If you are using an additional [`container`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontainer), 31 | then please also include that information here. 32 | placeholder: |- 33 | runs-on: ubuntu-latest 34 | container: node:18 35 | render: yml 36 | validations: 37 | required: true 38 | 39 | - type: textarea 40 | id: cpp-linter-config 41 | attributes: 42 | label: How is cpp-linter-action configured? 43 | description: >- 44 | Please copy and paste the version and inputs used to run cpp-linter-action. 45 | placeholder: |- 46 | - uses: cpp-linter/cpp-linter-action@v2 47 | id: linter 48 | env: 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | with: 51 | style: 'file' 52 | tidy-checks: '' 53 | render: yml 54 | validations: 55 | required: true 56 | 57 | - type: textarea 58 | id: what-happened 59 | attributes: 60 | label: What was the unexpected behavior? 61 | description: >- 62 | Use this area to describe what behavior you expected and what behavior you observed. 63 | Please be clear and concise as possible. Use screenshots if that would help. Most users 64 | use this to paste the workflow logs. 65 | placeholder: You can use markdown syntax here 66 | validations: 67 | required: true 68 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # this setting will force users to use the provided issue templates 2 | blank_issues_enabled: false 3 | # if the templates provided don't fit the subject of the user feedback, 4 | # here we can give links to other forms of user feedback 5 | contact_links: 6 | - name: cpp-linter discussions 7 | url: https://github.com/orgs/cpp-linter/discussions 8 | about: A place for feedback not specific to cpp-linter-action 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | description: Suggest an idea for this project 4 | body: 5 | - type: dropdown 6 | id: existing-feature 7 | attributes: 8 | label: Is your idea related to an existing feature? 9 | description: >- 10 | If this idea is related to an already available feature(s), then please list them here. 11 | multiple: true 12 | options: 13 | - version 14 | - database 15 | - thread-comments 16 | - tidy-checks 17 | - style 18 | - lines-changed-only 19 | - ignore 20 | - tidy-ignore 21 | - format-ignore 22 | - files-changed-only 23 | - file-annotations 24 | - step-summary 25 | - no-lgtm 26 | - tidy-review 27 | - format-review 28 | - passive-reviews 29 | - verbosity 30 | - 'output: checks-failed' 31 | - 'output: clang-tidy-checks-failed' 32 | - 'output: clang-format-checks-failed' 33 | 34 | - type: textarea 35 | id: behavior 36 | attributes: 37 | label: Describe the behavior you would like 38 | description: >- 39 | Use this area to describe what behavior you desire. 40 | Please be clear and concise as possible. Use screenshots if that would help. 41 | placeholder: You can use markdown syntax here 42 | validations: 43 | required: true 44 | 45 | - type: textarea 46 | id: alternative 47 | attributes: 48 | label: Describe alternatives you have considered 49 | description: >- 50 | Were you able to achieve the desired behavior in some other/inconvenient way? 51 | placeholder: You can use markdown syntax here 52 | 53 | - type: textarea 54 | id: added-context 55 | attributes: 56 | label: Additional context 57 | description: >- 58 | If there is anything that might be special or specific to your usage, please let us know. 59 | placeholder: You can use markdown syntax here 60 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: github-actions 9 | directory: / 10 | schedule: 11 | interval: "weekly" 12 | groups: 13 | actions: 14 | patterns: 15 | - "*" 16 | - package-ecosystem: pip 17 | directory: / 18 | schedule: 19 | interval: "daily" 20 | groups: 21 | pip: 22 | patterns: 23 | - "*" 24 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | _extends: .github 2 | -------------------------------------------------------------------------------- /.github/workflows/cpp-linter.yml: -------------------------------------------------------------------------------- 1 | name: cpp-linter 2 | 3 | on: 4 | push: 5 | paths: 6 | - "docs/examples/demo/*" 7 | pull_request: 8 | paths: 9 | - "docs/examples/demo/*" 10 | 11 | 12 | jobs: 13 | cpp-linter: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: cpp-linter/cpp-linter-action@main 18 | id: linter 19 | continue-on-error: true 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | style: file 24 | files-changed-only: false 25 | thread-comments: false 26 | 27 | - name: Fail fast?! 28 | if: steps.linter.outputs.checks-failed != 0 29 | run: | 30 | echo "some linter checks failed. ${{ steps.linter.outputs.checks-failed }}" 31 | # for actual deployment 32 | # run: exit 1 33 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: PR Autolabeler 2 | 3 | on: 4 | # pull_request event is required for autolabeler 5 | pull_request: 6 | types: [opened, reopened, synchronize] 7 | 8 | jobs: 9 | draft-release: 10 | uses: cpp-linter/.github/.github/workflows/release-drafter.yml@main 11 | -------------------------------------------------------------------------------- /.github/workflows/mkdocs-deploy.yml: -------------------------------------------------------------------------------- 1 | name: MkDocs Deploy 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build-docs: 9 | uses: cpp-linter/.github/.github/workflows/mkdocs.yml@main 10 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | name: Run pre-commit 2 | 3 | on: 4 | push: 5 | pull_request: 6 | types: opened 7 | 8 | jobs: 9 | pre-commit: 10 | uses: cpp-linter/.github/.github/workflows/pre-commit.yml@main 11 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | workflow_dispatch: 8 | 9 | jobs: 10 | draft-release: 11 | uses: cpp-linter/.github/.github/workflows/release-drafter.yml@main 12 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | branches: [main] 6 | types: [published] 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: 'which tag to update to' 11 | default: 'v2' 12 | required: true 13 | ref: 14 | description: 'which branch to update the tag on' 15 | default: 'main' 16 | required: true 17 | 18 | jobs: 19 | re-tag: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | ref: ${{ inputs.ref }} 26 | - name: Config git name and email 27 | run: | 28 | git config user.name 'github-actions' 29 | git config user.email '41898282+github-actions[bot]@users.noreply.github.com' 30 | - name: Update tag with parameter 31 | if: github.event.inputs.tag != '' 32 | run: | 33 | git tag --delete ${{ inputs.tag }} || true 34 | git push --delete origin ${{ inputs.tag }} || true 35 | git tag -a ${{ inputs.tag }} -m 'Retag ${{ inputs.tag }}' 36 | git push origin ${{ inputs.tag }} 37 | - name: Update tag to v2 38 | if: github.event.inputs.tag == '' 39 | run: | 40 | git tag --delete v2 || true 41 | git push --delete origin v2 || true 42 | git tag -a v2 -m 'Retag v2' 43 | git push origin v2 44 | -------------------------------------------------------------------------------- /.github/workflows/self-test.yml: -------------------------------------------------------------------------------- 1 | name: Self test action 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | paths: 7 | - 'action.yml' 8 | - 'requirements.txt' 9 | - 'docs/examples/demo/**' 10 | - '.github/workflows/self-test.yml' 11 | pull_request: 12 | branches: main 13 | paths: 14 | - 'action.yml' 15 | - 'requirements.txt' 16 | - 'docs/examples/demo/**' 17 | - '.github/workflows/self-test.yml' 18 | pull_request_target: 19 | branches: main 20 | paths: 21 | - 'action.yml' 22 | - 'requirements.txt' 23 | - 'docs/examples/demo/**' 24 | - '.github/workflows/self-test.yml' 25 | 26 | jobs: 27 | test: 28 | permissions: 29 | contents: write 30 | pull-requests: write 31 | strategy: 32 | matrix: 33 | os: [ ubuntu-latest, macos-latest, windows-latest ] 34 | clang-version: ['8','9','10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20'] 35 | fail-fast: false 36 | runs-on: ${{ matrix.os }} 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v4 40 | 41 | - name: Cache the build artifacts 42 | id: cache-build 43 | uses: actions/cache@v4 44 | with: 45 | path: build 46 | key: ${{ runner.os }}-${{ hashFiles('docs/examples/demo/**') }} 47 | 48 | - name: Generate compilation database 49 | if: steps.cache-build.outputs.cache-hit != 'true' 50 | run: mkdir build && cmake -Bbuild docs/examples/demo 51 | 52 | - name: Self test action 53 | uses: ./ 54 | id: linter 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | with: 58 | style: file 59 | files-changed-only: false 60 | # to ignore all build folder contents 61 | ignore: build|venv 62 | database: build 63 | verbosity: debug 64 | version: ${{ matrix.clang-version }} 65 | thread-comments: ${{ matrix.clang-version == '12' && 'update' }} 66 | file-annotations: ${{ runner.os == 'Linux' && matrix.clang-version == '12' }} 67 | step-summary: ${{ matrix.clang-version == '12' }} 68 | extra-args: -std=c++14 -Wall 69 | 70 | - name: Fail fast?! 71 | # if: steps.linter.outputs.checks-failed > 0 72 | run: | 73 | echo "some linter checks failed" 74 | echo "total checks-failed: ${{ steps.linter.outputs.checks-failed }}" 75 | echo "clang-tidy checks-failed: ${{ steps.linter.outputs.clang-tidy-checks-failed }}" 76 | echo "clang-format checks-failed: ${{ steps.linter.outputs.clang-format-checks-failed }}" 77 | # for actual deployment 78 | # run: exit 1 79 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Close stale issues' 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | permissions: 6 | issues: write 7 | 8 | jobs: 9 | stale: 10 | uses: cpp-linter/.github/.github/workflows/stale.yml@main 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # local demo specific 2 | .changed_files.json 3 | clang_format*.txt 4 | clang_tidy*.txt 5 | act.exe 6 | clang_tidy_output.yml 7 | clang_format_output.xml 8 | event_payload.json 9 | comments.json 10 | 11 | #### ignores for Python 12 | # Byte-compiled / optimized / DLL files 13 | __pycache__/ 14 | *.py[cod] 15 | *$py.class 16 | 17 | # Distribution / packaging 18 | .Python 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib/ 26 | lib64/ 27 | parts/ 28 | sdist/ 29 | var/ 30 | wheels/ 31 | pip-wheel-metadata/ 32 | share/python-wheels/ 33 | *.egg-info/ 34 | .installed.cfg 35 | *.egg 36 | MANIFEST 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | *.spec 43 | 44 | # Installer logs 45 | pip-log.txt 46 | pip-delete-this-directory.txt 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .nox/ 52 | .coverage 53 | .coverage.* 54 | .cache 55 | nosetests.xml 56 | coverage.xml 57 | *.cover 58 | *.py,cover 59 | .hypothesis/ 60 | .pytest_cache/ 61 | tests/*/test*.json 62 | tests/**/*.c 63 | 64 | # Translations 65 | *.mo 66 | *.pot 67 | 68 | # Django stuff: 69 | *.log 70 | local_settings.py 71 | db.sqlite3 72 | db.sqlite3-journal 73 | 74 | # Flask stuff: 75 | instance/ 76 | .webassets-cache 77 | 78 | # Scrapy stuff: 79 | .scrapy 80 | 81 | # Sphinx documentation 82 | docs/_build/ 83 | 84 | # PyBuilder 85 | target/ 86 | 87 | # Jupyter Notebook 88 | .ipynb_checkpoints 89 | 90 | # IPython 91 | profile_default/ 92 | ipython_config.py 93 | 94 | # pyenv 95 | .python-version 96 | 97 | # pipenv 98 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 99 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 100 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 101 | # install all needed dependencies. 102 | #Pipfile.lock 103 | 104 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 105 | __pypackages__/ 106 | 107 | # Celery stuff 108 | celerybeat-schedule 109 | celerybeat.pid 110 | 111 | # SageMath parsed files 112 | *.sage.py 113 | 114 | # Environments 115 | .env 116 | .venv 117 | env/ 118 | venv/ 119 | ENV/ 120 | env.bak/ 121 | venv.bak/ 122 | 123 | # Spyder project settings 124 | .spyderproject 125 | .spyproject 126 | 127 | # Rope project settings 128 | .ropeproject 129 | 130 | # mkdocs documentation 131 | /site 132 | 133 | # mypy 134 | .mypy_cache/ 135 | .dmypy.json 136 | dmypy.json 137 | 138 | # Pyre type checker 139 | .pyre/ 140 | 141 | # exclude local VSCode's settings folder 142 | .vscode/ 143 | 144 | #### ignores for C++ 145 | # Prerequisites 146 | *.d 147 | 148 | # Compiled Object files 149 | *.slo 150 | *.lo 151 | *.o 152 | *.obj 153 | 154 | # Precompiled Headers 155 | *.gch 156 | *.pch 157 | 158 | # Compiled Dynamic libraries 159 | *.so 160 | *.dylib 161 | *.dll 162 | 163 | # Fortran module files 164 | *.mod 165 | *.smod 166 | 167 | # Compiled Static libraries 168 | *.lai 169 | *.la 170 | *.a 171 | *.lib 172 | 173 | # Executables 174 | *.exe 175 | *.out 176 | *.app 177 | 178 | # Cmake build-in-source generated stuff 179 | CMakeUserPresets.json 180 | CMakeCache.txt 181 | CPackConfig.cmake 182 | CPackSourceConfig.cmake 183 | CMakeFiles 184 | cmake_install.cmake 185 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | 5 | tasks: 6 | - init: pip install -r requirements.txt pre-commit 7 | command: pre-commit install 8 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.5.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: end-of-file-fixer 7 | - id: check-added-large-files 8 | - id: check-yaml 9 | # special mkdocs config to include inline icons fails (see `pymdownx.emoji` in mkdocs.yml) 10 | args: ['--unsafe'] # use `--unsafe` to workaround yaml loading 11 | - id: requirements-txt-fixer 12 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for MkDocs projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the version of Python and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.12" 12 | 13 | mkdocs: 14 | configuration: mkdocs.yml 15 | 16 | # Optionally declare the Python requirements required to build your docs 17 | python: 18 | install: 19 | - requirements: docs/requirements.txt 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for investing your time in contributing to our project! We welcome feedback, bug reports, and pull requests! 4 | 5 | ## New contributor guide 6 | 7 | Ours develop branch is `main` not `master` (`master` used to be the develop branch for v1.x). 8 | 9 | The reason we didn't delete the `master` branch is that there are still users whose workflows point to the `master` branch. 10 | 11 | For pull requests, please stick to the following guidelines 12 | 13 | * Add tests for any new features and bug fixes. 14 | * Put a reasonable amount of comments into the code. 15 | * Fork cpp-linter-action on your GitHub user account, do your changes there and then create a PR against `main` branch of cpp-linter-action repository. 16 | * Separate unrelated changes into multiple pull requests. 17 | 18 | If you wish to contribute to the python source package used by this action, then that has moved to it's own repository named [cpp-linter](https://github.com/cpp-linter/cpp-linter) as of v2 of this action. 19 | 20 | Please note that by contributing any code or documentation to this repository (by raising pull requests, or otherwise) you explicitly agree to the [License Agreement](https://github.com/cpp-linter/cpp-linter-action/blob/main/LICENSE). 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 shenxianpeng 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 | [file-annotations]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs/#file-annotations 2 | [thread-comments]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs/#thread-comments 3 | [step-summary]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs/#step-summary 4 | [tidy-review]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs/#tidy-review 5 | [format-review]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs/#format-review 6 | 7 | [io-doc]: https://cpp-linter.github.io/cpp-linter-action/inputs-outputs 8 | [recipes-doc]: https://cpp-linter.github.io/cpp-linter-action/examples 9 | 10 | [format-annotations-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/annotations-clang-format.png 11 | [tidy-annotations-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/annotations-clang-tidy.png 12 | [thread-comment-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/comment.png 13 | [step-summary-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/step-summary.png 14 | [tidy-review-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/tidy-review.png 15 | [format-review-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/format-review.png 16 | [format-suggestion-preview]: https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/main/docs/images/format-suggestion.png 17 | 18 | 19 | 20 | # C/C++ Linter Action | clang-format & clang-tidy 21 | 22 | ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/cpp-linter/cpp-linter-action) 23 | [![GitHub marketplace](https://img.shields.io/badge/marketplace-C%2FC%2B%2B%20Linter-blue?logo=github)](https://github.com/marketplace/actions/c-c-linter) 24 | [![cpp-linter](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml) 25 | [![MkDocs Deploy](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/mkdocs-deploy.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/mkdocs-deploy.yml) 26 | ![GitHub](https://img.shields.io/github/license/cpp-linter/cpp-linter-action?label=license&logo=github) 27 | 28 | A Github Action for linting C/C++ code integrating clang-tidy and clang-format 29 | to collect feedback provided in the form of 30 | [`file-annotations`][file-annotations], [`thread-comments`][thread-comments], 31 | workflow [`step-summary`][step-summary], and Pull Request reviews (with 32 | [`tidy-review`][tidy-review] or [`format-review`][format-review]). 33 | 34 | > [!WARNING] 35 | > We only support Linux runners using a Debian-based Linux OS (like Ubuntu and many others). 36 | > 37 | > MacOS and Windows runners are supported as well. 38 | 39 | ## Usage 40 | 41 | > [!NOTE] 42 | > Python 3.10 needs to be installed in the docker image if your workflow is 43 | > [running jobs in a container](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) 44 | > (see discussion in [#185](https://github.com/cpp-linter/cpp-linter-action/issues/185)). 45 | > Our intention is to synchronize with the default Python version included with Ubuntu's latest LTS releases. 46 | 47 | Create a new GitHub Actions workflow in your project, e.g. at [.github/workflows/cpp-linter.yml](https://github.com/cpp-linter/cpp-linter-action/blob/main/.github/workflows/cpp-linter.yml) 48 | 49 | The content of the file should be in the following format. 50 | 51 | ```yaml 52 | steps: 53 | - uses: actions/checkout@v4 54 | - uses: cpp-linter/cpp-linter-action@v2 55 | id: linter 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | with: 59 | style: 'file' # Use .clang-format config file 60 | tidy-checks: '' # Use .clang-tidy config file 61 | # only 'update' a single comment in a pull request thread. 62 | thread-comments: ${{ github.event_name == 'pull_request' && 'update' }} 63 | - name: Fail fast?! 64 | if: steps.linter.outputs.checks-failed > 0 65 | run: exit 1 66 | ``` 67 | 68 | For all explanations of our available input parameters and output variables, see our 69 | [Inputs and Outputs document][io-doc]. 70 | 71 | See also our [example recipes][recipes-doc]. 72 | 73 | ## Used By 74 | 75 |

76 | Microsoft 77 | Microsoft   78 | Apache 79 | Apache   80 | NASA 81 | NASA   82 | Samsung 83 | Samsung   84 | TheAlgorithms 85 | TheAlgorithms   86 | CachyOS 87 | CachyOS   88 |
89 | Nextcloud 90 | Nextcloud   91 | Jupyter 92 | Jupyter   93 | NNStreamer 94 | NNStreamer   95 | imgproxy 96 | imgproxy   97 | Zondax 98 | Zondax   99 | AppNeta 100 | AppNeta   101 |
102 | Chocolate Doom 103 | Chocolate Doom 104 | and many more. 105 |

106 | 107 | ## Example 108 | 109 | ### Annotations 110 | 111 | Using [`file-annotations`][file-annotations]: 112 | 113 | #### clang-format annotations 114 | 115 | ![clang-format annotations][format-annotations-preview] 116 | 117 | #### clang-tidy annotations 118 | 119 | ![clang-tidy annotations][tidy-annotations-preview] 120 | 121 | ### Thread Comment 122 | 123 | Using [`thread-comments`][thread-comments]: 124 | 125 | ![sample thread-comment][thread-comment-preview] 126 | 127 | ### Step Summary 128 | 129 | Using [`step-summary`][step-summary]: 130 | 131 | ![step summary][step-summary-preview] 132 | 133 | ### Pull Request Review 134 | 135 | #### Only clang-tidy 136 | 137 | Using [`tidy-review`][tidy-review]: 138 | 139 | ![sample tidy-review][tidy-review-preview] 140 | 141 | #### Only clang-format 142 | 143 | Using [`format-review`][format-review]: 144 | 145 | ![sample format-review][format-review-preview] 146 | 147 | ![sample format-suggestion][format-suggestion-preview] 148 | 149 | ## Add C/C++ Linter Action badge in README 150 | 151 | You can show C/C++ Linter Action status with a badge in your repository README 152 | 153 | Example 154 | 155 | ```markdown 156 | [![cpp-linter](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml) 157 | ``` 158 | 159 | [![cpp-linter](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml/badge.svg)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml) 160 | 161 | ## Have question or feedback? 162 | 163 | To provide feedback (requesting a feature or reporting a bug) please post to [issues](https://github.com/cpp-linter/cpp-linter-action/issues). 164 | 165 | ## License 166 | 167 | The scripts and documentation in this project are released under the [MIT License](https://github.com/cpp-linter/cpp-linter-action/blob/main/LICENSE) 168 | 169 | 170 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ Linter 2 | description: Linting C/C++ code with clang-tidy or clang-format to give feedback as comments, PR reviews, and more. 3 | author: cpp-linter 4 | branding: 5 | icon: "check-circle" 6 | color: "green" 7 | inputs: 8 | style: 9 | description: | 10 | The style rules to use. 11 | 12 | - Set this to `file` to have clang-format use the closest relative .clang-format file. 13 | - Set this to a blank string (`''`) to disable the use of clang-format entirely. 14 | - Any code style supported by the specified version of clang-format. 15 | required: false 16 | default: "llvm" 17 | extensions: 18 | description: The file extensions to run the action against. This is a comma-separated string. 19 | required: false 20 | default: "c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx" 21 | tidy-checks: 22 | description: | 23 | Comma-separated list of globs with optional `-` prefix. 24 | Globs are processed in order of appearance in the list. 25 | Globs without `-` prefix add checks with matching names to the set, 26 | globs with the `-` prefix remove checks with matching names from the set of enabled checks. 27 | This option's value is appended to the value of the 'Checks' option in a .clang-tidy file (if any). 28 | 29 | - It is possible to disable clang-tidy entirely by setting this option to `'-*'`. 30 | - It is also possible to rely solely on a .clang-tidy config file by specifying this option as a blank string (`''`). 31 | required: false 32 | default: "boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*" 33 | repo-root: 34 | description: > 35 | The relative path to the repository root directory. 36 | This path is relative to the path designated as the runner's `GITHUB_WORKSPACE` environment variable. 37 | required: false 38 | default: '.' 39 | version: 40 | description: | 41 | The desired version of the [clang-tools](https://github.com/cpp-linter/clang-tools-pip) to use. 42 | Accepted options are strings which can be 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, or 8. 43 | 44 | - Set this option to a blank string (`''`) to use the platform's default installed version. 45 | - This value can also be a path to where the clang tools are installed (if using a custom install location). 46 | required: false 47 | default: 16 48 | verbosity: 49 | description: | 50 | This controls the action's verbosity in the workflow's logs. 51 | Supported options are `info` or `debug`. 52 | This option does not affect the verbosity of resulting thread comments or file annotations. 53 | 54 | The verbosity can also be engaged by enabling debug logs when 55 | [re-running jobs or workflows](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs). 56 | required: false 57 | default: info 58 | lines-changed-only: 59 | description: | 60 | This controls what part of the files are analyzed. The following values are accepted: 61 | 62 | - `false`: All lines in a file are analyzed. 63 | - `true`: Only lines in the diff that contain additions are analyzed. 64 | - `diff`: All lines in the diff are analyzed (including unchanged lines but not subtractions). 65 | 66 | !!! info "Important" 67 | This feature requires special permissions to perform successfully. 68 | See our [documented permissions](permissions.md) 69 | required: false 70 | default: false 71 | files-changed-only: 72 | description: | 73 | Set this option to false to analyze any source files in the repo. 74 | This is automatically enabled if [`lines-changed-only`](#lines-changed-only) is enabled. 75 | 76 | !!! info "Important" 77 | This feature requires special permissions to perform successfully. 78 | See our [documented permissions](permissions.md) 79 | required: false 80 | default: true 81 | ignore: 82 | description: | 83 | Set this option with string of path(s) to ignore. 84 | 85 | - In the case of multiple paths, you can use a pipe character (`|`) 86 | to separate the multiple paths. Multiple lines are forbidden as an input to this option; 87 | it must be a single string. 88 | - This can also have files, but the file's relative path has to be specified 89 | as well. 90 | - There is no need to use `./` for each entry; a blank string (`''`) represents 91 | the [`repo-root`](#repo-root) path. 92 | - Submodules are automatically ignored. Hidden directories (beginning with a `.`) are also ignored 93 | automatically. 94 | - Prefix a path with a bang (`!`) to make it explicitly _not_ ignored. The order of 95 | multiple paths does _not_ take precedence. The `!` prefix can be applied to 96 | a submodule's path (if desired) but not hidden directories. 97 | - **As of v2.12**, glob patterns are supported here. 98 | All asterisk characters (`*`) were previously literal. 99 | required: false 100 | default: '.github' 101 | ignore-tidy: 102 | description: |- 103 | Use this option to allow clang-tidy to ignore certain paths/files. 104 | See [`ignore`](#ignore) for more details on possible values. 105 | required: false 106 | default: '.github' 107 | ignore-format: 108 | description: |- 109 | Use this option to allow clang-format to ignore certain paths/files. 110 | See [`ignore`](#ignore) for more details on possible values. 111 | required: false 112 | default: '.github' 113 | thread-comments: 114 | description: | 115 | This controls the behavior of posted thread comments as feedback. The following options are supported: 116 | 117 | - `true`: enable the use of thread comments. This will always delete an outdated thread comment and post a new comment (triggering a notification for every comment). 118 | - `update`: update an existing thread comment if one already exists. This option does not trigger a new notification for every thread comment update. 119 | - `false`: disable the use of thread comments. 120 | 121 | !!! info "Important" 122 | This feature requires special permissions to perform successfully. 123 | See our [documented permissions](permissions.md) 124 | 125 | > [!NOTE] 126 | > If run on a private repository, then this feature is disabled because the GitHub REST API behaves differently for thread comments on a private repository. 127 | required: false 128 | default: 'false' 129 | no-lgtm: 130 | description: | 131 | Set this option to true or false to enable or disable the use of a 132 | thread comment or pull request review that basically says 'Looks Good To Me' (when all checks pass). 133 | The default value, `true` means no LGTM comment posted. 134 | 135 | See [`thread-comments`](#thread-comments), [`tidy-review`](#tidy-review), 136 | and [`format-review`](#format-review) options for further details. 137 | required: false 138 | default: true 139 | step-summary: 140 | description: | 141 | Set this option to true to append content as part of workflow's job summary. 142 | 143 | See implementation details in GitHub's documentation about 144 | [Adding a job summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary). 145 | This option is independent of the [`thread-comments`](#thread-comments) option, 146 | rather this option uses the same content that the 147 | [`thread-comments`](#thread-comments) option would use. 148 | 149 | > [!NOTE] 150 | > The [`no-lgtm`](#no-lgtm) option is _not_ applied to step summaries. 151 | required: false 152 | default: false 153 | file-annotations: 154 | description: | 155 | Set this option to false to disable the use of file annotations as feedback. 156 | required: false 157 | default: true 158 | database: 159 | description: The directory containing compilation database (like compile_commands.json) file. 160 | required: false 161 | default: "" 162 | extra-args: 163 | description: | 164 | A string of extra arguments passed to clang-tidy for use as compiler arguments. 165 | Multiple arguments are separated by spaces so the argument name and value should 166 | use an `=` sign instead of a space. 167 | 168 | !!! example 169 | 170 | ``` yaml 171 | extra-args: '-std=c++17 -Wall' 172 | ``` 173 | This will be passed to clang-tidy as multiple `--extra-arg` options: 174 | ``` 175 | clang-tidy --extra-arg=-std=c++17 --extra-arg=-Wall 176 | ``` 177 | required: false 178 | default: "" 179 | tidy-review: 180 | description: | 181 | Set this option to `true` to enable Pull Request reviews from clang-tidy. 182 | 183 | !!! info "Important" 184 | This feature requires special permissions to perform successfully. 185 | See our [documented permissions](permissions.md). 186 | 187 | See also [the PR review feature caveats](pr-review-caveats.md). 188 | 189 | > [!NOTE] 190 | > The [`no-lgtm`](#no-lgtm) option is applicable to Pull Request reviews. 191 | required: false 192 | default: false 193 | format-review: 194 | description: | 195 | Set this option to `true` to enable Pull Request reviews from clang-format. 196 | 197 | !!! info "Important" 198 | This feature requires special permissions to perform successfully. 199 | See our [documented permissions](permissions.md). 200 | 201 | See also [the PR review feature caveats](pr-review-caveats.md). 202 | 203 | > [!NOTE] 204 | > The [`no-lgtm`](#no-lgtm) option is applicable to Pull Request reviews. 205 | required: false 206 | default: false 207 | passive-reviews: 208 | description: | 209 | Set this option to `true` to prevent Pull Request reviews from approving or requesting changes. 210 | default: false 211 | required: false 212 | jobs: 213 | description: | 214 | The number of jobs to run in parallel. 215 | If less than or equal to 0, the number of jobs is set to 216 | use the number of all available CPU cores. 217 | required: false 218 | default: 0 219 | outputs: 220 | checks-failed: 221 | description: An integer that can be used as a boolean value to indicate if any checks failed by clang-tidy and clang-format. 222 | value: ${{ steps.cpp-linter-unix.outputs.checks-failed || steps.cpp-linter-windows.outputs.checks-failed }} 223 | clang-tidy-checks-failed: 224 | description: An integer that can be used as a boolean value to indicate if any checks failed by clang-tidy only. 225 | value: ${{ steps.cpp-linter-unix.outputs.clang-tidy-checks-failed || steps.cpp-linter-windows.outputs.clang-tidy-checks-failed }} 226 | clang-format-checks-failed: 227 | description: An integer that can be used as a boolean value to indicate if any checks failed by clang-format only. 228 | value: ${{ steps.cpp-linter-unix.outputs.clang-format-checks-failed || steps.cpp-linter-windows.outputs.clang-format-checks-failed }} 229 | runs: 230 | using: "composite" 231 | steps: 232 | - name: Install python 233 | uses: actions/setup-python@v5 234 | id: setup-python 235 | with: 236 | # use python version shipped with latest Ubuntu LTS 237 | python-version: '3.10' 238 | update-environment: false 239 | 240 | - name: Install Linux clang dependencies 241 | if: runner.os == 'Linux' 242 | shell: bash 243 | run: | 244 | sudo apt-get update 245 | # First try installing from default Ubuntu repositories before trying LLVM script 246 | if ! sudo apt-get install -y clang-format-${{ inputs.version }} clang-tidy-${{ inputs.version }}; then 247 | # This LLVM script will add the relevant LLVM PPA: https://apt.llvm.org/ 248 | wget https://apt.llvm.org/llvm.sh -O $GITHUB_ACTION_PATH/llvm_install.sh 249 | chmod +x $GITHUB_ACTION_PATH/llvm_install.sh 250 | if sudo $GITHUB_ACTION_PATH/llvm_install.sh ${{ inputs.version }}; then 251 | sudo apt-get install -y clang-format-${{ inputs.version }} clang-tidy-${{ inputs.version }} 252 | fi 253 | fi 254 | 255 | - name: Install MacOS clang dependencies 256 | if: runner.os == 'macOS' 257 | shell: bash 258 | continue-on-error: true 259 | run: | 260 | brew install llvm@${{ inputs.version }} 261 | ln -s "$(brew --prefix llvm@${{ inputs.version }})/bin/clang-format" "/usr/local/bin/clang-format-${{ inputs.version }}" 262 | ln -s "$(brew --prefix llvm@${{ inputs.version }})/bin/clang-tidy" "/usr/local/bin/clang-tidy-${{ inputs.version }}" 263 | 264 | - name: Setup python venv (Unix) 265 | if: runner.os == 'Linux' || runner.os == 'macOS' 266 | shell: bash 267 | run: | 268 | ${{ steps.setup-python.outputs.python-path }} -m venv "$GITHUB_ACTION_PATH/venv" 269 | source "$GITHUB_ACTION_PATH/venv/bin/activate" 270 | pip install -r "$GITHUB_ACTION_PATH/requirements.txt" 271 | clang-tools -i ${{ inputs.version }} -b 272 | 273 | - name: Run cpp-linter (Unix) 274 | id: cpp-linter-unix 275 | if: runner.os == 'Linux' || runner.os == 'macOS' 276 | shell: bash 277 | run: | 278 | source "$GITHUB_ACTION_PATH/venv/bin/activate" 279 | 280 | cpp-linter \ 281 | --style="${{ inputs.style }}" \ 282 | --extensions=${{ inputs.extensions }} \ 283 | --tidy-checks="${{ inputs.tidy-checks }}" \ 284 | --repo-root=${{ inputs.repo-root }} \ 285 | --version=${{ inputs.version }} \ 286 | --verbosity=${{ inputs.verbosity }} \ 287 | --lines-changed-only=${{ inputs.lines-changed-only }} \ 288 | --files-changed-only=${{ inputs.files-changed-only }} \ 289 | --thread-comments=${{ inputs.thread-comments }} \ 290 | --no-lgtm=${{ inputs.no-lgtm }} \ 291 | --step-summary=${{ inputs.step-summary }} \ 292 | --ignore="${{ inputs.ignore }}" \ 293 | --ignore-tidy="${{ inputs.ignore-tidy }}" \ 294 | --ignore-format="${{ inputs.ignore-format }}" \ 295 | --database=${{ inputs.database }} \ 296 | --file-annotations=${{ inputs.file-annotations }} \ 297 | --extra-arg="${{ inputs.extra-args }}" \ 298 | --tidy-review="${{ inputs.tidy-review }}" \ 299 | --format-review="${{ inputs.format-review }}" \ 300 | --passive-reviews="${{ inputs.passive-reviews }}" \ 301 | --jobs=${{ inputs.jobs }} 302 | 303 | - name: Setup python venv (Windows) 304 | if: runner.os == 'Windows' 305 | shell: pwsh 306 | run: | 307 | ${{ steps.setup-python.outputs.python-path }} -m venv "$env:GITHUB_ACTION_PATH/venv" 308 | Invoke-Expression -Command "$env:GITHUB_ACTION_PATH/venv/Scripts/Activate.ps1" 309 | pip install -r "$env:GITHUB_ACTION_PATH/requirements.txt" 310 | clang-tools -i ${{ inputs.version }} -b 311 | 312 | - name: Run cpp-linter (Windows) 313 | id: cpp-linter-windows 314 | if: runner.os == 'Windows' 315 | shell: pwsh 316 | run: | 317 | Invoke-Expression -Command "$env:GITHUB_ACTION_PATH/venv/Scripts/Activate.ps1" 318 | 319 | $app = 'cpp-linter' + 320 | ' --style="${{ inputs.style }}"' + 321 | ' --extensions=${{ inputs.extensions }}' + 322 | ' --tidy-checks="${{ inputs.tidy-checks }}"' + 323 | ' --repo-root=${{ inputs.repo-root }}' + 324 | ' --version=${{ inputs.version }}' + 325 | ' --verbosity=${{ inputs.verbosity }}' + 326 | ' --lines-changed-only=${{ inputs.lines-changed-only }}' + 327 | ' --files-changed-only=${{ inputs.files-changed-only }}' + 328 | ' --thread-comments=${{ inputs.thread-comments }}' + 329 | ' --no-lgtm=${{ inputs.no-lgtm }}' + 330 | ' --step-summary=${{ inputs.step-summary }}' + 331 | ' --ignore="${{ inputs.ignore }}"' + 332 | ' --ignore-tidy="${{ inputs.ignore-tidy }}"' + 333 | ' --ignore-format="${{ inputs.ignore-format }}"' + 334 | ' --database=${{ inputs.database }}' + 335 | ' --file-annotations=${{ inputs.file-annotations }}' + 336 | ' --extra-arg="${{ inputs.extra-args }}"' + 337 | ' --tidy-review="${{ inputs.tidy-review }}"' + 338 | ' --format-review="${{ inputs.format-review }}"' + 339 | ' --passive-reviews="${{ inputs.passive-reviews }}"' + 340 | ' --jobs=${{ inputs.jobs }}' 341 | 342 | Invoke-Expression -Command $app 343 | -------------------------------------------------------------------------------- /docs/README.rst: -------------------------------------------------------------------------------- 1 | How to build the docs 2 | ===================== 3 | 4 | From the root directory of the repository, do the following to steps 5 | 6 | 1. Install docs' dependencies 7 | 8 | .. code-block:: text 9 | 10 | pip install -r docs/requirements.txt 11 | 12 | On Linux, you may need to use `pip3` instead. 13 | 14 | 2. Build the docs 15 | 16 | .. code-block:: text 17 | 18 | mkdocs build 19 | 20 | or use the following command to see changes rendered in realtime. 21 | 22 | .. code-block:: text 23 | 24 | mkdocs serve 25 | -------------------------------------------------------------------------------- /docs/action.yml: -------------------------------------------------------------------------------- 1 | # file to hold metadata about the action.yml inputs and outputs 2 | inputs: 3 | style: 4 | minimum-version: '1.2.0' 5 | extensions: 6 | minimum-version: '1.2.0' 7 | tidy-checks: 8 | minimum-version: '1.2.0' 9 | repo-root: 10 | minimum-version: '1.2.0' 11 | version: 12 | minimum-version: '1.2.0' 13 | verbosity: 14 | minimum-version: '1.3.0' 15 | lines-changed-only: 16 | minimum-version: '1.5.0' 17 | required-permission: 'contents: read #file-changes' 18 | files-changed-only: 19 | minimum-version: '1.3.0' 20 | required-permission: 'contents: read #file-changes' 21 | ignore: 22 | minimum-version: '1.3.0' 23 | ignore-tidy: 24 | minimum-version: '2.12.0' 25 | ignore-format: 26 | minimum-version: '2.12.0' 27 | thread-comments: 28 | minimum-version: '2.6.2' 29 | required-permission: 'contents: write #thread-comments' 30 | no-lgtm: 31 | minimum-version: '2.6.2' 32 | step-summary: 33 | minimum-version: '2.6.0' 34 | file-annotations: 35 | minimum-version: '1.4.3' 36 | database: 37 | minimum-version: '1.4.0' 38 | extra-args: 39 | minimum-version: '2.1.0' 40 | tidy-review: 41 | experimental: true 42 | minimum-version: '2.9.0' 43 | required-permission: 'pull-requests: write #pull-request-reviews' 44 | format-review: 45 | minimum-version: '2.9.0' 46 | required-permission: 'pull-requests: write #pull-request-reviews' 47 | passive-reviews: 48 | minimum-version: '2.12.0' 49 | required-permission: 'pull-requests: write #pull-request-reviews' 50 | jobs: 51 | minimum-version: '2.11.0' 52 | outputs: 53 | checks-failed: 54 | minimum-version: '1.2.0' 55 | clang-tidy-checks-failed: 56 | minimum-version: '2.7.2' 57 | clang-format-checks-failed: 58 | minimum-version: '2.7.2' 59 | -------------------------------------------------------------------------------- /docs/badge_hook.py: -------------------------------------------------------------------------------- 1 | """A mkdocs hook that injects an HTML syntax used to generate badges at build time.""" 2 | 3 | import re 4 | from re import Match 5 | from mkdocs.config.defaults import MkDocsConfig 6 | from mkdocs.structure.files import Files 7 | from mkdocs.structure.pages import Page 8 | 9 | 10 | def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files): 11 | # Replace callback 12 | def replace(match: Match): 13 | badge_type, args = match.groups() 14 | args = args.strip() 15 | if badge_type == "version": 16 | return _badge_for_version(args, page, files) 17 | elif badge_type == "flag": 18 | return _badge_for_flags(args, page, files) 19 | elif badge_type == "permission": 20 | return _badge_for_permissions(args, page, files) 21 | elif badge_type == "default": 22 | return _badge_for_default(args, page, files) 23 | 24 | # Otherwise, raise an error 25 | raise RuntimeError(f"Unknown badge type: {badge_type}") 26 | 27 | # Find and replace all external asset URLs in current page 28 | return re.sub(r"", replace, markdown, flags=re.I | re.M) 29 | 30 | 31 | # ----------------------------------------------------------------------------- 32 | # Helper functions 33 | 34 | 35 | def _badge_for_flags(arg, page: Page, files: Files): 36 | if arg == "experimental": 37 | return _badge_for_experimental(page, files) 38 | raise ValueError(f"Unsupported badge flag: {arg}") 39 | 40 | 41 | # Create badge 42 | def _badge(icon: str, text: str = ""): 43 | return "".join( 44 | [ 45 | '', 46 | *([f'{icon}'] if icon else []), 47 | *([f'{text}'] if text else []), 48 | "", 49 | ] 50 | ) 51 | 52 | 53 | # Create badge for version 54 | def _badge_for_version(text: str, page: Page, files: Files): 55 | icon = "material-tag-outline" 56 | href = "https://github.com/cpp-linter/cpp-linter-action/releases/" + ( 57 | f"v{text}" if text[0:1].isdigit() else text 58 | ) 59 | return _badge( 60 | icon=f'[:{icon}:]({href} "minimum version")', 61 | text=f'[{text}]({href} "minimum version")', 62 | ) 63 | 64 | 65 | # Create badge for default value 66 | def _badge_for_default(text: str, page: Page, files: Files): 67 | return _badge(icon="Default", text=f"`#!yaml {text}`") 68 | 69 | 70 | # Create badge for required value flag 71 | def _badge_for_permissions(args: str, page: Page, files: Files): 72 | match_permission = re.match(r"([^#]+)(.*)", args) 73 | if match_permission is None: 74 | raise ValueError(f"failed to parse permissions from {args}") 75 | permission, link = match_permission.groups()[:2] 76 | permission = permission.strip() 77 | link = "permissions.md" + link 78 | icon = "material-lock" 79 | return _badge( 80 | icon=f'[:{icon}:]({link} "required permissions")', 81 | text=f'[`#!yaml {permission}`]({link} "required permission")', 82 | ) 83 | 84 | 85 | # Create badge for experimental flag 86 | def _badge_for_experimental(page: Page, files: Files): 87 | icon = "material-flask-outline" 88 | return _badge(icon=f":{icon}:{{ .mdx-badge--heart }}", text="experimental") 89 | -------------------------------------------------------------------------------- /docs/contributing-guidelines.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - toc 4 | --- 5 | 6 | {% 7 | include-markdown "../CONTRIBUTING.md" 8 | %} 9 | -------------------------------------------------------------------------------- /docs/examples/demo/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: WebKit 4 | -------------------------------------------------------------------------------- /docs/examples/demo/.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,performance-*,bugprone-*,clang-analyzer-*,mpi-*,misc-*,readability-*' 3 | WarningsAsErrors: '' 4 | HeaderFilterRegex: '' 5 | AnalyzeTemporaryDtors: false 6 | FormatStyle: 'file' 7 | CheckOptions: 8 | - key: bugprone-argument-comment.CommentBoolLiterals 9 | value: '0' 10 | - key: bugprone-argument-comment.CommentCharacterLiterals 11 | value: '0' 12 | - key: bugprone-argument-comment.CommentFloatLiterals 13 | value: '0' 14 | - key: bugprone-argument-comment.CommentIntegerLiterals 15 | value: '0' 16 | - key: bugprone-argument-comment.CommentNullPtrs 17 | value: '0' 18 | - key: bugprone-argument-comment.CommentStringLiterals 19 | value: '0' 20 | - key: bugprone-argument-comment.CommentUserDefinedLiterals 21 | value: '0' 22 | - key: bugprone-argument-comment.IgnoreSingleArgument 23 | value: '0' 24 | - key: bugprone-argument-comment.StrictMode 25 | value: '0' 26 | - key: bugprone-assert-side-effect.AssertMacros 27 | value: assert 28 | - key: bugprone-assert-side-effect.CheckFunctionCalls 29 | value: '0' 30 | - key: bugprone-dangling-handle.HandleClasses 31 | value: 'std::basic_string_view;std::experimental::basic_string_view' 32 | - key: bugprone-dynamic-static-initializers.HeaderFileExtensions 33 | value: ',h,hh,hpp,hxx' 34 | - key: bugprone-exception-escape.FunctionsThatShouldNotThrow 35 | value: '' 36 | - key: bugprone-exception-escape.IgnoredExceptions 37 | value: '' 38 | - key: bugprone-misplaced-widening-cast.CheckImplicitCasts 39 | value: '0' 40 | - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions 41 | value: '1' 42 | - key: bugprone-signed-char-misuse.CharTypdefsToIgnore 43 | value: '' 44 | - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant 45 | value: '1' 46 | - key: bugprone-sizeof-expression.WarnOnSizeOfConstant 47 | value: '1' 48 | - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression 49 | value: '0' 50 | - key: bugprone-sizeof-expression.WarnOnSizeOfThis 51 | value: '1' 52 | - key: bugprone-string-constructor.LargeLengthThreshold 53 | value: '8388608' 54 | - key: bugprone-string-constructor.WarnOnLargeLength 55 | value: '1' 56 | - key: bugprone-suspicious-enum-usage.StrictMode 57 | value: '0' 58 | - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens 59 | value: '5' 60 | - key: bugprone-suspicious-missing-comma.RatioThreshold 61 | value: '0.200000' 62 | - key: bugprone-suspicious-missing-comma.SizeThreshold 63 | value: '5' 64 | - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions 65 | value: '' 66 | - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison 67 | value: '1' 68 | - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison 69 | value: '0' 70 | - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit 71 | value: '16' 72 | - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField 73 | value: '1' 74 | - key: bugprone-unused-return-value.CheckedFunctions 75 | value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty' 76 | - key: cert-dcl16-c.NewSuffixes 77 | value: 'L;LL;LU;LLU' 78 | - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField 79 | value: '0' 80 | - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors 81 | value: '1' 82 | - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic 83 | value: '1' 84 | - key: google-readability-braces-around-statements.ShortStatementLines 85 | value: '1' 86 | - key: google-readability-function-size.StatementThreshold 87 | value: '800' 88 | - key: google-readability-namespace-comments.ShortNamespaceLines 89 | value: '10' 90 | - key: google-readability-namespace-comments.SpacesBeforeComments 91 | value: '2' 92 | - key: misc-definitions-in-headers.HeaderFileExtensions 93 | value: ',h,hh,hpp,hxx' 94 | - key: misc-definitions-in-headers.UseHeaderFileExtension 95 | value: '1' 96 | - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries 97 | value: '1' 98 | - key: misc-unused-parameters.StrictMode 99 | value: '0' 100 | - key: modernize-loop-convert.MaxCopySize 101 | value: '16' 102 | - key: modernize-loop-convert.MinConfidence 103 | value: reasonable 104 | - key: modernize-loop-convert.NamingStyle 105 | value: CamelCase 106 | - key: modernize-pass-by-value.IncludeStyle 107 | value: llvm 108 | - key: modernize-replace-auto-ptr.IncludeStyle 109 | value: llvm 110 | - key: modernize-use-nullptr.NullMacros 111 | value: 'NULL' 112 | - key: performance-faster-string-find.StringLikeClasses 113 | value: 'std::basic_string' 114 | - key: performance-for-range-copy.AllowedTypes 115 | value: '' 116 | - key: performance-for-range-copy.WarnOnAllAutoCopies 117 | value: '0' 118 | - key: performance-inefficient-string-concatenation.StrictMode 119 | value: '0' 120 | - key: performance-inefficient-vector-operation.EnableProto 121 | value: '0' 122 | - key: performance-inefficient-vector-operation.VectorLikeClasses 123 | value: '::std::vector' 124 | - key: performance-move-const-arg.CheckTriviallyCopyableMove 125 | value: '1' 126 | - key: performance-move-constructor-init.IncludeStyle 127 | value: llvm 128 | - key: performance-no-automatic-move.AllowedTypes 129 | value: '' 130 | - key: performance-type-promotion-in-math-fn.IncludeStyle 131 | value: llvm 132 | - key: performance-unnecessary-copy-initialization.AllowedTypes 133 | value: '' 134 | - key: performance-unnecessary-value-param.AllowedTypes 135 | value: '' 136 | - key: performance-unnecessary-value-param.IncludeStyle 137 | value: llvm 138 | - key: readability-braces-around-statements.ShortStatementLines 139 | value: '0' 140 | - key: readability-else-after-return.WarnOnUnfixable 141 | value: '1' 142 | - key: readability-function-size.BranchThreshold 143 | value: '4294967295' 144 | - key: readability-function-size.LineThreshold 145 | value: '4294967295' 146 | - key: readability-function-size.NestingThreshold 147 | value: '4294967295' 148 | - key: readability-function-size.ParameterThreshold 149 | value: '4294967295' 150 | - key: readability-function-size.StatementThreshold 151 | value: '800' 152 | - key: readability-function-size.VariableThreshold 153 | value: '4294967295' 154 | - key: readability-identifier-naming.IgnoreFailedSplit 155 | value: '0' 156 | - key: readability-implicit-bool-conversion.AllowIntegerConditions 157 | value: '0' 158 | - key: readability-implicit-bool-conversion.AllowPointerConditions 159 | value: '0' 160 | - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros 161 | value: '1' 162 | - key: readability-inconsistent-declaration-parameter-name.Strict 163 | value: '0' 164 | - key: readability-magic-numbers.IgnoredFloatingPointValues 165 | value: '1.0;100.0;' 166 | - key: readability-magic-numbers.IgnoredIntegerValues 167 | value: '1;2;3;4;' 168 | - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors 169 | value: '0' 170 | - key: readability-redundant-smartptr-get.IgnoreMacros 171 | value: '1' 172 | - key: readability-redundant-string-init.StringNames 173 | value: '::std::basic_string' 174 | - key: readability-simplify-boolean-expr.ChainedConditionalAssignment 175 | value: '0' 176 | - key: readability-simplify-boolean-expr.ChainedConditionalReturn 177 | value: '0' 178 | - key: readability-simplify-subscript-expr.Types 179 | value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' 180 | - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold 181 | value: '3' 182 | - key: readability-uppercase-literal-suffix.IgnoreMacros 183 | value: '1' 184 | - key: readability-uppercase-literal-suffix.NewSuffixes 185 | value: '' 186 | ... 187 | -------------------------------------------------------------------------------- /docs/examples/demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # Set the project name to your project name 4 | project(demo C CXX) 5 | 6 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 7 | 8 | add_executable(demo_app 9 | ${CMAKE_BINARY_SOURCE_DIR}demo.hpp 10 | ${CMAKE_BINARY_SOURCE_DIR}demo.cpp 11 | ) 12 | target_include_directories(demo_app PUBLIC ${CMAKE_BINARY_SOURCE_DIR}) 13 | -------------------------------------------------------------------------------- /docs/examples/demo/compile_flags.txt: -------------------------------------------------------------------------------- 1 | -Wall 2 | -Werror 3 | -------------------------------------------------------------------------------- /docs/examples/demo/demo.cpp: -------------------------------------------------------------------------------- 1 | /** This is a very ugly test code (doomed to fail linting) */ 2 | #include "demo.hpp" 3 | #include 4 | 5 | 6 | 7 | 8 | int main(){ 9 | 10 | for (;;) break; 11 | 12 | 13 | printf("Hello world!\n"); 14 | 15 | 16 | 17 | 18 | return 0;} 19 | -------------------------------------------------------------------------------- /docs/examples/demo/demo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | 5 | class Dummy { 6 | char* useless; 7 | int numb; 8 | Dummy() :numb(0), useless("\0"){} 9 | 10 | public: 11 | void *not_useful(char *str){useless = str;} 12 | }; 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | struct LongDiff 32 | { 33 | 34 | long diff; 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /docs/examples/index.md: -------------------------------------------------------------------------------- 1 | 2 | [style]: ../inputs-outputs.md#style 3 | [tidy-checks]: ../inputs-outputs.md#tidy-checks 4 | [thread-comments]: ../inputs-outputs.md#thread-comments 5 | 6 | # Recipes 7 | 8 | Here are some example workflows to get started quickly. 9 | 10 | === "only clang-tidy" 11 | 12 | ``` yaml 13 | --8<-- "docs/examples/only-clang-tidy.yml" 14 | ``` 15 | 16 | 1. See also [`style`][style] 17 | 2. See also [`tidy-checks`][tidy-checks] 18 | 19 | === "only clang-format" 20 | 21 | ``` yaml 22 | --8<-- "docs/examples/only-clang-format.yml" 23 | ``` 24 | 25 | 1. See also [`style`][style] 26 | 2. See also [`tidy-checks`][tidy-checks] 27 | 28 | === "only PR comments" 29 | 30 | ``` yaml 31 | --8<-- "docs/examples/only-PR-comments.yml" 32 | ``` 33 | 34 | 1. See also our [token permissions document](../permissions.md) 35 | 2. See also [`style`][style] 36 | 3. See also [`tidy-checks`][tidy-checks] 37 | 4. See also [`thread-comments`][thread-comments] 38 | -------------------------------------------------------------------------------- /docs/examples/only-PR-comments.yml: -------------------------------------------------------------------------------- 1 | name: cpp-linter 2 | on: 3 | pull_request: 4 | branches: [main, master, develop] 5 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 6 | push: 7 | branches: [main, master, develop] 8 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 9 | 10 | jobs: 11 | cpp-linter: 12 | runs-on: ubuntu-latest 13 | permissions: # (1)! 14 | pull-requests: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | # ... optionally setup build env to create a compilation database 19 | 20 | - uses: cpp-linter/cpp-linter-action@v2 21 | id: linter 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | with: 25 | style: 'file' # Use .clang-format config file. (2) 26 | tidy-checks: '' # Use .clang-tidy config file. (3) 27 | # only 'update' a single comment in a pull request's thread. (4) 28 | thread-comments: ${{ github.event_name == 'pull_request' && 'update' }} 29 | 30 | - name: Fail fast?! 31 | if: steps.linter.outputs.checks-failed > 0 32 | run: exit 1 33 | -------------------------------------------------------------------------------- /docs/examples/only-clang-format.yml: -------------------------------------------------------------------------------- 1 | name: cpp-linter 2 | on: 3 | pull_request: 4 | branches: [main, master, develop] 5 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 6 | push: 7 | branches: [main, master, develop] 8 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 9 | 10 | jobs: 11 | cpp-linter: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | # ... optionally setup build env to create a compilation database 17 | 18 | - uses: cpp-linter/cpp-linter-action@v2 19 | id: linter 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | style: 'file' # Use .clang-format config file. (1) 24 | tidy-checks: '-*' # disable clang-tidy checks. (2) 25 | 26 | - name: Fail fast?! 27 | if: steps.linter.outputs.clang-format-checks-failed > 0 28 | run: exit 1 29 | -------------------------------------------------------------------------------- /docs/examples/only-clang-tidy.yml: -------------------------------------------------------------------------------- 1 | name: cpp-linter 2 | on: 3 | pull_request: 4 | branches: [main, master, develop] 5 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 6 | push: 7 | branches: [main, master, develop] 8 | paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] 9 | 10 | jobs: 11 | cpp-linter: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | # ... optionally setup build env to create a compilation database 17 | 18 | - uses: cpp-linter/cpp-linter-action@v2 19 | id: linter 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | style: '' # disable clang-format checks. (1) 24 | tidy-checks: '' # Use .clang-tidy config file. (2) 25 | 26 | - name: Fail fast?! 27 | if: steps.linter.outputs.clang-tidy-checks-failed > 0 28 | run: exit 1 29 | -------------------------------------------------------------------------------- /docs/gen_io_doc.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import Union, Dict, Any 3 | import yaml 4 | import mkdocs_gen_files 5 | 6 | FILENAME = "inputs-outputs.md" 7 | 8 | with mkdocs_gen_files.open(FILENAME, "w") as io_doc: 9 | action_yml = Path(__file__).parent.parent / "action.yml" 10 | action_doc = Path(__file__).parent / "action.yml" 11 | a_dict: Dict[str, Any] = yaml.safe_load(action_yml.read_bytes()) 12 | b_dict: Dict[str, Dict[str, Any]] = yaml.safe_load(action_doc.read_bytes()) 13 | 14 | # extract info we need from a_dict and merge into b_dict 15 | for info_key in b_dict: 16 | assert info_key in a_dict and isinstance(a_dict[info_key], dict) 17 | for k, v in a_dict[info_key].items(): 18 | if k not in b_dict[info_key]: 19 | print( 20 | "::error file=docs/action.yml,title={title}::{message}".format( 21 | title=f"Undocumented {info_key} field `{k}` in actions.yml", 22 | message=( 23 | f"Field '{k}' not found in docs/action.yml mapping:" 24 | ), 25 | ), 26 | info_key 27 | ) 28 | continue 29 | b_dict[info_key][k].update(v) 30 | 31 | doc = "".join( 32 | [ 33 | "---\ntitle: Inputs and Outputs\n---\n\n" "\n\n", 37 | "# Inputs and Outputs\n\n", 38 | "These are the action inputs and outputs offered by cpp-linter-action.\n", 39 | ] 40 | ) 41 | assert "inputs" in b_dict 42 | doc += "\n## Inputs\n" 43 | for action_input, input_metadata in b_dict["inputs"].items(): 44 | doc += f"### `{action_input}`\n\n" 45 | 46 | if "minimum-version" not in input_metadata: 47 | print( 48 | "\n::warning file={name}title={title}::{message}".format( 49 | name="docs/action.yml", 50 | title="Input's minimum-version not found", 51 | message="minimum-version not set for input:", 52 | ), 53 | action_input, 54 | ) 55 | else: 56 | min_ver = input_metadata["minimum-version"] 57 | doc += f"\n" 58 | 59 | assert ( 60 | "default" in input_metadata 61 | ), f"default value for `{action_input}` not set in action.yml" 62 | default: Union[str, bool] = input_metadata["default"] 63 | if isinstance(default, bool): 64 | default = str(default).lower() 65 | elif isinstance(default, str): 66 | default = repr(default) # add quotes around value 67 | doc += f"\n" 68 | 69 | if "experimental" in input_metadata and input_metadata["experimental"] is True: 70 | doc += "\n" 71 | 72 | if "required-permission" in input_metadata: 73 | permission = input_metadata["required-permission"] 74 | doc += f"\n" 75 | 76 | assert ( 77 | "description" in input_metadata 78 | ), f"`{action_input}` description not found in action.yml" 79 | doc += "\n" + input_metadata["description"] + "\n" 80 | 81 | assert "outputs" in b_dict 82 | doc += ( 83 | "\n## Outputs\n\nThis action creates 3 output variables. Even if the linting " 84 | "checks fail for source files this action will still pass, but users' CI " 85 | "workflows can use this action's outputs to exit the workflow early if that is " 86 | "desired.\n" 87 | ) 88 | for action_output, output_metadata in b_dict["outputs"].items(): 89 | doc += f"\n### `{action_output}`\n\n" 90 | 91 | if "minimum-version" not in output_metadata: 92 | print( 93 | "\n::warning file={name}title={title}::{message}".format( 94 | name="docs/action.yml", 95 | title="Output's minimum-version not found", 96 | message="minimum-version not set for output:", 97 | ), 98 | action_output, 99 | ) 100 | else: 101 | min_ver = output_metadata["minimum-version"] 102 | doc += f"\n" 103 | 104 | assert ( 105 | "description" in output_metadata 106 | ), f"`{action_output}` description not found in action.yml" 107 | doc += "\n" + output_metadata["description"] + "\n" 108 | 109 | print(doc, file=io_doc) 110 | 111 | mkdocs_gen_files.set_edit_path(FILENAME, "gen_io_doc.py") 112 | -------------------------------------------------------------------------------- /docs/images/annotations-clang-format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/annotations-clang-format.png -------------------------------------------------------------------------------- /docs/images/annotations-clang-tidy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/annotations-clang-tidy.png -------------------------------------------------------------------------------- /docs/images/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/comment.png -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/format-review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/format-review.png -------------------------------------------------------------------------------- /docs/images/format-suggestion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/format-suggestion.png -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/step-summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/step-summary.png -------------------------------------------------------------------------------- /docs/images/tidy-review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/530737f357d479227961c26554c59a4167c552a4/docs/images/tidy-review.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | [file-annotations]: inputs-outputs.md#file-annotations 2 | [thread-comments]: inputs-outputs.md#thread-comments 3 | [step-summary]: inputs-outputs.md#step-summary 4 | [tidy-review]: inputs-outputs.md#tidy-review 5 | [format-review]: inputs-outputs.md#format-review 6 | 7 | [io-doc]: inputs-outputs.md 8 | [recipes-doc]: examples/index.md 9 | 10 | [format-annotations-preview]: images/annotations-clang-format.png 11 | [tidy-annotations-preview]: images/annotations-clang-tidy.png 12 | [thread-comment-preview]: images/comment.png 13 | [step-summary-preview]: images/step-summary.png 14 | [tidy-review-preview]: images/tidy-review.png 15 | [format-review-preview]: images/format-review.png 16 | [format-suggestion-preview]: images/format-suggestion.png 17 | 18 | {% 19 | include-markdown "../README.md" 20 | start="" 21 | end="" 22 | %} 23 | -------------------------------------------------------------------------------- /docs/permissions.md: -------------------------------------------------------------------------------- 1 | # Token Permissions 2 | 3 | This is an exhaustive list of required permissions organized by features. 4 | 5 | !!! info "Important" 6 | The `GITHUB_TOKEN` environment variable should be supplied when running on a private repository. 7 | Otherwise the runner does not not have the privileges needed for the features mentioned here. 8 | 9 | See also [Authenticating with the `GITHUB_TOKEN`](https://docs.github.com/en/actions/reference/authentication-in-a-workflow) 10 | 11 | ## File Changes 12 | 13 | When using [`files-changed-only`](inputs-outputs.md#files-changed-only) or 14 | [`lines-changed-only`](inputs-outputs.md#lines-changed-only) to get the list 15 | of file changes for a CI event, the following permissions are needed: 16 | 17 | === "`#!yaml on: push`" 18 | 19 | For [push events](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) 20 | 21 | ```yaml 22 | permissions: 23 | contents: read # (1)! 24 | ``` 25 | 26 | 1. This permission is also needed to download files if the repository is not 27 | checked out before running cpp-linter. 28 | 29 | === "`#!yaml on: pull_request`" 30 | 31 | For [pull_request events](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request) 32 | 33 | ```yaml 34 | permissions: 35 | contents: read # (1)! 36 | pull-requests: read # (2)! 37 | ``` 38 | 39 | 1. For pull requests, this permission is only needed to download files if 40 | the repository is not checked out before running cpp-linter. 41 | 2. Specifying `#!yaml write` is also sufficient as that is required for 42 | 43 | * posting [thread comments](#thread-comments) on pull requests 44 | * posting [pull request reviews](#pull-request-reviews) 45 | 46 | ## Thread Comments 47 | 48 | The [`thread-comments`](inputs-outputs.md#thread-comments) feature requires the following permissions: 49 | 50 | === "`#!yaml on: push`" 51 | 52 | For [push events](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) 53 | 54 | ```yaml 55 | permissions: 56 | metadata: read # (1)! 57 | contents: write # (2)! 58 | ``` 59 | 60 | 1. needed to fetch existing comments 61 | 2. needed to post or update a commit comment. This also allows us to delete 62 | an outdated comment if needed. 63 | 64 | === "`#!yaml on: pull_request`" 65 | 66 | For [pull_request events](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request) 67 | 68 | ```yaml 69 | permissions: 70 | pull-requests: write 71 | ``` 72 | 73 | ## Pull Request Reviews 74 | 75 | The [`tidy-review`](inputs-outputs.md#tidy-review), [`format-review`](inputs-outputs.md#format-review), and [`passive-reviews`](inputs-outputs.md#passive-reviews) features require the following permissions: 76 | 77 | ```yaml 78 | permissions: 79 | pull-requests: write 80 | ``` 81 | -------------------------------------------------------------------------------- /docs/pr-review-caveats.md: -------------------------------------------------------------------------------- 1 | # Pull Request Review Caveats 2 | 3 | [repository settings]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#preventing-github-actions-from-creating-or-approving-pull-requests 4 | [organization settings]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#preventing-github-actions-from-creating-or-approving-pull-requests 5 | [hiding a comment]: https://docs.github.com/en/communities/moderating-comments-and-conversations/managing-disruptive-comments#hiding-a-comment 6 | [resolve a conversion]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request#resolving-conversations 7 | 8 | [tidy-review]: inputs-outputs.md#tidy-review 9 | [format-review]: inputs-outputs.md#format-review 10 | [lines-changed-only]: inputs-outputs.md#lines-changed-only 11 | [style]: inputs-outputs.md#style 12 | 13 | !!! abstract 14 | This information is specific to GitHub Pull Requests (often abbreviated as "PR"). 15 | 16 | While the Pull Request review feature has been diligently tested, there are still some caveats to 17 | beware of when using Pull Request reviews. 18 | 19 | ## Bot Permissions required 20 | The "GitHub Actions" bot may need to be allowed to approve Pull Requests. 21 | By default, the bot cannot approve Pull Request changes, only request more changes. 22 | This will show as a warning in the workflow logs if the given token (set to the 23 | environment variable `GITHUB_TOKEN`) isn't configured with the proper permissions. 24 | 25 | !!! note "See also" 26 | Refer to the GitHub documentation for [repository settings][] or [organization settings][] 27 | about adjusting the required permissions for GitHub Actions's `secrets.GITHUB_TOKEN`. 28 | 29 | See our [documented permissions](permissions.md#pull-request-reviews). 30 | 31 | ## Auto-disabled for certain event types 32 | The feature is auto-disabled for 33 | 34 | - closed Pull Requests 35 | - Pull Requests marked as "draft" 36 | - push events 37 | 38 | ## Posts a new review on each run 39 | Clang-tidy and clang-format suggestions are shown in 1 Pull Request review. 40 | 41 | - Users are encouraged to choose either [`tidy-review`][tidy-review] or [`format-review`][format-review]. 42 | Enabling both will likely show duplicate or similar suggestions. 43 | Remember, clang-tidy can be configured to use the same [`style`][style] that clang-format accepts. 44 | There is no current implementation to combine suggestions from both tools (clang-tidy kind of 45 | does that anyway). 46 | - Each generated review is specific to the commit that triggered the Continuous Integration 47 | workflow. 48 | - Outdated reviews are dismissed but not marked as resolved. 49 | Also, the outdated review's summary comment is not automatically hidden. 50 | To reduce the Pull Request's thread noise, users interaction is required. 51 | 52 | !!! note "See also" 53 | Refer to GitHub's documentation about [hiding a comment][]. 54 | Hiding a Pull Request review's summary comment will not resolve the suggestions in the diff. 55 | Please also refer to [resolve a conversion][] to collapse outdated or duplicate suggestions 56 | in the diff. 57 | 58 | GitHub REST API does not provide a way to hide comments or mark review suggestions as resolved. 59 | 60 | !!! tip 61 | We do support an environment variable named `CPP_LINTER_PR_REVIEW_SUMMARY_ONLY`. 62 | If the variable is set to ``true``, then the review only contains a summary comment 63 | with no suggestions posted in the diff. 64 | 65 | ## Probable non-exhaustive reviews 66 | If any suggestions did not fit within the Pull Request diff, then the review's summary comment will 67 | indicate how many suggestions were left out. 68 | The full patch of suggestions is always included as a collapsed code block in the review summary 69 | comment. This isn't a problem we can fix. 70 | GitHub won't allow review comments/suggestions to target lines that are not shown in the Pull 71 | Request diff (the summation of file differences in a Pull Request). 72 | 73 | - Users are encouraged to set [`lines-changed-only`][lines-changed-only] to `true`. 74 | This will *help* us keep the suggestions limited to lines that are shown within the Pull 75 | Request diff. 76 | However, there are still some cases where clang-format or clang-tidy will apply fixes to lines 77 | that are not within the diff. 78 | This can't be avoided because the `--line-filter` passed to the clang-tidy (and `--lines` 79 | passed to clang-format) only applies to analysis, not fixes. 80 | - Not every diagnostic from clang-tidy can be automatically fixed. 81 | Some diagnostics require user interaction/decision to properly address. 82 | - Some fixes provided might depend on what compiler is used. 83 | We have made it so clang-tidy takes advantage of any fixes provided by the compiler. 84 | Compilation errors may still prevent clang-tidy from reporting all concerns. 85 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | markdown-gfm-admonition 2 | mkdocs 3 | mkdocs-gen-files 4 | mkdocs-include-markdown-plugin 5 | mkdocs-material 6 | pyyaml 7 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | th { 2 | background-color: var(--md-default-fg-color--lightest); 3 | } 4 | 5 | .md-header, 6 | .md-nav--primary .md-nav__title[for="__drawer"] { 7 | background-color: #4051b5; 8 | } 9 | 10 | @keyframes heart { 11 | 12 | 0%, 13 | 40%, 14 | 80%, 15 | to { 16 | transform: scale(1) 17 | } 18 | 19 | 20%, 20 | 60% { 21 | transform: scale(1.15) 22 | } 23 | } 24 | 25 | .md-typeset .mdx-heart { 26 | animation: heart 1s infinite 27 | } 28 | 29 | .md-typeset .mdx-badge { 30 | font-size: .85em 31 | } 32 | 33 | .md-typeset .mdx-badge--heart { 34 | color: #ff4281; 35 | } 36 | 37 | .md-typeset .mdx-badge--heart.twemoji { 38 | animation: heart 1s infinite 39 | } 40 | 41 | .md-typeset .mdx-badge--right { 42 | float: right; 43 | margin-left: .35em 44 | } 45 | 46 | [dir=ltr] .md-typeset .mdx-badge__icon { 47 | border-top-left-radius: .1rem 48 | } 49 | 50 | [dir=rtl] .md-typeset .mdx-badge__icon { 51 | border-top-right-radius: .1rem 52 | } 53 | 54 | [dir=ltr] .md-typeset .mdx-badge__icon { 55 | border-bottom-left-radius: .1rem 56 | } 57 | 58 | [dir=rtl] .md-typeset .mdx-badge__icon { 59 | border-bottom-right-radius: .1rem 60 | } 61 | 62 | .md-typeset .mdx-badge__icon { 63 | background: var(--md-accent-fg-color--transparent); 64 | padding: .2rem 65 | } 66 | 67 | .md-typeset .mdx-badge__icon:last-child { 68 | border-radius: .1rem 69 | } 70 | 71 | [dir=ltr] .md-typeset .mdx-badge__text { 72 | border-top-right-radius: .1rem 73 | } 74 | 75 | [dir=rtl] .md-typeset .mdx-badge__text { 76 | border-top-left-radius: .1rem 77 | } 78 | 79 | [dir=ltr] .md-typeset .mdx-badge__text { 80 | border-bottom-right-radius: .1rem 81 | } 82 | 83 | [dir=rtl] .md-typeset .mdx-badge__text { 84 | border-bottom-left-radius: .1rem 85 | } 86 | 87 | .md-typeset .mdx-badge__text { 88 | box-shadow: 0 0 0 1px inset var(--md-accent-fg-color--transparent); 89 | padding: .2rem .3rem 90 | } 91 | 92 | .md-typeset .mdx-social { 93 | height: min(27rem, 80vw); 94 | position: relative 95 | } 96 | 97 | .md-typeset .mdx-social:hover .mdx-social__image { 98 | background-color: #e4e4e40d 99 | } 100 | 101 | .md-typeset .mdx-social__layer { 102 | margin-top: 4rem; 103 | position: absolute; 104 | transform-style: preserve-3d; 105 | transition: .25s cubic-bezier(.7, 0, .3, 1) 106 | } 107 | 108 | .md-typeset .mdx-social__layer:hover .mdx-social__label { 109 | opacity: 1 110 | } 111 | 112 | .md-typeset .mdx-social__layer:hover .mdx-social__image { 113 | background-color: #7f7f7ffc 114 | } 115 | 116 | .md-typeset .mdx-social__layer:hover~.mdx-social__layer { 117 | opacity: 0 118 | } 119 | 120 | .md-typeset .mdx-social__image { 121 | box-shadow: -.25rem .25rem .5rem #0000000d; 122 | transform: rotate(-40deg) skew(15deg, 15deg) scale(.7); 123 | transition: all .25s 124 | } 125 | 126 | .md-typeset .mdx-social__image img { 127 | display: block 128 | } 129 | 130 | .md-typeset .mdx-social__label { 131 | background-color: var(--md-default-fg-color--light); 132 | color: var(--md-default-bg-color); 133 | display: block; 134 | opacity: 0; 135 | padding: .2rem .4rem; 136 | position: absolute; 137 | transition: all .25s 138 | } 139 | 140 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(6) { 141 | transform: translateY(-30px) 142 | } 143 | 144 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(5) { 145 | transform: translateY(-20px) 146 | } 147 | 148 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(4) { 149 | transform: translateY(-10px) 150 | } 151 | 152 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(3) { 153 | transform: translateY(0) 154 | } 155 | 156 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(2) { 157 | transform: translateY(10px) 158 | } 159 | 160 | .md-typeset .mdx-social:hover .mdx-social__layer:first-child { 161 | transform: translateY(20px) 162 | } 163 | 164 | .md-typeset .mdx-social:hover .mdx-social__layer:nth-child(0) { 165 | transform: translateY(30px) 166 | } 167 | 168 | .md-banner { 169 | color: var(--md-footer-fg-color--lighter) 170 | } 171 | 172 | .md-banner strong { 173 | white-space: nowrap 174 | } 175 | 176 | .md-banner a, 177 | .md-banner strong { 178 | color: var(--md-footer-fg-color) 179 | } 180 | 181 | .md-banner a:focus, 182 | .md-banner a:hover { 183 | color: currentcolor 184 | } 185 | 186 | .md-banner a:focus .twemoji, 187 | .md-banner a:hover .twemoji { 188 | background-color: var(--md-footer-fg-color); 189 | box-shadow: none 190 | } 191 | 192 | .md-banner .twemoji { 193 | border-radius: 100%; 194 | box-shadow: inset 0 0 0 .05rem currentcolor; 195 | display: inline-block; 196 | height: 1.2rem; 197 | padding: .25rem; 198 | transition: all .25s; 199 | vertical-align: bottom; 200 | width: 1.2rem 201 | } 202 | 203 | .md-banner .twemoji svg { 204 | display: block; 205 | max-height: none 206 | } 207 | 208 | /* annotation buttons' pulse animation */ 209 | a.md-annotation__index { 210 | border-radius: 2.2ch; 211 | } 212 | 213 | @keyframes pulse { 214 | 0% { 215 | box-shadow: 0 0 0 0 var(--md-accent-fg-color); 216 | transform: scale(.95) 217 | } 218 | 219 | 75% { 220 | box-shadow: 0 0 0 .625em transparent; 221 | transform: scale(1) 222 | } 223 | 224 | to { 225 | box-shadow: 0 0 0 0 transparent; 226 | transform: scale(.95) 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: C/C++ Linter Action 2 | site_description: "Developer documentation from sources." 3 | site_url: "https://cpp-linter.github.io/cpp-linter-action" 4 | repo_url: "https://github.com/cpp-linter/cpp-linter-action" 5 | repo_name: "cpp-linter/cpp-linter-action" 6 | edit_uri: "edit/main/docs/" 7 | nav: 8 | - index.md 9 | - inputs-outputs.md 10 | - pr-review-caveats.md 11 | - permissions.md 12 | - examples/index.md 13 | - contributing-guidelines.md 14 | 15 | theme: 16 | name: material 17 | features: 18 | - navigation.top 19 | - content.tabs.link 20 | - content.tooltips 21 | - content.code.annotate 22 | - content.code.copy 23 | - content.action.view 24 | - content.action.edit 25 | - navigation.footer 26 | - search.suggest 27 | - search.share 28 | - navigation.tracking 29 | - toc.follow 30 | logo: images/logo.png 31 | favicon: images/favicon.ico 32 | icon: 33 | repo: fontawesome/brands/github 34 | palette: 35 | # Palette toggle for automatic mode 36 | - media: "(prefers-color-scheme)" 37 | primary: blue 38 | accent: cyan 39 | toggle: 40 | icon: material/brightness-auto 41 | name: Switch to light mode 42 | 43 | # Palette toggle for light mode 44 | - media: "(prefers-color-scheme: light)" 45 | scheme: default 46 | primary: blue 47 | accent: cyan 48 | toggle: 49 | icon: material/lightbulb-outline 50 | name: Switch to dark mode 51 | 52 | # Palette toggle for dark mode 53 | - media: "(prefers-color-scheme: dark)" 54 | scheme: slate 55 | primary: blue 56 | accent: cyan 57 | toggle: 58 | icon: material/lightbulb 59 | name: Switch to system preference 60 | extra: 61 | social: 62 | - icon: fontawesome/brands/github 63 | link: https://github.com/cpp-linter/cpp-linter 64 | 65 | extra_css: 66 | - stylesheets/extra.css 67 | 68 | plugins: 69 | - search 70 | - include-markdown 71 | - gen-files: 72 | scripts: 73 | - docs/gen_io_doc.py 74 | 75 | markdown_extensions: 76 | - pymdownx.superfences 77 | - pymdownx.tabbed: 78 | alternate_style: true 79 | - pymdownx.emoji: 80 | emoji_index: !!python/name:material.extensions.emoji.twemoji 81 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 82 | - toc: 83 | permalink: true 84 | - pymdownx.highlight: 85 | linenums_style: pymdownx-inline 86 | - pymdownx.inlinehilite 87 | - pymdownx.snippets: 88 | check_paths: true 89 | - attr_list 90 | - admonition 91 | - markdown_gfm_admonition 92 | 93 | # Hooks 94 | hooks: 95 | - docs/badge_hook.py 96 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Install clang-tools binaries (clang-format, clang-tidy) 2 | # For details please see: https://github.com/cpp-linter/clang-tools-pip 3 | clang-tools==0.15.1 4 | 5 | # cpp-linter core Python executable package 6 | # For details please see: https://github.com/cpp-linter/cpp-linter 7 | cpp-linter==1.10.7 8 | --------------------------------------------------------------------------------