Skip to content

Commit 3812b8f

Browse files
justin808claude
andcommitted
Implement automatic Git hooks with Lefthook for code quality
- Replace manual hook installation with modular Lefthook configuration - Check all changed files (staged + unstaged + untracked) for comprehensive coverage - Add separate scripts in bin/lefthook/ for testability and maintainability - Automatic installation via script/bootstrap and package.json postinstall - Provide helpful error messages with fix commands and skip options - Parallel execution of linting checks for performance Prevents CI failures by catching linting issues locally before commits. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent bb1a67a commit 3812b8f

File tree

10 files changed

+48
-33
lines changed

10 files changed

+48
-33
lines changed

.lefthook.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
# .lefthook.yml
2-
# Fast pre-commit hooks that only check changed files
2+
# Fast pre-commit hooks that check all changed files (staged + unstaged + untracked)
33
# Install with: bundle exec lefthook install
44

55
pre-commit:
66
parallel: true
77
commands:
88
autofix:
9-
run: bin/lefthook/ruby-autofix staged
9+
run: bin/lefthook/ruby-autofix all-changed
1010

1111
rubocop:
12-
run: bin/lefthook/ruby-lint staged
12+
run: bin/lefthook/ruby-lint all-changed
1313

1414
prettier:
15-
run: bin/lefthook/prettier-format staged
15+
run: bin/lefthook/prettier-format all-changed
1616

1717
trailing-newlines:
18-
run: bin/lefthook/check-trailing-newlines staged
18+
run: bin/lefthook/check-trailing-newlines all-changed
1919

2020
pre-push:
2121
commands:

CLAUDE.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
1212

1313
These requirements are non-negotiable. CI will fail if not followed.
1414

15-
**🚀 RECOMMENDED: Install Git hooks to automate these checks:**
15+
**🚀 AUTOMATIC: Git hooks are installed automatically during setup**
1616

17-
```bash
18-
# Install Lefthook hooks (already included in Gemfile)
19-
bundle install
20-
bundle exec lefthook install
21-
```
22-
23-
This will automatically run linting on **only the files you changed** before each commit - making it fast!
17+
Git hooks will automatically run linting on **all changed files (staged + unstaged + untracked)** before each commit - making it fast while preventing CI failures!
2418

2519
**Note:** Git hooks are for React on Rails gem developers only, not for users who install the gem.
2620

CONTRIBUTING.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@
77
## Prerequisites
88

99
- [Yalc](https://github.com/whitecolor/yalc) must be installed globally for most local development.
10-
- **Git hooks setup** (REQUIRED for all contributors):
10+
- **Git hooks setup** (automatic during normal setup):
1111

12-
```sh
13-
cd react_on_rails/
14-
bundle install
15-
bundle exec lefthook install
16-
```
17-
18-
This sets up automatic linting that runs **only on files you changed** - making commits fast while preventing CI failures.
12+
Git hooks are installed automatically when you run the standard setup commands. They will run automatic linting on **all changed files (staged + unstaged + untracked)** - making commits fast while preventing CI failures.
1913

2014
- After updating code via Git, to prepare all examples:
2115

@@ -492,10 +486,10 @@ rake lint
492486

493487
- Format JavaScript/TypeScript files with Prettier (on changed files only)
494488
- Check and fix linting issues with ESLint
495-
- Check and fix Ruby style issues with RuboCop (on changed files only)
489+
- Check and fix Ruby style issues with RuboCop (on all changed files)
496490
- Ensure trailing newlines on all files
497491

498-
**Setup once**: `bundle exec lefthook install` (see Prerequisites above)
492+
**Setup**: Automatic during normal development setup
499493

500494
## 🤖 Best Practices for AI Coding Agents
501495

bin/lefthook/check-trailing-newlines

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ if [ -z "$files" ]; then
1010
exit 0
1111
fi
1212

13-
echo "🔍 Checking trailing newlines on $CONTEXT files..."
13+
if [ "$CONTEXT" = "all-changed" ]; then
14+
echo "🔍 Checking trailing newlines on all changed files..."
15+
else
16+
echo "🔍 Checking trailing newlines on $CONTEXT files..."
17+
fi
1418

1519
failed_files=""
1620
for file in $files; do

bin/lefthook/get-changed-files

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ case "$CONTEXT" in
99
staged)
1010
git diff --cached --name-only --diff-filter=ACM | grep -E "$PATTERN" || true
1111
;;
12+
all-changed)
13+
# Get all changed files (staged + unstaged + untracked) vs working directory
14+
(git diff --cached --name-only --diff-filter=ACM; git diff --name-only --diff-filter=ACM; git ls-files --others --exclude-standard) | sort -u | grep -E "$PATTERN" || true
15+
;;
1216
branch)
1317
# Find base branch (prefer main over master)
1418
base="origin/main"
1519
git rev-parse --verify --quiet "$base" >/dev/null || base="origin/master"
1620
git diff --name-only --diff-filter=ACM "$base"...HEAD | grep -E "$PATTERN" || true
1721
;;
1822
*)
19-
echo "Usage: $0 {staged|branch} [pattern]" >&2
23+
echo "Usage: $0 {staged|all-changed|branch} [pattern]" >&2
2024
exit 1
2125
;;
2226
esac

bin/lefthook/prettier-format

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ if [ -z "$files" ]; then
1010
exit 0
1111
fi
1212

13-
echo "💅 Prettier on $CONTEXT files:"
13+
if [ "$CONTEXT" = "all-changed" ]; then
14+
echo "💅 Prettier on all changed files:"
15+
else
16+
echo "💅 Prettier on $CONTEXT files:"
17+
fi
1418
printf " %s\n" $files
1519

1620
yarn run prettier --write $files
1721

18-
# Re-stage files if running on staged context
19-
if [ "$CONTEXT" = "staged" ]; then
22+
# Re-stage files if running on staged or all-changed context
23+
if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
2024
echo $files | xargs -r git add
2125
echo "✅ Re-staged formatted files"
2226
fi

bin/lefthook/ruby-autofix

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ if [ -z "$files" ]; then
1010
exit 0
1111
fi
1212

13-
echo "🎨 Autofix on $CONTEXT Ruby files:"
13+
if [ "$CONTEXT" = "all-changed" ]; then
14+
echo "🎨 Autofix on all changed Ruby files:"
15+
else
16+
echo "🎨 Autofix on $CONTEXT Ruby files:"
17+
fi
1418
printf " %s\n" $files
1519

1620
bundle exec rake autofix
1721

18-
# Re-stage files if running on staged context
19-
if [ "$CONTEXT" = "staged" ]; then
22+
# Re-stage files if running on staged or all-changed context
23+
if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
2024
echo $files | xargs -r git add
2125
echo "✅ Re-staged formatted files"
2226
fi

bin/lefthook/ruby-lint

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ if [ -z "$files" ]; then
1010
exit 0
1111
fi
1212

13-
echo "🔍 RuboCop on $CONTEXT Ruby files:"
13+
if [ "$CONTEXT" = "all-changed" ]; then
14+
echo "🔍 RuboCop on all changed Ruby files:"
15+
else
16+
echo "🔍 RuboCop on $CONTEXT Ruby files:"
17+
fi
1418
printf " %s\n" $files
1519

1620
if ! bundle exec rubocop --force-exclusion --display-cop-names -- $files; then

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
"type-check": "yarn run tsc --noEmit --noErrorTruncation",
103103
"release:patch": "node_package/scripts/release patch",
104104
"release:minor": "node_package/scripts/release minor",
105-
"release:major": "node_package/scripts/release major"
105+
"release:major": "node_package/scripts/release major",
106+
"postinstall": "test -f .lefthook.yml && test -d .git && command -v bundle >/dev/null 2>&1 && bundle exec lefthook install || true"
106107
},
107108
"repository": {
108109
"type": "git",

script/bootstrap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ if [ -f "Gemfile" ]; then
3030
bundle check --path vendor/gems 2>&1 >/dev/null || {
3131
bundle install --path vendor/gems --quiet --without production
3232
}
33+
34+
# Install Git hooks for code quality (development only)
35+
if [ -f ".lefthook.yml" ] && [ -d ".git" ]; then
36+
echo "==> Installing Git hooks for code quality…"
37+
bundle exec lefthook install
38+
fi
3339
fi

0 commit comments

Comments
 (0)