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..4f84a390 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' +> auto-fix-commit-msg: 'style: apply styling format fix [skip ci]' +> ``` + ## Used By
diff --git a/action.yml b/action.yml index c5053d88..2407326c 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 + auto-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.auto-fix-commit-msg }}' | is-empty) { + 'style: apply styling format fix' + } else { + '${{ inputs.auto-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..eeb13d49 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' + auto-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.