From b29742f7af2502246cac12afba196e2749b488ad Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 17:51:06 +0100 Subject: [PATCH 01/12] Suggest changes instead of automatically fixing them --- .github/workflows/format.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 85a91e23..5678ecfc 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -11,7 +11,8 @@ jobs: format: runs-on: ubuntu-latest permissions: - contents: write + contents: read + pull-requests: write steps: - name: Checkout code @@ -37,12 +38,24 @@ jobs: - name: Apply C++ formatting fixes run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i + - name: Suggest C++ formatting fixes + if: github.event_name == 'pull_request' + uses: reviewdog/action-suggester@v1 + with: + tool_name: clang-format + - name: Apply Rust lint fixes run: | cargo clippy --fix --allow-dirty --manifest-path rules/Cargo.toml --all-targets cargo +nightly clippy --fix --allow-dirty --manifest-path rule-preprocessor/Cargo.toml --all-targets cargo clippy --fix --allow-dirty --manifest-path libcc2rs/Cargo.toml --all-targets + - name: Suggest Rust lint fixes + if: github.event_name == 'pull_request' + uses: reviewdog/action-suggester@v1 + with: + tool_name: clippy + - name: Apply Rust formatting fixes run: | cargo fmt --manifest-path rules/Cargo.toml @@ -50,11 +63,11 @@ jobs: cargo fmt --manifest-path libcc2rs/Cargo.toml find tests -name '*.rs' -print0 | xargs -0 rustfmt - - name: Commit auto-fixes - if: github.ref != 'refs/heads/master' - uses: stefanzweifel/git-auto-commit-action@v5 + - name: Suggest Rust formatting fixes + if: github.event_name == 'pull_request' + uses: reviewdog/action-suggester@v1 with: - commit_message: "Automatically apply formatting and lint fixes" + tool_name: rustfmt - name: Check C++ formatting run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format --dry-run --Werror From d3865b128cbf3560eb758a6af314a813bc507245 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 17:52:16 +0100 Subject: [PATCH 02/12] Intentionally break formatting --- cpp2rust/converter/converter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 359210aa..18062284 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include +#include #include "compiler.h" #include "converter/converter_lib.h" From 8125d3d1bc094af800dc90b0fa8693f9f3c34514 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:18:56 +0100 Subject: [PATCH 03/12] Split auto-fixing in 2 workflows format.yml, which runs on pull_request, does not have write access to neither base nor fork repos. To fix this, split auto-fixing in 2 steps: first format.yml publishes an artifact with the diff, then format-apply.yml fetches the artifact and commits the auto-fixes. This works because format-applt.yml runs on workflow_run, not pull_request, and has write permissions. --- .github/workflows/format-apply.yml | 42 ++++++++++++++++++++++++++++++ .github/workflows/format.yml | 39 +++++++++++++++------------ 2 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/format-apply.yml diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml new file mode 100644 index 00000000..66e39476 --- /dev/null +++ b/.github/workflows/format-apply.yml @@ -0,0 +1,42 @@ +name: Format Apply + +on: + workflow_run: + workflows: ["Format Check"] + types: [completed] + +jobs: + apply: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + permissions: + contents: read + + steps: + - name: Download diff artifact + uses: actions/download-artifact@v4 + with: + name: format-diff + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Read PR head + id: head + run: | + echo "repo=$(cat head-repo.txt)" >> "$GITHUB_OUTPUT" + echo "branch=$(cat head-branch.txt)" >> "$GITHUB_OUTPUT" + + - name: Checkout PR head + uses: actions/checkout@v6 + with: + repository: ${{ steps.head.outputs.repo }} + ref: ${{ steps.head.outputs.branch }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Apply diff + run: git apply $GITHUB_WORKSPACE/../format.diff + + - name: Commit and push + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Automatically apply formatting and lint fixes" diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 5678ecfc..81a790c5 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -12,13 +12,12 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - pull-requests: write steps: - name: Checkout code uses: actions/checkout@v6 - - name: Setup LLVM 22 + - name: Setup LLVM uses: ZhongRuoyu/setup-llvm@v0 with: llvm-version: 22 @@ -38,24 +37,12 @@ jobs: - name: Apply C++ formatting fixes run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i - - name: Suggest C++ formatting fixes - if: github.event_name == 'pull_request' - uses: reviewdog/action-suggester@v1 - with: - tool_name: clang-format - - name: Apply Rust lint fixes run: | cargo clippy --fix --allow-dirty --manifest-path rules/Cargo.toml --all-targets cargo +nightly clippy --fix --allow-dirty --manifest-path rule-preprocessor/Cargo.toml --all-targets cargo clippy --fix --allow-dirty --manifest-path libcc2rs/Cargo.toml --all-targets - - name: Suggest Rust lint fixes - if: github.event_name == 'pull_request' - uses: reviewdog/action-suggester@v1 - with: - tool_name: clippy - - name: Apply Rust formatting fixes run: | cargo fmt --manifest-path rules/Cargo.toml @@ -63,11 +50,29 @@ jobs: cargo fmt --manifest-path libcc2rs/Cargo.toml find tests -name '*.rs' -print0 | xargs -0 rustfmt - - name: Suggest Rust formatting fixes + - name: Capture diff for later auto-commit + id: diff if: github.event_name == 'pull_request' - uses: reviewdog/action-suggester@v1 + run: | + git diff > /tmp/format.diff + echo "${{ github.event.pull_request.head.repo.full_name }}" > /tmp/head-repo.txt + echo "${{ github.event.pull_request.head.ref }}" > /tmp/head-branch.txt + if [ -s /tmp/format.diff ]; then + echo "has_diff=true" >> "$GITHUB_OUTPUT" + else + echo "has_diff=false" >> "$GITHUB_OUTPUT" + fi + + - name: Upload diff artifact + if: github.event_name == 'pull_request' && steps.diff.outputs.has_diff == 'true' + uses: actions/upload-artifact@v4 with: - tool_name: rustfmt + name: format-diff + path: | + /tmp/format.diff + /tmp/head-repo.txt + /tmp/head-branch.txt + retention-days: 1 - name: Check C++ formatting run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format --dry-run --Werror From 560875d9b51161c1cd95b0da4f9794b1b38cfe58 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:32:40 +0100 Subject: [PATCH 04/12] Fix paths --- .github/workflows/format-apply.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index 66e39476..88bbd7d6 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -19,12 +19,13 @@ jobs: name: format-diff run-id: ${{ github.event.workflow_run.id }} github-token: ${{ secrets.GITHUB_TOKEN }} + path: ${{ runner.temp }}/format-diff - name: Read PR head id: head run: | - echo "repo=$(cat head-repo.txt)" >> "$GITHUB_OUTPUT" - echo "branch=$(cat head-branch.txt)" >> "$GITHUB_OUTPUT" + echo "repo=$(cat ${{ runner.temp }}/format-diff/head-repo.txt)" >> "$GITHUB_OUTPUT" + echo "branch=$(cat ${{ runner.temp }}/format-diff/head-branch.txt)" >> "$GITHUB_OUTPUT" - name: Checkout PR head uses: actions/checkout@v6 @@ -34,7 +35,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Apply diff - run: git apply $GITHUB_WORKSPACE/../format.diff + run: git apply ${{ runner.temp }}/format-diff/format.diff - name: Commit and push uses: stefanzweifel/git-auto-commit-action@v5 From 2af5a4435c04ecf4cf7c371002b9a84dec8159c2 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:37:01 +0100 Subject: [PATCH 05/12] Add write permissions --- .github/workflows/format-apply.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index 88bbd7d6..5b7ceb71 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: github.event.workflow_run.event == 'pull_request' permissions: - contents: read + contents: write steps: - name: Download diff artifact From 4dc38f26807604874da35ba723ff34c5c02237da Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:48:50 +0100 Subject: [PATCH 06/12] Try suggester in 2-workflows setup --- .github/workflows/format-apply.yml | 32 +++++++++++++++++------------- .github/workflows/format.yml | 10 +++++----- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index 5b7ceb71..9854ee19 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -6,11 +6,12 @@ on: types: [completed] jobs: - apply: + suggest: runs-on: ubuntu-latest if: github.event.workflow_run.event == 'pull_request' permissions: - contents: write + contents: read + pull-requests: write steps: - name: Download diff artifact @@ -21,23 +22,26 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} path: ${{ runner.temp }}/format-diff - - name: Read PR head - id: head + - name: Read PR metadata + id: meta run: | - echo "repo=$(cat ${{ runner.temp }}/format-diff/head-repo.txt)" >> "$GITHUB_OUTPUT" - echo "branch=$(cat ${{ runner.temp }}/format-diff/head-branch.txt)" >> "$GITHUB_OUTPUT" + echo "number=$(cat ${{ runner.temp }}/format-diff/pr-number.txt)" >> "$GITHUB_OUTPUT" + echo "sha=$(cat ${{ runner.temp }}/format-diff/head-sha.txt)" >> "$GITHUB_OUTPUT" - - name: Checkout PR head + - name: Checkout base repo at PR head uses: actions/checkout@v6 with: - repository: ${{ steps.head.outputs.repo }} - ref: ${{ steps.head.outputs.branch }} - token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ steps.meta.outputs.sha }} - - name: Apply diff + - name: Replay diff in working tree run: git apply ${{ runner.temp }}/format-diff/format.diff - - name: Commit and push - uses: stefanzweifel/git-auto-commit-action@v5 + - name: Post suggestions + uses: reviewdog/action-suggester@v1 + env: + CI_PULL_REQUEST: ${{ steps.meta.outputs.number }} + CI_COMMIT: ${{ steps.meta.outputs.sha }} + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - commit_message: "Automatically apply formatting and lint fixes" + tool_name: format + filter_mode: nofilter diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 81a790c5..0b7d0d12 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -50,13 +50,13 @@ jobs: cargo fmt --manifest-path libcc2rs/Cargo.toml find tests -name '*.rs' -print0 | xargs -0 rustfmt - - name: Capture diff for later auto-commit + - name: Capture diff for later suggestion posting id: diff if: github.event_name == 'pull_request' run: | git diff > /tmp/format.diff - echo "${{ github.event.pull_request.head.repo.full_name }}" > /tmp/head-repo.txt - echo "${{ github.event.pull_request.head.ref }}" > /tmp/head-branch.txt + echo "${{ github.event.pull_request.number }}" > /tmp/pr-number.txt + echo "${{ github.event.pull_request.head.sha }}" > /tmp/head-sha.txt if [ -s /tmp/format.diff ]; then echo "has_diff=true" >> "$GITHUB_OUTPUT" else @@ -70,8 +70,8 @@ jobs: name: format-diff path: | /tmp/format.diff - /tmp/head-repo.txt - /tmp/head-branch.txt + /tmp/pr-number.txt + /tmp/head-sha.txt retention-days: 1 - name: Check C++ formatting From af0466171862c8be49efae50be20f72e6657fa05 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:54:00 +0100 Subject: [PATCH 07/12] Fabricate a pull_request event for reviewdog --- .github/workflows/format-apply.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index 9854ee19..49538523 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -36,11 +36,23 @@ jobs: - name: Replay diff in working tree run: git apply ${{ runner.temp }}/format-diff/format.diff + - name: Fabricate a pull_request event for reviewdog + run: | + cat > ${{ runner.temp }}/pr-event.json <> $GITHUB_ENV + echo "GITHUB_EVENT_PATH=${{ runner.temp }}/pr-event.json" >> $GITHUB_ENV + - name: Post suggestions uses: reviewdog/action-suggester@v1 env: - CI_PULL_REQUEST: ${{ steps.meta.outputs.number }} - CI_COMMIT: ${{ steps.meta.outputs.sha }} REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tool_name: format From ba1a56dcd8c91aae19f16bf92f8c784ac0c8b63c Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 19:07:37 +0100 Subject: [PATCH 08/12] Overwrite the runner's event file with the PR event --- .github/workflows/format-apply.yml | 21 +++++---------------- .github/workflows/format.yml | 6 ++---- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index 49538523..a5001ad4 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -22,11 +22,11 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} path: ${{ runner.temp }}/format-diff - - name: Read PR metadata + - name: Extract head SHA from event id: meta run: | - echo "number=$(cat ${{ runner.temp }}/format-diff/pr-number.txt)" >> "$GITHUB_OUTPUT" - echo "sha=$(cat ${{ runner.temp }}/format-diff/head-sha.txt)" >> "$GITHUB_OUTPUT" + sha=$(jq -r '.pull_request.head.sha' ${{ runner.temp }}/format-diff/pr-event.json) + echo "sha=$sha" >> "$GITHUB_OUTPUT" - name: Checkout base repo at PR head uses: actions/checkout@v6 @@ -36,19 +36,8 @@ jobs: - name: Replay diff in working tree run: git apply ${{ runner.temp }}/format-diff/format.diff - - name: Fabricate a pull_request event for reviewdog - run: | - cat > ${{ runner.temp }}/pr-event.json <> $GITHUB_ENV - echo "GITHUB_EVENT_PATH=${{ runner.temp }}/pr-event.json" >> $GITHUB_ENV + - name: Overwrite the runner's event file with the PR event + run: cp ${{ runner.temp }}/format-diff/pr-event.json "$GITHUB_EVENT_PATH" - name: Post suggestions uses: reviewdog/action-suggester@v1 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 0b7d0d12..aae73a54 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -55,8 +55,7 @@ jobs: if: github.event_name == 'pull_request' run: | git diff > /tmp/format.diff - echo "${{ github.event.pull_request.number }}" > /tmp/pr-number.txt - echo "${{ github.event.pull_request.head.sha }}" > /tmp/head-sha.txt + cp "$GITHUB_EVENT_PATH" /tmp/pr-event.json if [ -s /tmp/format.diff ]; then echo "has_diff=true" >> "$GITHUB_OUTPUT" else @@ -70,8 +69,7 @@ jobs: name: format-diff path: | /tmp/format.diff - /tmp/pr-number.txt - /tmp/head-sha.txt + /tmp/pr-event.json retention-days: 1 - name: Check C++ formatting From 39cf8e57995196e96a230d41f165b21763407977 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 20:42:36 +0100 Subject: [PATCH 09/12] Manually post suggestions --- .github/workflows/format-apply.yml | 87 +++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml index a5001ad4..aea5dd68 100644 --- a/.github/workflows/format-apply.yml +++ b/.github/workflows/format-apply.yml @@ -22,27 +22,78 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} path: ${{ runner.temp }}/format-diff - - name: Extract head SHA from event + - name: Read PR metadata id: meta run: | - sha=$(jq -r '.pull_request.head.sha' ${{ runner.temp }}/format-diff/pr-event.json) - echo "sha=$sha" >> "$GITHUB_OUTPUT" + echo "number=$(jq -r '.pull_request.number' ${{ runner.temp }}/format-diff/pr-event.json)" >> "$GITHUB_OUTPUT" + echo "sha=$(jq -r '.pull_request.head.sha' ${{ runner.temp }}/format-diff/pr-event.json)" >> "$GITHUB_OUTPUT" - - name: Checkout base repo at PR head - uses: actions/checkout@v6 - with: - ref: ${{ steps.meta.outputs.sha }} + - name: Post suggestion comments + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DIFF_FILE: ${{ runner.temp }}/format-diff/format.diff + PR: ${{ steps.meta.outputs.number }} + REPO: ${{ github.repository }} + COMMIT: ${{ steps.meta.outputs.sha }} + run: | + python3 <<'PY' + import json, os, re, subprocess, sys - - name: Replay diff in working tree - run: git apply ${{ runner.temp }}/format-diff/format.diff + with open(os.environ["DIFF_FILE"]) as f: + lines = f.read().splitlines() - - name: Overwrite the runner's event file with the PR event - run: cp ${{ runner.temp }}/format-diff/pr-event.json "$GITHUB_EVENT_PATH" + repo = os.environ["REPO"] + pr = os.environ["PR"] + commit = os.environ["COMMIT"] + endpoint = f"/repos/{repo}/pulls/{pr}/comments" - - name: Post suggestions - uses: reviewdog/action-suggester@v1 - env: - REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tool_name: format - filter_mode: nofilter + def post(comment): + r = subprocess.run( + ["gh", "api", endpoint, "-X", "POST", "--input", "-"], + input=json.dumps(comment), text=True, capture_output=True, + ) + if r.returncode != 0: + print(f"skip ({r.stderr.strip()})", file=sys.stderr) + + path = None + i = 0 + posted = 0 + while i < len(lines): + line = lines[i] + if line.startswith("+++ b/"): + path = line[6:] + i += 1 + elif line.startswith("@@"): + m = re.match(r"@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@", line) + if not m: + i += 1; continue + old_start = int(m.group(1)) + old_count = int(m.group(2) or "1") + end_line = old_start + old_count - 1 + new_content = [] + i += 1 + while i < len(lines) and not lines[i].startswith("@@") and not lines[i].startswith("diff "): + l = lines[i] + if l.startswith("+") and not l.startswith("+++"): + new_content.append(l[1:]) + elif l.startswith(" "): + new_content.append(l[1:]) + i += 1 + body = "```suggestion\n" + "\n".join(new_content) + "\n```" + comment = { + "body": body, + "commit_id": commit, + "path": path, + "line": end_line, + "side": "RIGHT", + } + if end_line > old_start: + comment["start_line"] = old_start + comment["start_side"] = "RIGHT" + post(comment) + posted += 1 + else: + i += 1 + + print(f"attempted {posted} suggestion comment(s)") + PY From 3b5cb442276b093afca414cd41a6b23afaec0908 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 21:17:36 +0100 Subject: [PATCH 10/12] Revert "Intentionally break formatting" This reverts commit d3865b128cbf3560eb758a6af314a813bc507245. --- cpp2rust/converter/converter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 18062284..359210aa 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -6,10 +6,10 @@ #include #include #include +#include #include #include -#include #include "compiler.h" #include "converter/converter_lib.h" From efe31bacffb24763962b66248ad85034d273ad21 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 18:28:08 +0100 Subject: [PATCH 11/12] Trigger CI From abf1ef2cc0aa29a2ba39ae771d4eb3a716cdbe2c Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 22 Apr 2026 21:18:36 +0100 Subject: [PATCH 12/12] Break formatting --- cpp2rust/converter/converter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 359210aa..18062284 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include +#include #include "compiler.h" #include "converter/converter_lib.h"