From c4cd36acb1eab24f28c3c30d8689060458de735a Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Wed, 5 Aug 2026 17:35:40 +0000 Subject: [PATCH 01/15] test: exercise the auto-fix pull-request path end to end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 covers the push path. This adds the half only a real pull request can reach: the step that moves the runner off the PR merge ref and onto the PR head branch, its same-repository gating, and pushing the fix back so the pull request updates itself. Neither cpp-linter-action#443 nor cpp-linter#202 has to be merged — the action is consumed from its PR branch as a local action and its pinned cpp-linter version is rewritten in the runner's workspace. Scans only the files this pull request changes, because src/demo.cpp and src/demo.hpp are intentionally unformatted fixtures that auto-fix would otherwise repair and commit; the check asserts they stay untouched. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012uXrN1wk5EaqK5GimN3deT --- .github/workflows/auto-fix-pr-e2e.yml | 182 ++++++++++++++++++++++++++ src/e2e_autofix_pr_demo.cpp | 2 + 2 files changed, 184 insertions(+) create mode 100644 .github/workflows/auto-fix-pr-e2e.yml create mode 100644 src/e2e_autofix_pr_demo.cpp diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml new file mode 100644 index 0000000..8ece82b --- /dev/null +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -0,0 +1,182 @@ +name: auto-fix PR e2e + +# Phase 2 of the auto-fix end-to-end test: the pull-request path. +# +# Phase 1 (auto-fix-e2e.yml) covers the push path, where the action derives the +# branch from GITHUB_REF. This workflow covers what only a real PR can exercise: +# +# - the "Checkout PR branch for auto-fix push capability" step, which switches +# the runner off the PR *merge* ref and onto the PR *head* branch +# - the same-repository gating that gets applied to that step +# - pushing the fix back onto the PR head branch, so the PR updates itself +# +# As in phase 1, neither cpp-linter-action#443 nor cpp-linter#202 needs to be +# merged: the action is consumed from its PR branch as a local action, and the +# cpp-linter version it pins is rewritten in this runner's workspace. +# +# Workflows added by a pull request do run for `pull_request` events, so this +# file takes effect from the PR branch itself. + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: write + +env: + CPP_LINTER_REF: 'feature/auto-fix' + ACTION_DIR: .action-under-test + TEST_FILE: src/e2e_autofix_pr_demo.cpp + CLANG_VERSION: '18' + COMMIT_MSG: 'style: apply clang-format fixes' + +jobs: + auto-fix-pr: + # Only ever run for the dedicated e2e branch, never for real pull requests. + if: startsWith(github.head_ref, 'test/auto-fix-pr-e2e') + runs-on: ubuntu-latest + steps: + # `persist-credentials` stays enabled (the default) so the action can fetch + # the head branch and push the fix back to it. + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: Check out the action under test + uses: actions/checkout@v7 + with: + repository: cpp-linter/cpp-linter-action + ref: feature/auto-fix + path: .action-under-test + persist-credentials: false + + - name: Point the action at the cpp-linter PR branch + run: | + set -euo pipefail + cd "$ACTION_DIR" + python3 - "$CPP_LINTER_REF" <<'PY' + import pathlib + import re + import sys + + ref = sys.argv[1] + spec = f"cpp-linter @ git+https://github.com/cpp-linter/cpp-linter.git@{ref}" + path = pathlib.Path("pyproject.toml") + text = path.read_text(encoding="utf-8") + patched, count = re.subn(r'"cpp-linter==[^"]+"', f'"{spec}"', text) + if count != 1: + sys.exit(f"expected exactly 1 cpp-linter pin, patched {count}") + path.write_text(patched, encoding="utf-8") + print(patched) + PY + rm -f uv.lock + + - name: Record the pre-fix state + run: | + set -euo pipefail + echo "::group::fixture before" + cat "$TEST_FILE" + echo "::endgroup::" + { + echo "MALFORMED_BLOB=$(git hash-object "$TEST_FILE")" + echo "PR_HEAD_SHA=${{ github.event.pull_request.head.sha }}" + } >> "$GITHUB_ENV" + + # `files-changed-only: true` is deliberate and load-bearing: src/demo.cpp + # and src/demo.hpp are intentionally unformatted fixtures of this repo, and + # scanning everything would make auto-fix "repair" and commit them too. + # clang-tidy is off so this measures the clang-format path only. + - name: Run cpp-linter with auto-fix + uses: ./.action-under-test + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: file + tidy-checks: '-*' + files-changed-only: true + lines-changed-only: false + ignore: build|.action-under-test + version: '18' + verbosity: debug + auto-fix: true + auto-fix-commit-msg: 'style: apply clang-format fixes' + + - name: Verify the PR branch was fixed and updated + run: | + set -uo pipefail + failed=0 + head_ref='${{ github.event.pull_request.head.ref }}' + + echo "::group::fixture after" + cat "$TEST_FILE" + echo "::endgroup::" + + # The action must have moved the runner onto the PR head branch. + current="$(git rev-parse --abbrev-ref HEAD)" + if [ "$current" != "$head_ref" ]; then + echo "::error title=Wrong branch::expected to be on '$head_ref', but HEAD is '$current'" + failed=1 + else + echo "PASS: runner switched from the merge ref onto '$head_ref'" + fi + + if [ "$(git hash-object "$TEST_FILE")" = "$MALFORMED_BLOB" ]; then + echo "::error title=Not reformatted::$TEST_FILE is unchanged; --fix did not rewrite it." + failed=1 + else + echo "PASS: fixture was reformatted" + fi + + head_sha="$(git rev-parse HEAD)" + subject="$(git log -1 --pretty=%s)" + if [ "$head_sha" = "$PR_HEAD_SHA" ]; then + echo "::error title=No commit::auto-fix produced no commit on the PR branch." + failed=1 + else + echo "PASS: auto-fix commit $head_sha" + echo " subject: $subject" + echo " author: $(git log -1 --pretty='%an <%ae>')" + fi + + if [ "$subject" != "$COMMIT_MSG" ]; then + echo "::error title=Wrong commit message::expected '$COMMIT_MSG', got '$subject'" + failed=1 + else + echo "PASS: commit message matches auto-fix-commit-msg" + fi + + fmt="$(command -v "clang-format-${CLANG_VERSION}" || command -v clang-format || true)" + if [ -n "$fmt" ]; then + if "$fmt" --style=file --dry-run --Werror "$TEST_FILE"; then + echo "PASS: committed fixture satisfies .clang-format" + else + echo "::error title=Still unformatted::the committed fixture still violates .clang-format" + failed=1 + fi + else + echo "note: clang-format not on PATH here; skipped the re-check" + fi + + # The repo's intentionally-unformatted fixtures must be left alone. + if ! git diff --quiet "$PR_HEAD_SHA" HEAD -- src/demo.cpp src/demo.hpp; then + echo "::error title=Collateral damage::auto-fix also rewrote this repo's intentional demo fixtures." + failed=1 + else + echo "PASS: src/demo.cpp and src/demo.hpp were left untouched" + fi + + # The fix has to be on the PR branch at the remote, not just locally. + git fetch -q origin "$head_ref" + if [ "$(git rev-parse FETCH_HEAD)" != "$head_sha" ]; then + echo "::error title=Not pushed::the auto-fix commit is not on origin/$head_ref" + failed=1 + else + echo "PASS: auto-fix commit is present on origin/$head_ref" + fi + + if [ "$failed" -eq 0 ]; then + echo "auto-fix PR e2e PASSED" + fi + exit "$failed" diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp new file mode 100644 index 0000000..38b08a5 --- /dev/null +++ b/src/e2e_autofix_pr_demo.cpp @@ -0,0 +1,2 @@ +#include +int main( ){int x=0 ;for(;;){break;}printf("Hello from PR!\n") ;return x;} From b658f069e265dfc21995e790f4908242bfaf274e Mon Sep 17 00:00:00 2001 From: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:36:36 +0000 Subject: [PATCH 02/15] style: apply clang-format fixes --- src/e2e_autofix_pr_demo.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 38b08a5..8fec1fe 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -1,2 +1,10 @@ #include -int main( ){int x=0 ;for(;;){break;}printf("Hello from PR!\n") ;return x;} +int main() +{ + int x = 0; + for (;;) { + break; + } + printf("Hello from PR!\n"); + return x; +} From 8ca581fff43a72a4a05d1721fc58a0cd127f4333 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 20 Aug 2026 01:58:17 +0300 Subject: [PATCH 03/15] test: cover clang-tidy alongside auto-fix The previous run passed with `tidy-checks: '-*'`, which meant it only ever exercised the clang-format half. That hid a real defect: `--fix` rewrites the file in place, but clang-tidy reads line numbers off the file on disk while its `--line-filter` is keyed to the diff, so every diagnostic after a reflowed line drifted out of the filter. The job now lints twice with identical inputs -- once with auto-fix off to establish a baseline, once with it on -- and asserts the clang-tidy count is unchanged. Expressing it as a comparison rather than a hard-coded number keeps it stable across clang releases. The fixture is rewritten so formatting it expands 12 lines to 28, which is what makes the drift observable, and `lines-changed-only` is now true so the `--line-filter` is actually in play. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/auto-fix-pr-e2e.yml | 105 ++++++++++++++++++++++++-- src/e2e_autofix_pr_demo.cpp | 22 +++--- 2 files changed, 111 insertions(+), 16 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 8ece82b..c052411 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -9,6 +9,7 @@ name: auto-fix PR e2e # the runner off the PR *merge* ref and onto the PR *head* branch # - the same-repository gating that gets applied to that step # - pushing the fix back onto the PR head branch, so the PR updates itself +# - that applying fixes does not disturb what clang-tidy reports # # As in phase 1, neither cpp-linter-action#443 nor cpp-linter#202 needs to be # merged: the action is consumed from its PR branch as a local action, and the @@ -30,6 +31,10 @@ env: TEST_FILE: src/e2e_autofix_pr_demo.cpp CLANG_VERSION: '18' COMMIT_MSG: 'style: apply clang-format fixes' + # Two long-standing checks with stable behaviour across clang releases. The + # fixture triggers both, and `-*` keeps the repo's .clang-tidy out of it so + # the counts below don't drift when that file changes. + TIDY_CHECKS: '-*,readability-magic-numbers,modernize-use-nullptr' jobs: auto-fix-pr: @@ -76,17 +81,48 @@ jobs: run: | set -euo pipefail echo "::group::fixture before" - cat "$TEST_FILE" + cat -n "$TEST_FILE" echo "::endgroup::" { echo "MALFORMED_BLOB=$(git hash-object "$TEST_FILE")" echo "PR_HEAD_SHA=${{ github.event.pull_request.head.sha }}" } >> "$GITHUB_ENV" + # Baseline: the same lint, with auto-fix off. This measures what + # clang-tidy reports against the file as the diff describes it, and is + # the reference the auto-fix run below has to reproduce. + # # `files-changed-only: true` is deliberate and load-bearing: src/demo.cpp # and src/demo.hpp are intentionally unformatted fixtures of this repo, and # scanning everything would make auto-fix "repair" and commit them too. - # clang-tidy is off so this measures the clang-format path only. + - name: Lint without auto-fix (baseline) + uses: ./.action-under-test + id: baseline + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: file + tidy-checks: ${{ env.TIDY_CHECKS }} + extra-args: '-std=c++17' + files-changed-only: true + lines-changed-only: true + ignore: build|.action-under-test + version: '18' + verbosity: debug + thread-comments: false + step-summary: false + auto-fix: false + + - name: The baseline must not have touched the fixture + run: | + set -euo pipefail + if [ "$(git hash-object "$TEST_FILE")" != "$MALFORMED_BLOB" ]; then + echo "::error title=Baseline mutated the fixture::auto-fix was off, but $TEST_FILE changed." + exit 1 + fi + echo "PASS: baseline left the fixture malformed, as expected" + + # The real run. Same inputs, auto-fix on. - name: Run cpp-linter with auto-fix uses: ./.action-under-test id: linter @@ -94,26 +130,73 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: style: file - tidy-checks: '-*' + tidy-checks: ${{ env.TIDY_CHECKS }} + extra-args: '-std=c++17' files-changed-only: true - lines-changed-only: false + lines-changed-only: true ignore: build|.action-under-test version: '18' verbosity: debug + thread-comments: false + step-summary: false auto-fix: true auto-fix-commit-msg: 'style: apply clang-format fixes' - name: Verify the PR branch was fixed and updated + env: + BASE_FORMAT: ${{ steps.baseline.outputs.clang-format-checks-failed }} + BASE_TIDY: ${{ steps.baseline.outputs.clang-tidy-checks-failed }} + FIX_FORMAT: ${{ steps.linter.outputs.clang-format-checks-failed }} + FIX_TIDY: ${{ steps.linter.outputs.clang-tidy-checks-failed }} run: | set -uo pipefail failed=0 head_ref='${{ github.event.pull_request.head.ref }}' echo "::group::fixture after" - cat "$TEST_FILE" + cat -n "$TEST_FILE" echo "::endgroup::" - # The action must have moved the runner onto the PR head branch. + echo "baseline: clang-format=$BASE_FORMAT clang-tidy=$BASE_TIDY" + echo "auto-fix: clang-format=$FIX_FORMAT clang-tidy=$FIX_TIDY" + + # --- sanity: the fixture has to actually exercise both tools --- + if [ "${BASE_FORMAT:-0}" -le 0 ]; then + echo "::error title=Fixture not malformed::the baseline found no clang-format issues, so this run proves nothing." + failed=1 + else + echo "PASS: baseline saw $BASE_FORMAT clang-format issue(s)" + fi + + if [ "${BASE_TIDY:-0}" -le 0 ]; then + echo "::error title=No tidy coverage::the baseline found no clang-tidy issues, so the comparison below proves nothing." + failed=1 + else + echo "PASS: baseline saw $BASE_TIDY clang-tidy diagnostic(s)" + fi + + # --- auto-fix cleared the format issues --- + if [ "${FIX_FORMAT:-1}" -ne 0 ]; then + echo "::error title=Format issues remain::auto-fix ran but still reports $FIX_FORMAT clang-format issue(s)." + failed=1 + else + echo "PASS: auto-fix cleared all clang-format issues" + fi + + # --- the point of the tidy coverage --- + # clang-format's `-i` rewrites the file. clang-tidy reports line + # numbers from the file on disk, but its --line-filter and the review + # comments built from its output are keyed to the diff. If the tools + # run in the wrong order, diagnostics past a reflowed line drift out + # of the filter and silently disappear. + if [ "${FIX_TIDY:-0}" -ne "${BASE_TIDY:-0}" ]; then + echo "::error title=Tidy diagnostics drifted::auto-fix changed the clang-tidy count from $BASE_TIDY to $FIX_TIDY. Applying format fixes must not affect what clang-tidy reports." + failed=1 + else + echo "PASS: clang-tidy still reports $FIX_TIDY diagnostic(s); auto-fix did not shift them" + fi + + # --- the pull-request plumbing --- current="$(git rev-parse --abbrev-ref HEAD)" if [ "$current" != "$head_ref" ]; then echo "::error title=Wrong branch::expected to be on '$head_ref', but HEAD is '$current'" @@ -147,6 +230,16 @@ jobs: echo "PASS: commit message matches auto-fix-commit-msg" fi + # Only the fixture may appear in the auto-fix commit. + touched="$(git diff --name-only "$PR_HEAD_SHA" HEAD)" + if [ "$touched" != "$TEST_FILE" ]; then + echo "::error title=Unexpected files committed::auto-fix committed more than the fixture:" + echo "$touched" + failed=1 + else + echo "PASS: the auto-fix commit contains only $TEST_FILE" + fi + fmt="$(command -v "clang-format-${CLANG_VERSION}" || command -v clang-format || true)" if [ -n "$fmt" ]; then if "$fmt" --style=file --dry-run --Werror "$TEST_FILE"; then diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 8fec1fe..7d0cbdd 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -1,10 +1,12 @@ -#include -int main() -{ - int x = 0; - for (;;) { - break; - } - printf("Hello from PR!\n"); - return x; -} +// Deliberately malformed fixture for the auto-fix e2e test. +// +// Two properties matter here: +// 1. clang-format has plenty to fix, so auto-fix has something to commit. +// 2. Formatting it changes its line count (the one-liners below expand), +// which is what makes it able to catch clang-tidy diagnostics drifting +// off the diff when the tools run in the wrong order. +int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} + +int magic_user( ){int v=42;return v;} + +int * null_user( ){int * p=0;return p;} From a8d79e9a8f5a9385e377953a62b4a394fe7f306f Mon Sep 17 00:00:00 2001 From: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com> Date: Wed, 19 Aug 2026 22:59:15 +0000 Subject: [PATCH 04/15] style: apply clang-format fixes --- src/e2e_autofix_pr_demo.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 7d0cbdd..874fb59 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,8 +5,24 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} +int accumulate() +{ + int a = 10; + int b = 20; + int c = 30; + int d = 40; + int e = 50; + return a + b + c + d + e; +} -int magic_user( ){int v=42;return v;} +int magic_user() +{ + int v = 42; + return v; +} -int * null_user( ){int * p=0;return p;} +int* null_user() +{ + int* p = 0; + return p; +} From b7df87fa3721f9dad91b7885daa1e92238e00626 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Wed, 19 Aug 2026 23:00:30 +0000 Subject: [PATCH 05/15] test: make the auto-fix PR check re-run safe Pushing the fix back onto the pull request raises a synchronize event, so this workflow runs again against its own auto-fix commit. The fixture is already clean by then and doing nothing is the correct behaviour, but the checks demanded another rewrite and another commit, so every second run failed -- as it just did on b658f06. Pick the assertions from the baseline's own clang-format count rather than from the fixture's contents, so this keeps working whatever the fixture is later rewritten to contain. The already-clean case now carries its own meaning: auto-fix must leave the file byte-identical and must not manufacture an empty commit. The clang-tidy drift comparison, the tidy coverage floor and the collateral-damage checks are unchanged and still run in both states. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012uXrN1wk5EaqK5GimN3deT --- .github/workflows/auto-fix-pr-e2e.yml | 94 +++++++++++++++++---------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index c052411..a13cc8b 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -160,12 +160,21 @@ jobs: echo "baseline: clang-format=$BASE_FORMAT clang-tidy=$BASE_TIDY" echo "auto-fix: clang-format=$FIX_FORMAT clang-tidy=$FIX_TIDY" - # --- sanity: the fixture has to actually exercise both tools --- - if [ "${BASE_FORMAT:-0}" -le 0 ]; then - echo "::error title=Fixture not malformed::the baseline found no clang-format issues, so this run proves nothing." - failed=1 - else + # --- which of the two states is this run in? --- + # Pushing the fix raises a `synchronize` event, so this workflow runs a + # second time against its own auto-fix commit. The fixture is clean by + # then and doing nothing is the correct behaviour, so that run asserts + # idempotency instead of demanding another fix. The baseline's own + # clang-format count says which state we are in, so this stays true + # whatever the fixture is later rewritten to contain. + if [ "${BASE_FORMAT:-0}" -gt 0 ]; then + expect_fix=true echo "PASS: baseline saw $BASE_FORMAT clang-format issue(s)" + else + expect_fix=false + echo "NOTE: the fixture is already formatted, so this is the re-run" + echo " that auto-fix's own push triggered. Asserting that it is" + echo " a no-op rather than expecting another fix." fi if [ "${BASE_TIDY:-0}" -le 0 ]; then @@ -205,39 +214,58 @@ jobs: echo "PASS: runner switched from the merge ref onto '$head_ref'" fi - if [ "$(git hash-object "$TEST_FILE")" = "$MALFORMED_BLOB" ]; then - echo "::error title=Not reformatted::$TEST_FILE is unchanged; --fix did not rewrite it." - failed=1 - else - echo "PASS: fixture was reformatted" - fi - head_sha="$(git rev-parse HEAD)" subject="$(git log -1 --pretty=%s)" - if [ "$head_sha" = "$PR_HEAD_SHA" ]; then - echo "::error title=No commit::auto-fix produced no commit on the PR branch." - failed=1 - else - echo "PASS: auto-fix commit $head_sha" - echo " subject: $subject" - echo " author: $(git log -1 --pretty='%an <%ae>')" - fi - if [ "$subject" != "$COMMIT_MSG" ]; then - echo "::error title=Wrong commit message::expected '$COMMIT_MSG', got '$subject'" - failed=1 - else - echo "PASS: commit message matches auto-fix-commit-msg" - fi + if [ "$expect_fix" = "true" ]; then + if [ "$(git hash-object "$TEST_FILE")" = "$MALFORMED_BLOB" ]; then + echo "::error title=Not reformatted::$TEST_FILE is unchanged; --fix did not rewrite it." + failed=1 + else + echo "PASS: fixture was reformatted" + fi - # Only the fixture may appear in the auto-fix commit. - touched="$(git diff --name-only "$PR_HEAD_SHA" HEAD)" - if [ "$touched" != "$TEST_FILE" ]; then - echo "::error title=Unexpected files committed::auto-fix committed more than the fixture:" - echo "$touched" - failed=1 + if [ "$head_sha" = "$PR_HEAD_SHA" ]; then + echo "::error title=No commit::auto-fix produced no commit on the PR branch." + failed=1 + else + echo "PASS: auto-fix commit $head_sha" + echo " subject: $subject" + echo " author: $(git log -1 --pretty='%an <%ae>')" + fi + + if [ "$subject" != "$COMMIT_MSG" ]; then + echo "::error title=Wrong commit message::expected '$COMMIT_MSG', got '$subject'" + failed=1 + else + echo "PASS: commit message matches auto-fix-commit-msg" + fi + + # Only the fixture may appear in the auto-fix commit. + touched="$(git diff --name-only "$PR_HEAD_SHA" HEAD)" + if [ "$touched" != "$TEST_FILE" ]; then + echo "::error title=Unexpected files committed::auto-fix committed more than the fixture:" + echo "$touched" + failed=1 + else + echo "PASS: the auto-fix commit contains only $TEST_FILE" + fi else - echo "PASS: the auto-fix commit contains only $TEST_FILE" + # Idempotency: with nothing left to fix, auto-fix must not rewrite + # the file and must not manufacture an empty commit. + if [ "$(git hash-object "$TEST_FILE")" != "$MALFORMED_BLOB" ]; then + echo "::error title=Needless rewrite::auto-fix modified an already-formatted file." + failed=1 + else + echo "PASS: already-clean fixture was left byte-identical" + fi + + if [ "$head_sha" != "$PR_HEAD_SHA" ]; then + echo "::error title=Empty commit::auto-fix committed $head_sha despite having nothing to fix." + failed=1 + else + echo "PASS: no commit was created when there was nothing to fix" + fi fi fmt="$(command -v "clang-format-${CLANG_VERSION}" || command -v clang-format || true)" From 1748a81db205c40048c9e7ca5a22a10a13893c89 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Thu, 20 Aug 2026 02:11:32 +0300 Subject: [PATCH 06/15] test: cover format-review alongside auto-fix Asking for a clang-format review while auto-fix is on used to abort cpp-linter outright: AssertionError: FormatAdvice has no suggestions for A fixed file has nothing left to report, but the review pass still walks it and wants a patch to diff against. The combination is a natural one to reach for -- suggestions for what you have to fix by hand, auto-fix for what you don't -- so it is worth a check. Nothing gets posted: the file comes out clean and `no-lgtm` defaults to true, so the review is suppressed. The step running at all is the assertion. The fixture goes back to its malformed state so this run exercises the whole path rather than the already-clean re-run. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/auto-fix-pr-e2e.yml | 11 +++++++++++ src/e2e_autofix_pr_demo.cpp | 22 +++------------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index a13cc8b..9cf04a6 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -24,6 +24,8 @@ on: permissions: contents: write + # `format-review` on the auto-fix run below needs this. + pull-requests: write env: CPP_LINTER_REF: 'feature/auto-fix' @@ -141,6 +143,15 @@ jobs: step-summary: false auto-fix: true auto-fix-commit-msg: 'style: apply clang-format fixes' + # Only this run asks for a clang-format review, and only this run can + # hit the bug it covers: a fixed file has no advice left to report, + # but the review pass still walks it and wants a patch to diff + # against. Handing it an empty one used to abort cpp-linter with + # `AssertionError: FormatAdvice has no suggestions for `, so + # this step failing at all is the assertion. Nothing is posted -- + # the file comes out clean, and `no-lgtm` defaults to true. + format-review: true + passive-reviews: true - name: Verify the PR branch was fixed and updated env: diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 874fb59..7d0cbdd 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,24 +5,8 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate() -{ - int a = 10; - int b = 20; - int c = 30; - int d = 40; - int e = 50; - return a + b + c + d + e; -} +int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} -int magic_user() -{ - int v = 42; - return v; -} +int magic_user( ){int v=42;return v;} -int* null_user() -{ - int* p = 0; - return p; -} +int * null_user( ){int * p=0;return p;} From 46eea4759134c2c98efefc12befb251a5b7dffaa Mon Sep 17 00:00:00 2001 From: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com> Date: Wed, 19 Aug 2026 23:14:14 +0000 Subject: [PATCH 07/15] style: apply clang-format fixes --- src/e2e_autofix_pr_demo.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 7d0cbdd..874fb59 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,8 +5,24 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} +int accumulate() +{ + int a = 10; + int b = 20; + int c = 30; + int d = 40; + int e = 50; + return a + b + c + d + e; +} -int magic_user( ){int v=42;return v;} +int magic_user() +{ + int v = 42; + return v; +} -int * null_user( ){int * p=0;return p;} +int* null_user() +{ + int* p = 0; + return p; +} From 49a1adbe2756a85f70177abdbe3df27f8f478d5e Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Wed, 16 Sep 2026 13:42:42 +0300 Subject: [PATCH 08/15] test: follow the auto-fix checkout contract, use the released cpp-linter - check out the PR head commit (`ref: pull_request.head.sha`), which the action now requires instead of switching branches itself, and assert it before running - drop the step that rewrote the cpp-linter pin to a git branch: 1.14.0 ships `--fix` and the action branch pins it - put the fixture back into its malformed state so this run exercises a real fix rather than the idempotent re-run path --- .github/workflows/auto-fix-pr-e2e.yml | 47 +++++++-------------------- src/e2e_autofix_pr_demo.cpp | 22 ++----------- 2 files changed, 14 insertions(+), 55 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 9cf04a6..475e272 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -5,15 +5,14 @@ name: auto-fix PR e2e # Phase 1 (auto-fix-e2e.yml) covers the push path, where the action derives the # branch from GITHUB_REF. This workflow covers what only a real PR can exercise: # -# - the "Checkout PR branch for auto-fix push capability" step, which switches -# the runner off the PR *merge* ref and onto the PR *head* branch -# - the same-repository gating that gets applied to that step +# - checking out the PR *head* commit (checkout's default is the merge ref) +# and the action's check that this was done before it commits +# - the same-repository gating of the commit step # - pushing the fix back onto the PR head branch, so the PR updates itself # - that applying fixes does not disturb what clang-tidy reports # -# As in phase 1, neither cpp-linter-action#443 nor cpp-linter#202 needs to be -# merged: the action is consumed from its PR branch as a local action, and the -# cpp-linter version it pins is rewritten in this runner's workspace. +# The action is consumed from its PR branch as a local action; it pins the +# released cpp-linter that ships `--fix`. # # Workflows added by a pull request do run for `pull_request` events, so this # file takes effect from the PR branch itself. @@ -28,7 +27,6 @@ permissions: pull-requests: write env: - CPP_LINTER_REF: 'feature/auto-fix' ACTION_DIR: .action-under-test TEST_FILE: src/e2e_autofix_pr_demo.cpp CLANG_VERSION: '18' @@ -48,6 +46,8 @@ jobs: # the head branch and push the fix back to it. - uses: actions/checkout@v7 with: + # auto-fix commits on the PR head; checkout's default is the merge ref + ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Check out the action under test @@ -58,27 +58,6 @@ jobs: path: .action-under-test persist-credentials: false - - name: Point the action at the cpp-linter PR branch - run: | - set -euo pipefail - cd "$ACTION_DIR" - python3 - "$CPP_LINTER_REF" <<'PY' - import pathlib - import re - import sys - - ref = sys.argv[1] - spec = f"cpp-linter @ git+https://github.com/cpp-linter/cpp-linter.git@{ref}" - path = pathlib.Path("pyproject.toml") - text = path.read_text(encoding="utf-8") - patched, count = re.subn(r'"cpp-linter==[^"]+"', f'"{spec}"', text) - if count != 1: - sys.exit(f"expected exactly 1 cpp-linter pin, patched {count}") - path.write_text(patched, encoding="utf-8") - print(patched) - PY - rm -f uv.lock - - name: Record the pre-fix state run: | set -euo pipefail @@ -89,6 +68,10 @@ jobs: echo "MALFORMED_BLOB=$(git hash-object "$TEST_FILE")" echo "PR_HEAD_SHA=${{ github.event.pull_request.head.sha }}" } >> "$GITHUB_ENV" + if [ "$(git rev-parse HEAD)" != "${{ github.event.pull_request.head.sha }}" ]; then + echo "::error title=Wrong checkout::HEAD is not the PR head commit; the ref input on actions/checkout is missing." + exit 1 + fi # Baseline: the same lint, with auto-fix off. This measures what # clang-tidy reports against the file as the diff describes it, and is @@ -217,14 +200,6 @@ jobs: fi # --- the pull-request plumbing --- - current="$(git rev-parse --abbrev-ref HEAD)" - if [ "$current" != "$head_ref" ]; then - echo "::error title=Wrong branch::expected to be on '$head_ref', but HEAD is '$current'" - failed=1 - else - echo "PASS: runner switched from the merge ref onto '$head_ref'" - fi - head_sha="$(git rev-parse HEAD)" subject="$(git log -1 --pretty=%s)" diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 874fb59..7d0cbdd 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,24 +5,8 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate() -{ - int a = 10; - int b = 20; - int c = 30; - int d = 40; - int e = 50; - return a + b + c + d + e; -} +int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} -int magic_user() -{ - int v = 42; - return v; -} +int magic_user( ){int v=42;return v;} -int* null_user() -{ - int* p = 0; - return p; -} +int * null_user( ){int * p=0;return p;} From 7e3ac0493c13eeb70d81747fadece15b4423dd87 Mon Sep 17 00:00:00 2001 From: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:43:19 +0000 Subject: [PATCH 09/15] style: apply clang-format fixes --- src/e2e_autofix_pr_demo.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 7d0cbdd..874fb59 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,8 +5,24 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} +int accumulate() +{ + int a = 10; + int b = 20; + int c = 30; + int d = 40; + int e = 50; + return a + b + c + d + e; +} -int magic_user( ){int v=42;return v;} +int magic_user() +{ + int v = 42; + return v; +} -int * null_user( ){int * p=0;return p;} +int* null_user() +{ + int* p = 0; + return p; +} From 84291d1f02e9b4c2ffc18ee85bd1182dd582be20 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Thu, 17 Sep 2026 07:59:03 +0300 Subject: [PATCH 10/15] Update auto-fix-pr-e2e.yml Co-authored-by: Brendan <2bndy5@gmail.com> --- .github/workflows/auto-fix-pr-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 475e272..1813b61 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -81,7 +81,7 @@ jobs: # and src/demo.hpp are intentionally unformatted fixtures of this repo, and # scanning everything would make auto-fix "repair" and commit them too. - name: Lint without auto-fix (baseline) - uses: ./.action-under-test + uses: $/cpp-linter-action id: baseline env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From ccef371385f61f2f01b3315edb0d4e8f8df1c344 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Thu, 17 Sep 2026 07:59:18 +0300 Subject: [PATCH 11/15] Update auto-fix-pr-e2e.yml Co-authored-by: Brendan <2bndy5@gmail.com> --- .github/workflows/auto-fix-pr-e2e.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 1813b61..611ff5a 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -46,18 +46,9 @@ jobs: # the head branch and push the fix back to it. - uses: actions/checkout@v7 with: - # auto-fix commits on the PR head; checkout's default is the merge ref - ref: ${{ github.event.pull_request.head.sha }} + submodules: true fetch-depth: 0 - - name: Check out the action under test - uses: actions/checkout@v7 - with: - repository: cpp-linter/cpp-linter-action - ref: feature/auto-fix - path: .action-under-test - persist-credentials: false - - name: Record the pre-fix state run: | set -euo pipefail From 0afbfda88fd88ef4c4ebb007f1883f4110234204 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Thu, 17 Sep 2026 07:59:28 +0300 Subject: [PATCH 12/15] Update auto-fix-pr-e2e.yml Co-authored-by: Brendan <2bndy5@gmail.com> --- .github/workflows/auto-fix-pr-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 611ff5a..816fc8c 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -100,7 +100,7 @@ jobs: # The real run. Same inputs, auto-fix on. - name: Run cpp-linter with auto-fix - uses: ./.action-under-test + uses: $/cpp-linter-action id: linter env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From dcd136270563283f4741b344da8342b4e7f698fe Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Thu, 17 Sep 2026 11:59:41 +0300 Subject: [PATCH 13/15] test: point the cpp-linter-action submodule at feature/auto-fix - submodule: 894a549 -> 8feb22c (head of cpp-linter-action#443) - `uses: ./cpp-linter-action` instead of `$/cpp-linter-action`: the `$/` form is resolved from the repository archive at "Set up job", and archives do not contain submodule contents, so action.yml was not found - drop the assertion that HEAD is the PR head: this workflow now uses the default pull_request checkout --- .github/workflows/auto-fix-pr-e2e.yml | 20 +++++++------------- cpp-linter-action | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index 816fc8c..a9faf95 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -5,14 +5,13 @@ name: auto-fix PR e2e # Phase 1 (auto-fix-e2e.yml) covers the push path, where the action derives the # branch from GITHUB_REF. This workflow covers what only a real PR can exercise: # -# - checking out the PR *head* commit (checkout's default is the merge ref) -# and the action's check that this was done before it commits +# - the default pull_request checkout (the merge ref), which is what users get # - the same-repository gating of the commit step # - pushing the fix back onto the PR head branch, so the PR updates itself # - that applying fixes does not disturb what clang-tidy reports # -# The action is consumed from its PR branch as a local action; it pins the -# released cpp-linter that ships `--fix`. +# The action under test is the ./cpp-linter-action submodule, pinned on this +# branch to the head of cpp-linter-action's feature/auto-fix. # # Workflows added by a pull request do run for `pull_request` events, so this # file takes effect from the PR branch itself. @@ -27,7 +26,6 @@ permissions: pull-requests: write env: - ACTION_DIR: .action-under-test TEST_FILE: src/e2e_autofix_pr_demo.cpp CLANG_VERSION: '18' COMMIT_MSG: 'style: apply clang-format fixes' @@ -59,10 +57,6 @@ jobs: echo "MALFORMED_BLOB=$(git hash-object "$TEST_FILE")" echo "PR_HEAD_SHA=${{ github.event.pull_request.head.sha }}" } >> "$GITHUB_ENV" - if [ "$(git rev-parse HEAD)" != "${{ github.event.pull_request.head.sha }}" ]; then - echo "::error title=Wrong checkout::HEAD is not the PR head commit; the ref input on actions/checkout is missing." - exit 1 - fi # Baseline: the same lint, with auto-fix off. This measures what # clang-tidy reports against the file as the diff describes it, and is @@ -72,7 +66,7 @@ jobs: # and src/demo.hpp are intentionally unformatted fixtures of this repo, and # scanning everything would make auto-fix "repair" and commit them too. - name: Lint without auto-fix (baseline) - uses: $/cpp-linter-action + uses: ./cpp-linter-action id: baseline env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -82,7 +76,7 @@ jobs: extra-args: '-std=c++17' files-changed-only: true lines-changed-only: true - ignore: build|.action-under-test + ignore: build version: '18' verbosity: debug thread-comments: false @@ -100,7 +94,7 @@ jobs: # The real run. Same inputs, auto-fix on. - name: Run cpp-linter with auto-fix - uses: $/cpp-linter-action + uses: ./cpp-linter-action id: linter env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -110,7 +104,7 @@ jobs: extra-args: '-std=c++17' files-changed-only: true lines-changed-only: true - ignore: build|.action-under-test + ignore: build version: '18' verbosity: debug thread-comments: false diff --git a/cpp-linter-action b/cpp-linter-action index 894a549..8feb22c 160000 --- a/cpp-linter-action +++ b/cpp-linter-action @@ -1 +1 @@ -Subproject commit 894a54988abed9f2c7a37f5b54694e819de7f462 +Subproject commit 8feb22c6fc72acab3a7ec79d71b67727ac1f6e7e From 36b8e60b6d9d7530d9efec8e67e3b601101eda16 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Fri, 18 Sep 2026 10:23:48 +0300 Subject: [PATCH 14/15] test: cover the action's own checkout of the PR head Point the submodule at cpp-linter-action b4e1034, where the action switches from the default merge-commit checkout to the PR head itself. Malform the fixture again so there is something to fix, assert that the run starts on the merge commit, and that the full clone is not turned into a shallow one. --- .github/workflows/auto-fix-pr-e2e.yml | 15 +++++++++++++++ cpp-linter-action | 2 +- src/e2e_autofix_pr_demo.cpp | 22 +++------------------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.github/workflows/auto-fix-pr-e2e.yml b/.github/workflows/auto-fix-pr-e2e.yml index a9faf95..8fefada 100644 --- a/.github/workflows/auto-fix-pr-e2e.yml +++ b/.github/workflows/auto-fix-pr-e2e.yml @@ -53,6 +53,13 @@ jobs: echo "::group::fixture before" cat -n "$TEST_FILE" echo "::endgroup::" + # This run has to start from the default checkout (the merge commit), + # otherwise it would not cover the action's own checkout of the PR head. + echo "HEAD=$(git rev-parse HEAD) PR head=${{ github.event.pull_request.head.sha }}" + if [ "$(git rev-parse HEAD)" = "${{ github.event.pull_request.head.sha }}" ]; then + echo "::error title=Not the default checkout::HEAD is already the PR head." + exit 1 + fi { echo "MALFORMED_BLOB=$(git hash-object "$TEST_FILE")" echo "PR_HEAD_SHA=${{ github.event.pull_request.head.sha }}" @@ -259,6 +266,14 @@ jobs: echo "PASS: src/demo.cpp and src/demo.hpp were left untouched" fi + # The checkout above is a full clone; the action must leave it that way. + if [ "$(git rev-parse --is-shallow-repository)" != "false" ]; then + echo "::error title=History truncated::the action turned the full clone into a shallow one." + failed=1 + else + echo "PASS: the full clone was left intact" + fi + # The fix has to be on the PR branch at the remote, not just locally. git fetch -q origin "$head_ref" if [ "$(git rev-parse FETCH_HEAD)" != "$head_sha" ]; then diff --git a/cpp-linter-action b/cpp-linter-action index 8feb22c..b4e1034 160000 --- a/cpp-linter-action +++ b/cpp-linter-action @@ -1 +1 @@ -Subproject commit 8feb22c6fc72acab3a7ec79d71b67727ac1f6e7e +Subproject commit b4e10340931c7cb5cc62f265af1ee37b09c1433e diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 874fb59..7d0cbdd 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,24 +5,8 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate() -{ - int a = 10; - int b = 20; - int c = 30; - int d = 40; - int e = 50; - return a + b + c + d + e; -} +int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} -int magic_user() -{ - int v = 42; - return v; -} +int magic_user( ){int v=42;return v;} -int* null_user() -{ - int* p = 0; - return p; -} +int * null_user( ){int * p=0;return p;} From 0bd02c7d133334bc9a1c1c2921440afbf8654483 Mon Sep 17 00:00:00 2001 From: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com> Date: Fri, 18 Sep 2026 07:24:25 +0000 Subject: [PATCH 15/15] style: apply clang-format fixes --- src/e2e_autofix_pr_demo.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/e2e_autofix_pr_demo.cpp b/src/e2e_autofix_pr_demo.cpp index 7d0cbdd..874fb59 100644 --- a/src/e2e_autofix_pr_demo.cpp +++ b/src/e2e_autofix_pr_demo.cpp @@ -5,8 +5,24 @@ // 2. Formatting it changes its line count (the one-liners below expand), // which is what makes it able to catch clang-tidy diagnostics drifting // off the diff when the tools run in the wrong order. -int accumulate( ){int a=10;int b=20;int c=30;int d=40;int e=50;return a+b+c+d+e;} +int accumulate() +{ + int a = 10; + int b = 20; + int c = 30; + int d = 40; + int e = 50; + return a + b + c + d + e; +} -int magic_user( ){int v=42;return v;} +int magic_user() +{ + int v = 42; + return v; +} -int * null_user( ){int * p=0;return p;} +int* null_user() +{ + int* p = 0; + return p; +}