Skip to content

feat(git-hooks): add commit message validation and pre-commit checks#62

Open
DurgaPrasad-54 wants to merge 28 commits intoPSMRI:mainfrom
DurgaPrasad-54:main
Open

feat(git-hooks): add commit message validation and pre-commit checks#62
DurgaPrasad-54 wants to merge 28 commits intoPSMRI:mainfrom
DurgaPrasad-54:main

Conversation

@DurgaPrasad-54
Copy link
Contributor

@DurgaPrasad-54 DurgaPrasad-54 commented Mar 5, 2026

📋 Description

JIRA ID:

Please provide a summary of the change and the motivation behind it. Include relevant context and details.


✅ Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)
  • New feature (non-breaking change which adds functionality)
  • 🔥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🛠 Refactor (change that is neither a fix nor a new feature)
  • ⚙️ Config change (configuration file or build script updates)
  • 📚 Documentation (updates to docs or readme)
  • 🧪 Tests (adding new or updating existing tests)
  • 🎨 UI/UX (changes that affect the user interface)
  • 🚀 Performance (improves performance)
  • 🧹 Chore (miscellaneous changes that don't modify src or test files)

ℹ️ Additional Information

Please describe how the changes were tested, and include any relevant screenshots, logs, or other information that provides additional context.

Summary by CodeRabbit

  • Chores

    • Enforced automated commit message validation (conventional commit rules, header/body/footer constraints). Validation runs locally via a commit hook and automatically on pull requests.
  • Documentation

    • Updated setup and usage steps to enable local git hooks, the PR commit message validation workflow, and adjusted startup/usage instructions.

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

Adds commit message validation: a local Git commit-msg hook that runs commitlint via pinned npx invocation, a detailed commitlint.config.js with explicit rules and allowed types, a GitHub Actions workflow that lints each commit in a PR range on pull_request events, and README updates describing hook and setup steps.

Changes

Cohort / File(s) Summary
Git hook script
./.git-hooks/commit-msg
New POSIX shell hook (#!/bin/sh) with set -e that runs npx --yes @commitlint/cli@20.4.3 --edit "$1" to validate the current commit message.
CI workflow
./.github/workflows/commit-check.yml
New "Commit Message Check" workflow (pull_request: opened, synchronize, reopened) that checks out repo (fetch-depth: 0), enumerates commits (base..head), writes each message to a temp file, and runs npx --yes @commitlint/cli@20.4.3 --edit against each, failing on violations.
Commitlint config
./commitlint.config.js
New module.exports with explicit rules: header/body/footer length limits, required non-empty subject/type, type-case: lower-case, subject-case constraints, subject-full-stop prohibition, and type-enum (build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test).
Docs
./README.md
Updated setup steps: added enabling git hooks and git-hooks config, reworded steps and added explicit steps for running dev server and accessing Swagger UI; step ordering and instructions adjusted.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Git as Git (local)
    participant Hook as .git-hooks/commit-msg
    participant CL as npx/@commitlint
    participant Repo as Repository
    participant GH as GitHub Actions

    Dev->>Git: git commit (creates commit message)
    Git->>Hook: invoke commit-msg hook with commit file path "$1"
    Hook->>CL: `/bin/sh` runs `npx --yes `@commitlint/cli`@20.4.3 --edit "$1"`
    CL-->>Hook: exit status (success / failure)
    Hook-->>Git: hook exit code returned

    Dev->>Repo: push branch / open PR
    Repo->>GH: webhook (pull_request opened/synchronize/reopened)
    GH->>Repo: checkout (fetch-depth: 0) and list commits (base..head)
    GH->>CL: run `npx --yes `@commitlint/cli`@20.4.3 --edit` on each temp commit message file
    CL-->>GH: report results → workflow pass/fail
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through hooks with /bin/sh so neat,
set -e made errors admit defeat,
npx pinned and tidy, each message I scan,
CI double-checks every PR I can,
nibble on clean commits — carrot-sweet! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary changes: adding git hooks for commit message validation via commitlint and related pre-commit infrastructure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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: 4

🧹 Nitpick comments (1)
commitlint.config.js (1)

1-13: Configuration looks correct and consistent with the CI workflow.

The rules enforce:

  • Required conventional commit types (feat, fix, docs, style, refactor, test, chore)
  • Mandatory scope (matching the workflow regex requirement)
  • Non-empty subject

Consider extending @commitlint/config-conventional as a base and overriding only the rules you want to customize, which provides additional best-practice rules like header-max-length and body-leading-blank out of the box:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-empty': [2, 'never'],
    'subject-case': [0]
  }
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commitlint.config.js` around lines 1 - 13, Update the commitlint
configuration to extend the standard preset instead of re-declaring all rules:
change module.exports to include extends: ['@commitlint/config-conventional']
and then keep only the custom overrides (e.g., retain your 'scope-empty' and
'subject-case' entries) so that the base preset provides additional
best-practice rules like header-max-length and body-leading-blank while your
overrides (in the existing rules object) still enforce mandatory scope and
disabled subject-case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.git-hooks/commit-msg:
- Around line 1-3: The commit hook at .git-hooks/commit-msg uses "npx
--no-install commitlint --edit \"$1\"" but will never run because core.hooksPath
is .git/hooks and there is no package.json providing `@commitlint/cli`; either
move the script to .git/hooks/commit-msg and add commitlint devDependency and an
npm install step (so the npx call succeeds), or keep it in .git-hooks and update
CONTRIBUTING.md to instruct contributors to run "git config core.hooksPath
.git-hooks" and "npm install" (and explain why Node.js/commitlint is needed for
this Java/Maven repo); update CONTRIBUTING.md to include the chosen setup steps
and ensure the hook script still references the same npx command.

In @.github/workflows/commit-check.yml:
- Line 16: The current regex assigned to the variable regex
('^(feat|fix|docs|style|refactor|test|chore)\([a-zA-Z0-9_-]+\): .+') is overly
restrictive for the commit scope; change the scope portion to allow any
characters except the closing parenthesis (for example use [^)]+) or otherwise
align it exactly with your commitlint scope rules so CI accepts valid local
commits (update the regex string where regex is defined in the workflow).
- Around line 18-23: The current commit validation uses a piped while-read loop
(git log ... | while read commit; do ... exit 1; done) so the exit only affects
the subshell and won't fail the workflow; change the logic to run the loop in
the main shell (e.g., use process substitution like while read commit; do ...;
done < <(git log ...)) or replace the loop with a grep-based check (capture
invalid=$(git log ... | grep -Ev "$regex" || true) and if [ -n "$invalid" ];
then echo the invalids and exit 1) so that an invalid commit triggers a real
exit 1 from the step.
- Around line 11-12: The checkout step currently uses actions/checkout@v4 with
the default shallow clone; update the step that references actions/checkout@v4
to include fetch-depth: 0 so the job performs a full clone and `git log
base..head` can access the full commit history (modify the workflow step that
contains uses: actions/checkout@v4 to add the fetch-depth: 0 option).

---

Nitpick comments:
In `@commitlint.config.js`:
- Around line 1-13: Update the commitlint configuration to extend the standard
preset instead of re-declaring all rules: change module.exports to include
extends: ['@commitlint/config-conventional'] and then keep only the custom
overrides (e.g., retain your 'scope-empty' and 'subject-case' entries) so that
the base preset provides additional best-practice rules like header-max-length
and body-leading-blank while your overrides (in the existing rules object) still
enforce mandatory scope and disabled subject-case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1bef85ca-f3c4-4f08-bef3-cf863e1f424a

📥 Commits

Reviewing files that changed from the base of the PR and between 4e00bee and 3ac2102.

📒 Files selected for processing (3)
  • .git-hooks/commit-msg
  • .github/workflows/commit-check.yml
  • commitlint.config.js

Copy link

@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.

🧹 Nitpick comments (2)
commitlint.config.js (1)

1-23: Consider extending @commitlint/config-conventional for additional rules.

The current configuration only defines a subset of rules. Extending the conventional config would provide additional useful defaults like header-max-length, body-leading-blank, and footer-leading-blank without explicit configuration.

♻️ Optional: Extend conventional config
 module.exports = {
+  extends: ['@commitlint/config-conventional'],
   rules: {
     'type-enum': [
       2,
       'always',
       ['build', 
        'chore', 
        'ci', 
        'docs', 
        'feat', 
        'fix', 
        'perf', 
        'refactor', 
        'revert', 
        'style', 
        'test']
     ],
     'type-case': [2, 'always', 'lower-case'],
     'scope-empty': [2, 'never'],
     'subject-empty': [2, 'never'],
     'subject-case': [0]
   }
 };

Note: This would require @commitlint/config-conventional as a dev dependency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commitlint.config.js` around lines 1 - 23, The commitlint config currently
defines only a few rules in module.exports.rules (e.g., 'type-enum',
'type-case', 'scope-empty', 'subject-empty', 'subject-case'); update the file to
extend the `@commitlint/config-conventional` preset instead of (or in addition to)
redefining everything so you inherit defaults like header-max-length,
body-leading-blank, and footer-leading-blank; add an extends property
referencing '@commitlint/config-conventional' in module.exports, keep or
override only the rules you intentionally changed (e.g., preserve your
'type-enum' override if needed), and ensure `@commitlint/config-conventional` is
added as a devDependency in package.json.
README.md (1)

24-26: Format example should use inline code formatting.

The commit format example on line 26 would be clearer with backticks to distinguish it as code.

📝 Suggested formatting improvement
 All commits must follow this format:
 
-type(scope): message
+`type(scope): message`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 24 - 26, The example commit format shown as the
literal text type(scope): message should be rendered as inline code to
distinguish it from prose; update the README entry that currently prints
"type(scope): message" to wrap that exact string in backticks (e.g.,
`type(scope): message`) so it appears as inline code in markdown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@commitlint.config.js`:
- Around line 1-23: The commitlint config currently defines only a few rules in
module.exports.rules (e.g., 'type-enum', 'type-case', 'scope-empty',
'subject-empty', 'subject-case'); update the file to extend the
`@commitlint/config-conventional` preset instead of (or in addition to) redefining
everything so you inherit defaults like header-max-length, body-leading-blank,
and footer-leading-blank; add an extends property referencing
'@commitlint/config-conventional' in module.exports, keep or override only the
rules you intentionally changed (e.g., preserve your 'type-enum' override if
needed), and ensure `@commitlint/config-conventional` is added as a devDependency
in package.json.

In `@README.md`:
- Around line 24-26: The example commit format shown as the literal text
type(scope): message should be rendered as inline code to distinguish it from
prose; update the README entry that currently prints "type(scope): message" to
wrap that exact string in backticks (e.g., `type(scope): message`) so it appears
as inline code in markdown.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d420d47d-44fb-4627-8816-66b0a963112f

📥 Commits

Reviewing files that changed from the base of the PR and between c1e8801 and 86e1f4d.

📒 Files selected for processing (3)
  • .github/workflows/commit-check.yml
  • README.md
  • commitlint.config.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/commit-check.yml

Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/commit-check.yml:
- Around line 18-26: Replace the hardcoded regex-based commit validation block
(the regex, the invalid variable and the git log | grep -Ev pipeline) with a
call to commitlint so CI uses the same rules as commitlint.config.js;
specifically, after setting up Node.js, invoke commitlint over the PR range (the
same commit range used in the git log command) via npx --no-install to avoid
installing packages, and fail the job if commitlint reports any errors. Ensure
the new step references the PR base/head commit range variables used in the
original git log invocation so the exact same commits are linted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 357e79bc-06df-469e-9028-d69b98b20ece

📥 Commits

Reviewing files that changed from the base of the PR and between 86e1f4d and 34b4b63.

📒 Files selected for processing (2)
  • .github/workflows/commit-check.yml
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md

Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/commit-check.yml:
- Around line 22-24: Replace the per-commit ephemeral npx install by invoking a
pinned commitlint binary once for the whole PR range: stop calling "npx --yes
`@commitlint/cli`" inside the while-loop and instead install or reference a fixed
version (e.g., `@commitlint/cli`@<version>) before the loop (or run a single
invocation) and run commitlint against the combined git log output (the existing
"git log --no-merges --pretty=format:%s ${{ github.event.pull_request.base.sha
}}..${{ github.event.pull_request.head.sha }}" pipeline); ensure the action uses
a pinned version of `@commitlint/cli` rather than installing latest at runtime.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cfe2d8ac-2aa4-412c-9ae7-d2ed640b8a69

📥 Commits

Reviewing files that changed from the base of the PR and between 34b4b63 and eb785ba.

📒 Files selected for processing (2)
  • .git-hooks/commit-msg
  • .github/workflows/commit-check.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .git-hooks/commit-msg

@DurgaPrasad-54
Copy link
Contributor Author

@coderabbitai resume

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

✅ Actions performed

Reviews resumed.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 6, 2026

Copy link

@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.

🧹 Nitpick comments (1)
.github/workflows/commit-check.yml (1)

22-29: Consider using commitlint's native --from/--to flags for efficiency.

The current approach is functionally correct, but loops over each commit individually. Commitlint supports linting a commit range directly in a single invocation, which avoids temp files and multiple npx overhead.

♻️ Optional: single-invocation approach
       - name: Validate commit messages
         run: |
-          set -eo pipefail
-          commits=$(git log --no-merges --pretty=format:"%H" "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}")
-          for sha in $commits; do
-            tmp=$(mktemp)
-            git log -1 --pretty=format:"%B" "$sha" > "$tmp"
-            npx --yes `@commitlint/cli`@20.4.3 --edit "$tmp"
-            rm "$tmp"
-          done
+          npx --yes `@commitlint/cli`@20.4.3 \
+            --from "${{ github.event.pull_request.base.sha }}" \
+            --to "${{ github.event.pull_request.head.sha }}" \
+            --git-log-args "--no-merges"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/commit-check.yml around lines 22 - 29, Replace the
per-commit loop that builds a temp file and calls npx for each commit with a
single commitlint invocation using the --from and --to flags; specifically
remove the commits/for sha/tmp/git log/git rm sequence and call npx --yes
`@commitlint/cli`@20.4.3 with --from "${{ github.event.pull_request.base.sha }}"
and --to "${{ github.event.pull_request.head.sha }}", keeping set -eo pipefail
and any existing environment behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/commit-check.yml:
- Around line 22-29: Replace the per-commit loop that builds a temp file and
calls npx for each commit with a single commitlint invocation using the --from
and --to flags; specifically remove the commits/for sha/tmp/git log/git rm
sequence and call npx --yes `@commitlint/cli`@20.4.3 with --from "${{
github.event.pull_request.base.sha }}" and --to "${{
github.event.pull_request.head.sha }}", keeping set -eo pipefail and any
existing environment behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0cca5a4-d240-4a4c-887e-7b3c912e291d

📥 Commits

Reviewing files that changed from the base of the PR and between fa7ad69 and ca51995.

📒 Files selected for processing (2)
  • .git-hooks/commit-msg
  • .github/workflows/commit-check.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .git-hooks/commit-msg

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.

2 participants