From c45a7b473f581804e943e871fd81ad6a378e49d4 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:09:54 -0500 Subject: [PATCH] feat: add clang-format config and formatting workflows Co-Authored-By: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> #163 got deleted. --- .clang-format | 2 + .github/scripts/check-clang-format.sh | 34 ++++++++++++ .github/scripts/run-clang-format-all.sh | 32 ++++++++++++ .github/workflows/clang-format-all.yml | 69 +++++++++++++++++++++++++ .github/workflows/clang-format.yml | 69 +++++++++++++++++++++++++ CONTRIBUTING.md | 4 +- 6 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 .clang-format create mode 100644 .github/scripts/check-clang-format.sh create mode 100644 .github/scripts/run-clang-format-all.sh create mode 100644 .github/workflows/clang-format-all.yml create mode 100644 .github/workflows/clang-format.yml diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..25ed9323e --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: Google +IndentWidth: 4 \ No newline at end of file diff --git a/.github/scripts/check-clang-format.sh b/.github/scripts/check-clang-format.sh new file mode 100644 index 000000000..3efb79fe5 --- /dev/null +++ b/.github/scripts/check-clang-format.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -euo pipefail + +formatter="${CLANG_FORMAT_BIN:-clang-format-19}" +base_ref="${1:-}" +head_ref="${2:-HEAD}" + +if [[ -z "$base_ref" ]]; then + if git rev-parse --verify HEAD^ >/dev/null 2>&1; then + base_ref="$(git rev-parse HEAD^)" + else + echo "No comparison base available; skipping clang-format check." + exit 0 + fi +fi + +diff_output="$( + git diff --name-only --diff-filter=ACMR "$base_ref" "$head_ref" -- \ + '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.inl' +)" + +if [[ -z "$diff_output" ]]; then + echo "No changed C/C++ files to check." + exit 0 +fi + +mapfile -t files <<<"$diff_output" + +echo "Checking formatting for changed files:" +printf ' %s\n' "${files[@]}" + +"$formatter" --version +"$formatter" --dry-run --Werror "${files[@]}" \ No newline at end of file diff --git a/.github/scripts/run-clang-format-all.sh b/.github/scripts/run-clang-format-all.sh new file mode 100644 index 000000000..4fcf8543a --- /dev/null +++ b/.github/scripts/run-clang-format-all.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -euo pipefail + +formatter="${CLANG_FORMAT_BIN:-clang-format-19}" +mode="${1:-apply}" + +mapfile -d '' -t files < <( + git ls-files -z -- \ + '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.inl' +) + +if [[ "${#files[@]}" -eq 0 ]]; then + echo "No tracked C/C++ files found." + exit 0 +fi + +echo "Found ${#files[@]} tracked C/C++ files." +"$formatter" --version + +case "$mode" in + apply) + printf '%s\0' "${files[@]}" | xargs -0 -r -n 100 "$formatter" -i + ;; + check) + printf '%s\0' "${files[@]}" | xargs -0 -r -n 100 "$formatter" --dry-run --Werror + ;; + *) + echo "Unknown mode: $mode" >&2 + exit 1 + ;; +esac \ No newline at end of file diff --git a/.github/workflows/clang-format-all.yml b/.github/workflows/clang-format-all.yml new file mode 100644 index 000000000..3cb2b65ba --- /dev/null +++ b/.github/workflows/clang-format-all.yml @@ -0,0 +1,69 @@ +name: Clang Format All + +on: + workflow_dispatch: + inputs: + commit_changes: + description: Commit formatted changes back to the selected branch + required: true + default: false + type: boolean + +permissions: + contents: write + +jobs: + clang-format-all: + runs-on: ubuntu-24.04 + concurrency: + group: clang-format-all-${{ github.ref }} + cancel-in-progress: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: Install clang-format + run: | + sudo apt-get update + sudo apt-get install -y clang-format-19 + + - name: Format tracked C/C++ files + env: + CLANG_FORMAT_BIN: clang-format-19 + run: | + bash ./.github/scripts/run-clang-format-all.sh apply + + - name: Export patch + id: patch + run: | + if git diff --quiet; then + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + git diff --binary > clang-format-all.patch + echo "changed=true" >> "$GITHUB_OUTPUT" + + - name: Upload patch artifact + if: steps.patch.outputs.changed == 'true' + uses: actions/upload-artifact@v4 + with: + name: clang-format-all-${{ github.sha }} + path: clang-format-all.patch + retention-days: 7 + + - name: Commit formatted changes + if: steps.patch.outputs.changed == 'true' && github.event.inputs.commit_changes == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "Run clang-format over tracked sources" + git push origin HEAD:${GITHUB_REF_NAME} + + - name: Report no-op run + if: steps.patch.outputs.changed == 'false' + run: echo "clang-format produced no changes." \ No newline at end of file diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 000000000..a125848e6 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,69 @@ +name: Clang Format + +on: + push: + paths: + - '**.cpp' + - '**.h' + - '**.c' + - '**.cc' + - '**.cxx' + - '**.hh' + - '**.hpp' + - '**.hxx' + - '**.inl' + - '.clang-format' + - '.github/workflows/clang-format.yml' + - '.github/scripts/check-clang-format.sh' + pull_request: + paths: + - '**.cpp' + - '**.h' + - '**.c' + - '**.cc' + - '**.cxx' + - '**.hh' + - '**.hpp' + - '**.hxx' + - '**.inl' + - '.clang-format' + - '.github/workflows/clang-format.yml' + - '.github/scripts/check-clang-format.sh' + +jobs: + clang-format: + runs-on: ubuntu-24.04 + concurrency: + group: clang-format-${{ github.ref }} + cancel-in-progress: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install clang-format + run: | + sudo apt-get update + sudo apt-get install -y clang-format-19 + + - name: Check changed files + env: + CLANG_FORMAT_BIN: clang-format-19 + EVENT_NAME: ${{ github.event_name }} + PR_BASE_REF: ${{ github.event.pull_request.base.ref }} + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + BEFORE_SHA: ${{ github.event.before }} + CURRENT_SHA: ${{ github.sha }} + run: | + set -euo pipefail + + BASE_SHA="" + if [ "$EVENT_NAME" = "pull_request" ]; then + git fetch --no-tags origin "$PR_BASE_REF" --depth=1 + BASE_SHA="$(git merge-base "origin/$PR_BASE_REF" "$CURRENT_SHA")" + elif [ -n "$BEFORE_SHA" ] && [ "$BEFORE_SHA" != "0000000000000000000000000000000000000000" ]; then + BASE_SHA="$BEFORE_SHA" + fi + + bash ./.github/scripts/check-clang-format.sh "$BASE_SHA" "$CURRENT_SHA" \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f6de058d..7c2dcf001 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,9 @@ Commit names should clearly describe what was changed in the commit. [Convention ### Keep code clean and readable. -At this time, we do not have a style guide or rules for how code should be formatted. In general, code should be readable and try to match the styling and conventions of whatever is around it. +Code formatting is defined by the repository's [`.clang-format`](./.clang-format) file. If you are touching C or C++ source, format the files you changed before opening or updating a pull request. + +CI checks formatting on changed C and C++ files, so local formatting mismatches will fail the relevant workflow. ### Avoid changing in-game behavior.