From 52ebca9e98e91744ece49c2a6a709a2d3bda207f Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 8 Jun 2026 19:29:36 +0300 Subject: [PATCH 1/2] feat: add auto-fix option to automatically format and commit clang-format fixes Adds two new inputs: - auto-fix: runs cpp-linter --fix and auto-commits changes - fix-commit-msg: custom commit message (default: 'style: apply styling format fix') The auto-fix workflow: 1. Runs cpp-linter with --fix (applies clang-format -i) 2. If there are changed files, commits and pushes as github-actions[bot] 3. Push failures degrade to a warning Closes #439 --- .github/workflows/examples/auto-fix.yml | 27 +++++++++++++++ README.md | 31 +++++++++++++++++ action.yml | 46 +++++++++++++++++++++++++ docs/action.yml | 5 +++ docs/examples/index.md | 11 ++++++ docs/permissions.md | 12 +++++++ 6 files changed, 132 insertions(+) create mode 100644 .github/workflows/examples/auto-fix.yml diff --git a/.github/workflows/examples/auto-fix.yml b/.github/workflows/examples/auto-fix.yml new file mode 100644 index 00000000..6d0df6fa --- /dev/null +++ b/.github/workflows/examples/auto-fix.yml @@ -0,0 +1,27 @@ +name: cpp-linter (auto-fix) +on: + pull_request: + branches: [main, master, develop] + paths: ['**.c', '**.cpp', '**.h', '**.hpp', '**.cxx', '**.hxx', '**.cc', '**.hh', '**CMakeLists.txt', 'meson.build', '**.cmake'] + +jobs: + cpp-linter: + runs-on: ubuntu-latest + permissions: + contents: write # needed for auto-fix commits + pull-requests: write + steps: + - uses: actions/checkout@v5 + + - uses: cpp-linter/cpp-linter-action@v2 + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: 'file' # Use .clang-format config file + tidy-checks: '-*' # disable clang-tidy + auto-fix: 'true' # auto-apply clang-format fixes + + - name: Fail fast?! + if: steps.linter.outputs.clang-format-checks-failed > 0 + run: exit 1 diff --git a/README.md b/README.md index 2f9ca9a2..051d1823 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,37 @@ For all explanations of our available input parameters and output variables, see See also our [example recipes][recipes-doc]. +### Auto-fix clang-format issues + +You can enable automatic fixing of clang-format issues by setting `auto-fix: 'true'`. +When enabled, the action will: + +1. Run clang-format detection as usual +2. Apply `clang-format -i` to fix any files with style issues +3. Commit and push the formatted changes back to the PR branch + +```yaml + steps: + - uses: actions/checkout@v5 + - uses: cpp-linter/cpp-linter-action@v2 + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: 'file' + auto-fix: 'true' # automatically fix format issues +``` + +> [!TIP] +> To prevent the auto-fix commit from triggering another CI run, include a +> `[skip ci]` (or `[ci skip]`, `[no ci]`, etc.) tag in your custom commit message: +> +> ```yaml +> with: +> auto-fix: 'true' +> fix-commit-msg: 'style: apply styling format fix [skip ci]' +> ``` + ## Used By

diff --git a/action.yml b/action.yml index c5053d88..b336d904 100644 --- a/action.yml +++ b/action.yml @@ -209,6 +209,24 @@ inputs: Set this option to `true` to prevent Pull Request reviews from approving or requesting changes. default: 'false' required: false + auto-fix: + description: | + Set this option to `true` to automatically apply clang-format fixes + and commit them back to the PR branch. + + When enabled, cpp-linter runs with ``--fix``, which applies + ``clang-format -i`` on files with style issues. After that, + a new commit is pushed to the PR branch with the formatted changes. + + This option has no effect on clang-tidy issues. + default: 'false' + required: false + fix-commit-msg: + description: | + Custom commit message for the auto-fix commit. + Only used when ``auto-fix`` is ``true``. + default: 'style: apply styling format fix' + required: false jobs: description: | The number of jobs to run in parallel. @@ -458,6 +476,9 @@ runs: '--passive-reviews=${{ inputs.passive-reviews }}' '--jobs=${{ inputs.jobs }}' ] + if '${{ inputs.auto-fix }}' == 'true' { + $args = ($args | append ['--fix']) + } mut uv_args = [run --no-sync --project $action_path --directory (pwd)] let gh_action_debug = $env | get --optional 'ACTIONS_STEP_DEBUG' @@ -483,3 +504,28 @@ runs: print $"\n(ansi purple)Running cpp-linter(ansi reset)" ^$'($env.UV_INSTALL_DIR)/uv' ...$uv_args cpp-linter ...$args + + - name: Auto-commit clang-format fixes + if: inputs.auto-fix == 'true' || inputs.auto-fix == true + shell: nu {0} + run: | + let has_changes = (^git diff --exit-code) | complete | $in.exit_code != 0 + if $has_changes { + ^git config user.name 'github-actions[bot]' + ^git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + ^git add -A + let commit_msg = if ('${{ inputs.fix-commit-msg }}' | is-empty) { + 'style: apply styling format fix' + } else { + '${{ inputs.fix-commit-msg }}' + } + ^git commit -m $"($commit_msg)" + let push_result = (^git push) | complete + if $push_result.exit_code != 0 { + print $"(ansi yellow)::warning title=Auto-fix push failed::($push_result.stderr)(ansi reset)" + } else { + print $"(ansi green)Auto-fix commit pushed successfully(ansi reset)" + } + } else { + print $"(ansi green)No formatting changes to commit(ansi reset)" + } diff --git a/docs/action.yml b/docs/action.yml index 29a08efa..ce186f8b 100644 --- a/docs/action.yml +++ b/docs/action.yml @@ -47,6 +47,11 @@ inputs: passive-reviews: minimum-version: '2.12.0' required-permission: 'pull-requests: write #pull-request-reviews' + auto-fix: + minimum-version: '2.19.0' + required-permission: 'contents: write #auto-fix' + fix-commit-msg: + minimum-version: '2.19.0' jobs: minimum-version: '2.11.0' cache-enable: diff --git a/docs/examples/index.md b/docs/examples/index.md index a36646e0..e0679327 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -2,11 +2,22 @@ [style]: ../inputs-outputs.md#style [tidy-checks]: ../inputs-outputs.md#tidy-checks [thread-comments]: ../inputs-outputs.md#thread-comments +[auto-fix]: ../inputs-outputs.md#auto-fix # Recipes Here are some example workflows to get started quickly. +=== "auto-fix clang-format" + + ``` yaml + --8<-- ".github/workflows/examples/auto-fix.yml" + ``` + + 1. See also [`auto-fix`][auto-fix] + 2. See also [`style`][style] + 3. See also [`tidy-checks`][tidy-checks] + === "only clang-tidy" ``` yaml diff --git a/docs/permissions.md b/docs/permissions.md index 3495c392..bdcf4a74 100644 --- a/docs/permissions.md +++ b/docs/permissions.md @@ -78,3 +78,15 @@ The [`tidy-review`](inputs-outputs.md#tidy-review), [`format-review`](inputs-out permissions: pull-requests: write ``` + +## Auto-fix + +The [`auto-fix`](inputs-outputs.md#auto-fix) feature requires the following permission +in addition to any other permissions needed for other features: + +```yaml + permissions: + contents: write # (1)! +``` + +1. Needed to commit and push the formatted changes back to the PR branch. From ff93734f91aa52e17e72a0c75970a9812539b7b3 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 8 Jun 2026 21:07:11 +0300 Subject: [PATCH 2/2] refactor: rename fix-commit-msg to auto-fix-commit-msg for consistency --- README.md | 2 +- action.yml | 6 +++--- docs/action.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 051d1823..4f84a390 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ When enabled, the action will: > ```yaml > with: > auto-fix: 'true' -> fix-commit-msg: 'style: apply styling format fix [skip ci]' +> auto-fix-commit-msg: 'style: apply styling format fix [skip ci]' > ``` ## Used By diff --git a/action.yml b/action.yml index b336d904..2407326c 100644 --- a/action.yml +++ b/action.yml @@ -221,7 +221,7 @@ inputs: This option has no effect on clang-tidy issues. default: 'false' required: false - fix-commit-msg: + auto-fix-commit-msg: description: | Custom commit message for the auto-fix commit. Only used when ``auto-fix`` is ``true``. @@ -514,10 +514,10 @@ runs: ^git config user.name 'github-actions[bot]' ^git config user.email '41898282+github-actions[bot]@users.noreply.github.com' ^git add -A - let commit_msg = if ('${{ inputs.fix-commit-msg }}' | is-empty) { + let commit_msg = if ('${{ inputs.auto-fix-commit-msg }}' | is-empty) { 'style: apply styling format fix' } else { - '${{ inputs.fix-commit-msg }}' + '${{ inputs.auto-fix-commit-msg }}' } ^git commit -m $"($commit_msg)" let push_result = (^git push) | complete diff --git a/docs/action.yml b/docs/action.yml index ce186f8b..eeb13d49 100644 --- a/docs/action.yml +++ b/docs/action.yml @@ -50,7 +50,7 @@ inputs: auto-fix: minimum-version: '2.19.0' required-permission: 'contents: write #auto-fix' - fix-commit-msg: + auto-fix-commit-msg: minimum-version: '2.19.0' jobs: minimum-version: '2.11.0'