Skip to content

add format-check cirrus workflow and pre-commit hooks.#903

Merged
gaoxueyu merged 1 commit intoIvorySQL:masterfrom
NotHimmel:master
Sep 30, 2025
Merged

add format-check cirrus workflow and pre-commit hooks.#903
gaoxueyu merged 1 commit intoIvorySQL:masterfrom
NotHimmel:master

Conversation

@NotHimmel
Copy link
Copy Markdown
Collaborator

@NotHimmel NotHimmel commented Sep 29, 2025

Summary by CodeRabbit

  • New Features

    • Added a pre-commit hook that auto-formats staged C/C++ files and blocks commits if formatting fails.
    • Added a make target and helper script to enable and install developer Git hooks and ensure formatter availability.
  • Chores

    • Added a PR-only CI job that checks formatting on changed C/C++ files and emits suggested patches on failures.
  • Documentation

    • Updated contributor and project READMEs (including Chinese) with hook and CI formatting workflow details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 29, 2025

Walkthrough

Adds PR-only CI formatting checks via Cirrus, introduces a pre-commit hook to auto-format staged C/C++ files with pgindent, provides a helper script and Makefile target to enable hooks, and updates English and Chinese docs describing the formatting workflow. No runtime code paths or public APIs are changed.

Changes

Cohort / File(s) Summary of changes
CI: PR-only format check
​.cirrus.format.yml, ​.cirrus.star
Adds a Cirrus PR-only FormatCheck workflow that builds pg_bsd_indent in a Debian container, detects changed .c/.h/.cpp/.hpp files (excluding the formatter sources), and runs pgindent --check (emits --diff on failure). Updates .cirrus.star to load the new PR config.
Git hooks and tooling
​.githooks/pre-commit, tools/enable-git-hooks.sh, Makefile
Adds a pre-commit hook to format staged C/C++ files with pgindent, re-stage them, and verify formatting; provides tools/enable-git-hooks.sh to set core.hooksPath and build pg_bsd_indent; adds .PHONY: enable-git-hooks and the enable-git-hooks target.
Documentation
CONTRIBUTING.md, README.md, README_CN.md
Documents developer formatting hooks, how to enable them, local commit-time formatting behavior, and the Cirrus PR FormatCheck workflow (English and Chinese updates).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant Git as Git (pre-commit)
  participant Hook as Pre-commit Hook
  participant Build as Build (Meson/Ninja)
  participant Indent as pg_bsd_indent
  participant PGI as pgindent
  participant Repo as Repo Index

  Dev->>Git: git commit
  Git->>Hook: invoke .githooks/pre-commit
  alt PG_NO_FORMAT=1
    Hook-->>Git: exit 0 (skip)
  else Format C/C++
    Hook->>Build: ensure pg_bsd_indent built
    Build->>Indent: build/check executable
    Hook->>PGI: format staged C/C++ (PGINDENT/PGTYPEDEFS)
    PGI-->>Hook: exit code
    Hook->>Repo: git add re-formatted files
    Hook->>PGI: pgindent --check on staged files
    alt Unformatted remains
      Hook-->>Git: exit non-zero (block commit)
    else Clean
      Hook-->>Git: exit 0 (allow commit)
    end
  end
Loading
sequenceDiagram
  autonumber
  actor PR as PR Event
  participant Cirrus as Cirrus CI
  participant Ctn as Debian Container
  participant Build as Meson/Ninja
  participant Indent as pg_bsd_indent
  participant PGI as pgindent
  participant Git as Git (BASE..HEAD)

  PR->>Cirrus: triggers PR-only workflow
  Cirrus->>Ctn: start container, install deps
  Ctn->>Build: configure minimal Meson
  Build->>Indent: build pg_bsd_indent
  Ctn->>Git: compute changed .c/.h/.cpp/.hpp (exclude formatter dir)
  alt No relevant changes
    Ctn-->>Cirrus: skip job (Passed)
  else Files present
    Ctn->>PGI: pgindent --check on changed files
    alt Differences found
      Ctn->>PGI: pgindent --diff (emit patch)
      Ctn-->>Cirrus: fail with non-zero
    else Clean
      Ctn-->>Cirrus: print "Passed"
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Add readme_cn #762 — Overlapping documentation changes to README_CN.md and README.md, likely related to the same docs updates.

Poem

A bunny taps commit with gentle might,
Hooks hop in, nibbling whitespace right.
CI carrots guard the PR trail,
pgindent hums its tidy tale.
Burrows neat, our code sleeps tight. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title accurately and succinctly describes the primary changes in this diff, namely the addition of a Cirrus format-check workflow and related pre-commit hooks, aligning with the new CI configuration and hook scripts introduced in the branch.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tools/enable-git-hooks.sh (1)

27-28: Quote the nproc expansion to keep ShellCheck happy.

ShellCheck is right that the command substitution should be quoted so the -j flag always receives a single argument. It also silences SC2046 for future runs.

-  if ! make -C src/tools/pg_bsd_indent -j$(nproc 2>/dev/null || echo 2) >/dev/null; then
+  if ! make -C src/tools/pg_bsd_indent -j"$(nproc 2>/dev/null || echo 2)" >/dev/null; then
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9c7975 and 769884a.

📒 Files selected for processing (7)
  • .cirrus.format.yml (1 hunks)
  • .cirrus.star (1 hunks)
  • .githooks/pre-commit (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Makefile (1 hunks)
  • README_CN.md (1 hunks)
  • tools/enable-git-hooks.sh (1 hunks)
🧰 Additional context used
🪛 checkmake (0.2.2)
Makefile

[warning] 48-48: Missing required phony target "all"

(minphony)


[warning] 48-48: Missing required phony target "clean"

(minphony)


[warning] 48-48: Missing required phony target "test"

(minphony)

🪛 Shellcheck (0.11.0)
tools/enable-git-hooks.sh

[warning] 27-27: Quote this to prevent word splitting.

(SC2046)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: pg_regression (ubuntu-latest)
  • GitHub Check: oracle_pg_regression (ubuntu-latest)
  • GitHub Check: oracle_regression (ubuntu-latest)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: contrib_regression
  • GitHub Check: meson_build (ubuntu-latest)

Comment thread .cirrus.star
Comment on lines +42 to +45
# output += config_from(".cirrus.tasks.yml")

# PR-only format check
output += config_from(".cirrus.format.yml")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Re-include .cirrus.tasks.yml or the rest of CI stops running.

By commenting out config_from(".cirrus.tasks.yml") you no longer append the repository’s main Cirrus task matrix (Linux/Windows/BSD/macOS builds, tests, etc.). Those hundreds of lines in .cirrus.tasks.yml now never get loaded, so every push/PR loses its full regression coverage.(github.com)

Please keep the existing tasks and add the new format check alongside them, e.g.:

-    # output += config_from(".cirrus.tasks.yml")
-
-    # PR-only format check
-    output += config_from(".cirrus.format.yml")
+    output += config_from(".cirrus.tasks.yml")
+
+    # PR-only format check
+    output += config_from(".cirrus.format.yml")

Otherwise the formatting job becomes the only Cirrus workload, which is a severe regression in our CI gate.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# output += config_from(".cirrus.tasks.yml")
# PR-only format check
output += config_from(".cirrus.format.yml")
output += config_from(".cirrus.tasks.yml")
# PR-only format check
output += config_from(".cirrus.format.yml")
🤖 Prompt for AI Agents
.cirrus.star around lines 42 to 45: restore the call to
config_from(".cirrus.tasks.yml") (remove the comment) so the repository’s main
task matrix is loaded, and then append the PR-only format check by keeping
output += config_from(".cirrus.format.yml") so both the full CI tasks and the
new formatting job run; ensure the tasks file is loaded before or alongside the
format config and do not replace the tasks call with the format call.

Comment thread .githooks/pre-commit
Comment on lines +15 to +18
mapfile -t files < <(\
git diff --cached --name-only --diff-filter=ACMR | \
grep -E '\.(c|h|cpp|hpp)$' | \
grep -vE '^src/tools/pg_bsd_indent/' || true)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Restore Bash 3.2 compatibility so the hook runs on macOS.

mapfile/readarray only exist in Bash 4+, but macOS still ships /bin/bash 3.2.57 by default. With your shebang resolving to that shell, the hook aborts entirely for every macOS contributor before any formatting happens.(dongtienvietnam.com)

Please switch to a portable read loop instead of mapfile, e.g.:

-mapfile -t files < <(\
-  git diff --cached --name-only --diff-filter=ACMR | \
-  grep -E '\.(c|h|cpp|hpp)$' | \
-  grep -vE '^src/tools/pg_bsd_indent/' || true)
+files=()
+while IFS= read -r file; do
+  files+=("$file")
+done < <(git diff --cached --name-only --diff-filter=ACMR |
+         grep -E '\.(c|h|cpp|hpp)$' |
+         grep -vE '^src/tools/pg_bsd_indent/' || true)

The rest of the script can stay the same, since ${#files[@]} and the later array expansions still work. That keeps the hook functional for the whole team without forcing everyone to install an alternate Bash.

🤖 Prompt for AI Agents
.githooks/pre-commit around lines 15-18: the script uses mapfile which requires
Bash 4+, breaking on macOS's default Bash 3.2; replace the mapfile usage with a
portable read loop that collects the git-diff output into the files array—run
the git diff | grep pipeline inside a command substitution or heredoc and
iterate each line with while IFS= read -r file; do files+=("$file"); done so the
array is populated in the current shell; keep the existing filters (grep -E for
extensions and grep -vE for excluded path) and the trailing || true logic
intact.

Comment thread README_CN.md
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
tools/enable-git-hooks.sh (2)

27-29: Quote nproc to avoid word splitting; address ShellCheck SC2046

Unquoted command substitution can split if nproc prints unexpected whitespace. Quote it and slightly polish the warning text.

Apply:

-  if ! make -C src/tools/pg_bsd_indent -j$(nproc 2>/dev/null || echo 2) >/dev/null; then
-    echo "[enable-git-hooks] Warning: build failed. you can build manually: make -C src/tools/pg_bsd_indent pg_bsd_indent"
+  if ! make -C src/tools/pg_bsd_indent -j"$(nproc 2>/dev/null || echo 2)" >/dev/null; then
+    echo "[enable-git-hooks] Warning: build failed. You can build manually: make -C src/tools/pg_bsd_indent pg_bsd_indent"
   fi

Based on static analysis hint (SC2046).


18-21: Optional: add non-symlink fallback for Windows devs

ln -s often fails on Windows without admin/dev mode. Consider copying as a fallback so tools checking .git/hooks still work.

Example:

-  ln -s ../.githooks/pre-commit .git/hooks/pre-commit || true
+  ln -s ../.githooks/pre-commit .git/hooks/pre-commit 2>/dev/null || \
+    cp .githooks/pre-commit .git/hooks/pre-commit || true
CONTRIBUTING.md (1)

25-29: Doc nits: mention skip env and scope details

Two small additions improve developer experience.

  • Note the escape hatch environment variable, if supported by the hook: e.g., “Set PG_NO_FORMAT=1 to bypass formatting for a commit.”
  • Clarify file scope: “The hook and CI target C/C++ sources (e.g., .c/.h/.cpp/.hpp); tool sources under src/tools/pg_bsd_indent/ are excluded.”

I can propose a patch if you confirm the hook supports PG_NO_FORMAT as per README.

.cirrus.format.yml (1)

48-50: Quote exported paths for safety

Guard against spaces or special chars in working directory paths.

-export PGTYPEDEFS=$(pwd)/src/tools/pgindent/typedefs.list
-export PGINDENT=$(pwd)/build/src/tools/pg_bsd_indent/pg_bsd_indent
+export PGTYPEDEFS="$(pwd)/src/tools/pgindent/typedefs.list"
+export PGINDENT="$(pwd)/build/src/tools/pg_bsd_indent/pg_bsd_indent"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 769884a and aef22eb.

📒 Files selected for processing (8)
  • .cirrus.format.yml (1 hunks)
  • .cirrus.star (1 hunks)
  • .githooks/pre-commit (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Makefile (1 hunks)
  • README.md (1 hunks)
  • README_CN.md (1 hunks)
  • tools/enable-git-hooks.sh (1 hunks)
🧰 Additional context used
🪛 Shellcheck (0.11.0)
tools/enable-git-hooks.sh

[warning] 27-27: Quote this to prevent word splitting.

(SC2046)

🪛 checkmake (0.2.2)
Makefile

[warning] 48-48: Missing required phony target "all"

(minphony)


[warning] 48-48: Missing required phony target "clean"

(minphony)


[warning] 48-48: Missing required phony target "test"

(minphony)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: oracle_pg_regression (ubuntu-latest)
  • GitHub Check: oracle_regression (ubuntu-latest)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: contrib_regression
  • GitHub Check: pg_regression (ubuntu-latest)
  • GitHub Check: meson_build (ubuntu-latest)
🔇 Additional comments (2)
.githooks/pre-commit (1)

15-18: Fix Bash 3.2 incompatibility in staged-file collection.

Line 15 still uses mapfile, which Bash 3.2 (macOS default) does not provide, so the hook aborts before formatting runs. Replace it with a portable read loop so everyone can commit without installing a newer shell.

-mapfile -t files < <(\
-  git diff --cached --name-only --diff-filter=ACMR | \
-  grep -E '\.(c|h|cpp|hpp)$' | \
-  grep -vE '^src/tools/pg_bsd_indent/' || true)
+files=()
+while IFS= read -r file; do
+  files+=("$file")
+done < <(git diff --cached --name-only --diff-filter=ACMR |
+         grep -E '\.(c|h|cpp|hpp)$' |
+         grep -vE '^src/tools/pg_bsd_indent/' || true)
.cirrus.star (1)

42-45: Restore inclusion of the main Cirrus task matrix.

Line 42 comments out config_from(".cirrus.tasks.yml"), so the entire build/test matrix stops loading and only the new format job runs—critical regression for every PR/push. Keep the tasks inclusion and append the format check afterward.

-    # output += config_from(".cirrus.tasks.yml")
-
-    # PR-only format check
-    output += config_from(".cirrus.format.yml")
+    output += config_from(".cirrus.tasks.yml")
+
+    # PR-only format check
+    output += config_from(".cirrus.format.yml")

Comment thread .cirrus.format.yml
Comment on lines +54 to +63
echo "[FormatCheck] Running pgindent --check..."
set +e
./src/tools/pgindent/pgindent --check $files
rc=$?
set -e
if [ $rc -ne 0 ]; then
echo "[FormatCheck] Unformatted changes detected; suggested patch below:"
./src/tools/pgindent/pgindent --diff $files || true
exit $rc
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid unquoted $files; use newline-delimited xargs for correctness

Unquoted $files is vulnerable to word splitting/globbing; filenames with spaces will break both --check and --diff. Switch to a newline-delimited xargs flow.

Apply:

-    set +e
-    ./src/tools/pgindent/pgindent --check $files
-    rc=$?
-    set -e
-    if [ $rc -ne 0 ]; then
-      echo "[FormatCheck] Unformatted changes detected; suggested patch below:"
-      ./src/tools/pgindent/pgindent --diff $files || true
-      exit $rc
-    fi
+    # Run checks safely with newline-delimited xargs (handles spaces in paths).
+    set +e
+    printf '%s\n' "$files" | xargs -r -d '\n' ./src/tools/pgindent/pgindent --check
+    rc=$?
+    set -e
+    if [ $rc -ne 0 ]; then
+      echo "[FormatCheck] Unformatted changes detected; suggested patch below:"
+      printf '%s\n' "$files" | xargs -r -d '\n' ./src/tools/pgindent/pgindent --diff || true
+      exit $rc
+    fi

Optionally extend extensions to cover .cc/.cxx/.hh/.hxx if the tree uses them.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "[FormatCheck] Running pgindent --check..."
set +e
./src/tools/pgindent/pgindent --check $files
rc=$?
set -e
if [ $rc -ne 0 ]; then
echo "[FormatCheck] Unformatted changes detected; suggested patch below:"
./src/tools/pgindent/pgindent --diff $files || true
exit $rc
fi
echo "[FormatCheck] Running pgindent --check..."
# Run checks safely with newline-delimited xargs (handles spaces in paths).
set +e
printf '%s\n' "$files" | xargs -r -d '\n' ./src/tools/pgindent/pgindent --check
rc=$?
set -e
if [ $rc -ne 0 ]; then
echo "[FormatCheck] Unformatted changes detected; suggested patch below:"
printf '%s\n' "$files" | xargs -r -d '\n' ./src/tools/pgindent/pgindent --diff || true
exit $rc
fi
🤖 Prompt for AI Agents
.cirrus.format.yml lines 54-63: the script uses unquoted $files which allows
word-splitting/globbing and breaks on filenames with spaces; change the
invocation to feed a newline- or NUL-delimited list to xargs and call pgindent
once per file (do this for both the --check and --diff invocations). Concretely,
emit files in a safe delimiter form (e.g. printf '%s\n' "$files" or better,
produce NUL-delimited output) and pipe into xargs (or xargs -0) to run
./src/tools/pgindent/pgindent --check and ./src/tools/pgindent/pgindent --diff
so filenames with spaces are preserved; also apply the same change to the diff
path and optionally extend the file-extension list to include .cc/.cxx/.hh/.hxx
if those are used in the repo.

@gaoxueyu gaoxueyu merged commit 1dc7a76 into IvorySQL:master Sep 30, 2025
6 checks passed
This was referenced Oct 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants