Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 13, 2025

Summary

  • Fixes the rake release task failing with "Unable to create index.lock" error
  • Root cause: Multiple pre-commit hooks running in parallel tried to git add files simultaneously, causing a race condition for the git index lock
  • Solution: Use lefthook's built-in stage_fixed: true option instead of manual git add commands

Changes

  • Updated .lefthook.yml to add stage_fixed: true to autofix, eslint, and prettier hooks
  • Removed manual git add calls from bin/lefthook/prettier-format
  • Removed manual git add calls from bin/lefthook/ruby-autofix
  • Added glob patterns to hook definitions for better performance

Test Plan

  • Tested commit with multiple file changes (prettier formatted .lefthook.yml)
  • Verified no index.lock errors occur
  • Confirmed files are properly re-staged after formatting
  • RuboCop passes with no violations

Impact

This fix ensures that the release script can successfully commit version bumps without encountering race conditions when multiple formatters try to re-stage files.


This change is Reviewable

Summary by CodeRabbit

  • Chores

    • Added file-type globs and ensured stage-fixed behavior for autofix, RuboCop, ESLint, Prettier, and trailing-newlines hooks.
    • Removed automatic re-staging after formatting and lint autofix; hooks no longer re-add modified files to staging.
    • Updated autofix completion messaging for clarity.
  • Bug Fixes

    • Trailing-newlines hook now auto-appends missing final newlines and reports success instead of failing.

- Use lefthook's stage_fixed option instead of manual git add
- Prevents index.lock errors when hooks run in parallel
- Fixes rake release task failures during version bumps
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Removed manual git re-staging from lefthook hook scripts and added explicit file globs plus stage_fixed: true entries in .lefthook.yml; trailing-newlines script now auto-corrects missing trailing newlines instead of failing.

Changes

Cohort / File(s) Summary
Lefthook configuration
\.lefthook.yml``
Added file globs for autofix, rubocop, eslint, prettier; enabled stage_fixed: true for autofix, rubocop, eslint, prettier, and trailing-newlines where applicable.
Prettier hook script
\bin/lefthook/prettier-format``
Removed post-format git add re-staging for root/Pro contexts; retained Prettier execution.
Ruby autofix script
\bin/lefthook/ruby-autofix``
Removed conditional git add re-staging blocks and re-stage messaging; replaced with a simple completion echo.
ESLint hook script
\bin/lefthook/eslint-lint``
Removed duplicated post---fix git add re-staging blocks for root/packages and react_on_rails_pro contexts; ESLint --fix runs remain.
Trailing newlines check
\bin/lefthook/check-trailing-newlines``
Replaced fail-collecting behavior with in-loop automatic appending of missing trailing newlines and per-file notes; always reports success at end.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Lefthook
    participant HookScript as Hook Script
    participant Git

    rect rgba(255,200,160,0.15)
    note over Dev,Lefthook: Old flow (pre-change)
    Dev->>Lefthook: Commit (pre-commit)
    Lefthook->>HookScript: Run formatter/autofix/eslint --fix
    HookScript->>Git: git add (manual re-stage)
    Git-->>HookScript: Files staged
    end

    rect rgba(160,220,200,0.12)
    note over Dev,Lefthook: New flow (post-change)
    Dev->>Lefthook: Commit (pre-commit)
    Lefthook->>HookScript: Run formatter/autofix/eslint --fix
    note right of Lefthook: Lefthook `stage_fixed: true` auto-stages fixes
    Lefthook->>Git: stage_fixed staging (automatic)
    Git-->>Lefthook: Files staged
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Changes are concentrated and homogeneous (removal of re-staging) but affect multiple hook scripts and config.
  • Reviewers should verify:
    • .lefthook.yml glob coverage matches intended files.
    • stage_fixed: true is sufficient for all contexts where re-staging was removed.
    • No remaining references to removed re-stage logic cause misleading messages.
    • Trailing-newlines auto-fix behavior is safe for binary/large files.

Possibly related issues

Possibly related PRs

Suggested reviewers

  • AbanoubGhadban
  • alexeyr-ci2

Poem

🐰 I nibbled at hooks, corrected each line,

No extra adds now — the staging's just fine.
Prettier and ESLint gave files a tune,
Lefthook took over and hummed a soft tune. 🥕

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 title directly matches the main objective: fixing a race condition in pre-commit hooks during the release script.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1680276 and c5880a9.

📒 Files selected for processing (3)
  • .lefthook.yml (1 hunks)
  • bin/lefthook/check-trailing-newlines (1 hunks)
  • bin/lefthook/ruby-autofix (1 hunks)

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.

@coderabbitai coderabbitai bot added the bug label Nov 13, 2025
Copy link
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1ae439 and 9a227ba.

📒 Files selected for processing (3)
  • .lefthook.yml (1 hunks)
  • bin/lefthook/prettier-format (0 hunks)
  • bin/lefthook/ruby-autofix (1 hunks)
💤 Files with no reviewable changes (1)
  • bin/lefthook/prettier-format
🔇 Additional comments (4)
bin/lefthook/ruby-autofix (1)

22-22: LGTM - Manual re-staging correctly removed.

The simplified completion message is appropriate. The manual git add re-staging logic has been correctly removed since the autofix hook in .lefthook.yml now uses stage_fixed: true to handle re-staging automatically, eliminating the race condition.

.lefthook.yml (3)

8-11: Excellent fix for the race condition.

The combination of glob pattern filtering and stage_fixed: true correctly addresses the git index lock issue. Lefthook will now handle re-staging automatically instead of the script doing manual git add calls in parallel.


17-20: LGTM - eslint hook properly configured.

The stage_fixed: true addition ensures that any ESLint auto-fixes are automatically re-staged, preventing the race condition when running in parallel with other hooks.


22-25: LGTM - prettier hook properly configured.

The stage_fixed: true addition ensures that any Prettier formatting changes are automatically re-staged. This complements the removal of manual git add from bin/lefthook/prettier-format mentioned in the PR summary.

justin808 and others added 2 commits November 12, 2025 21:39
- Update all glob patterns from "*.{...}" to "**/*.{...}" for recursive matching
- Ensures pre-commit hooks run on files in all subdirectories (lib/, spec/, etc.)
- Remove redundant git add from eslint-lint script (lefthook handles via stage_fixed)
- Add missing stage_fixed to rubocop command for consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add stage_fixed: true to trailing-newlines command in .lefthook.yml
- Update check-trailing-newlines script to automatically add missing newlines instead of just reporting them
- Improve ruby-autofix success message to clarify that files are auto-staged
- Ensures consistency with other auto-fixing hooks (autofix, eslint, prettier)

This completes the pre-commit hook race condition fix by making all auto-fixing commands use Lefthook's stage_fixed feature uniformly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a227ba and 1680276.

📒 Files selected for processing (2)
  • .lefthook.yml (1 hunks)
  • bin/lefthook/eslint-lint (0 hunks)
💤 Files with no reviewable changes (1)
  • bin/lefthook/eslint-lint
🔇 Additional comments (2)
.lefthook.yml (2)

11-11: stage_fixed: true configuration correctly addresses the race condition.

The addition of stage_fixed: true to the autofix, rubocop, eslint, and prettier hooks is the right approach to fix the race condition. Instead of multiple hooks competing to call git add in parallel, Lefthook now atomically re-stages modified files after each hook completes, eliminating the index.lock contention.

This aligns with the PR objectives and the removal of manual re-staging logic from bin/lefthook/ruby-autofix, bin/lefthook/eslint-lint, and bin/lefthook/prettier-format scripts.

Also applies to: 16-16, 21-21, 26-26


28-29: Trailing-newlines hook appropriately omits stage_fixed.

The trailing-newlines hook is a check-only hook that does not modify files, so stage_fixed: true is not needed. The current configuration is correct.

parallel: true
commands:
autofix:
glob: "**/*.{rb,rake,ru}"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Glob patterns may still miss root-level files—verify coverage.

The patterns have been updated to use **/*.{ext}, but according to Lefthook's glob semantics (as documented in the previous review), ** matches one-or-more directory levels and does not match files directly in the repository root. Files like babel.config.js, package.json, .eslintrc.json, or Rakefile in the root directory may not be matched.

The correct approach is to use array patterns that include both root and recursive matches:

glob: ["*.{rb,rake,ru}", "**/*.{rb,rake,ru}"]

Since the PR was tested and confirmed working, verify whether:

  1. Root-level files actually require formatting/linting by these hooks in your repository, or
  2. The Lefthook version/implementation differs from the documented behavior.

Run the following script to check if root-level files exist that should be matched by these hooks:

Also applies to: 14-14, 19-19, 24-24


🏁 Script executed:

#!/bin/bash
# Check for root-level files matching the hook patterns

echo "=== Root-level Ruby files ==="
find . -maxdepth 1 -type f \( -name "*.rb" -o -name "*.rake" -o -name "*.ru" \) | head -20

echo ""
echo "=== Root-level JavaScript/TypeScript files ==="
find . -maxdepth 1 -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) | head -20

echo ""
echo "=== Root-level JSON files ==="
find . -maxdepth 1 -type f -name "*.json" | head -20

echo ""
echo "=== Root-level YAML files ==="
find . -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) | head -20

echo ""
echo "=== Root-level Markdown files ==="
find . -maxdepth 1 -type f -name "*.md" | head -20

Length of output: 736



Fix glob patterns to match root-level configuration files—critical issue confirmed.

The glob patterns are missing important root-level files that should be linted and formatted:

  • ESLint hook (**/*.{js,jsx,ts,tsx}): Misses ./eslint.config.ts, ./jest.config.base.js, ./knip.ts
  • Prettier hook (**/*.{js,jsx,ts,tsx,json,md,yml,yaml}): Misses ./package.json, ./tsconfig.json, ./.rubocop.yml, ./docker-compose.yml, and root-level markdown files

The pattern **/*.{ext} matches one-or-more directory levels but does not match files directly in the repository root. Replace with array patterns:

glob: ["*.{js,jsx,ts,tsx}", "**/*.{js,jsx,ts,tsx}"]  # eslint (line 19)
glob: ["*.{js,jsx,ts,tsx,json,md,yml,yaml}", "**/*.{js,jsx,ts,tsx,json,md,yml,yaml}"]  # prettier (line 24)

Also affects lines 9 and 14 (autofix/rubocop). While no root-level Ruby files exist now, using arrays provides forward compatibility.

@justin808 justin808 merged commit 16b88c5 into master Nov 13, 2025
24 of 25 checks passed
@justin808 justin808 deleted the justin808/fix-release-prettier-hook branch November 13, 2025 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants