Skip to content

feat: add pre-commit hooks and PR title validation#13

Merged
aryeko merged 2 commits intomainfrom
chore/s4-precommit-hooks
Feb 5, 2026
Merged

feat: add pre-commit hooks and PR title validation#13
aryeko merged 2 commits intomainfrom
chore/s4-precommit-hooks

Conversation

@aryeko
Copy link
Collaborator

@aryeko aryeko commented Feb 5, 2026

Summary

Implements S4: Pre-commit Hooks from the SDLC plan.

Changes

  1. Local pre-commit hooks via lefthook.yml:

    • gofmt - checks code formatting
    • goimports - checks import formatting
    • golangci-lint - runs linter on staged files
    • All run in parallel for speed
  2. CI PR title validation:

    • New pr-title job validates PR titles follow conventional commits
    • Uses amannn/action-semantic-pull-request@v5
    • Ensures squash-merge commit messages are properly formatted
  3. MASTER.md updated:

    • Marked S4 as complete (🟢)

Architecture

Local:     pre-commit → fmt/lint checks → commit-msg → commitlint
CI:        PR opened → pr-title job validates conventional format
Merge:     Squash uses PR title (validated by CI)

Note on Branch Rulesets

GitHub's commit_message_pattern ruleset feature is not available in the free tier. The implementation relies on:

  • Local pre-commit hooks (can be bypassed with --no-verify)
  • CI PR title validation (cannot be bypassed)

For enterprise repos, branch rulesets can be added via GitHub UI for additional enforcement.

Test Plan

  • Ran make fmt && make lint && make test - all pass
  • Committed changes - pre-commit hooks executed successfully
  • Commit message validated by commitlint hook

To test locally:

# Update hooks
make setup-hooks

# Try committing unformatted code
echo "package main;func main(){}" > test.go
git add test.go
git commit -m "test: formatting check"  # Should fail pre-commit

Made with Cursor

Summary by CodeRabbit

  • Chores
    • Added CI check to validate pull request titles automatically.
    • Configured pre-commit hooks to enforce formatting, import ordering, and linting for Go and to validate commit messages.
    • Updated internal project plan statuses to mark two previously deferred items as complete.

- Add lefthook pre-commit hooks for gofmt, goimports, golangci-lint
- Add CI job to validate PR titles follow conventional commits
- Update MASTER.md to mark S4 (Pre-commit Hooks) as complete

Note: Branch rulesets with commit_message_pattern not available in
free tier, so enforcement relies on local hooks + PR title checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

Updates development workflows: adds Lefthook pre-commit and commit-msg checks, introduces a CI job to validate semantic PR titles, and marks two SDLC entries (S4 Pre-commit Hooks, S5 Test Coverage) as complete in the master plan.

Changes

Cohort / File(s) Summary
Plan update
.github/internal/plans/MASTER.md
Changed status for S4 (Pre-commit Hooks) and S5 (Test Coverage) from Deferred to Complete.
CI workflow
.github/workflows/ci.yml
Added a new "Validate PR Title" job that runs on pull_request using amannn/action-semantic-pull-request@v5 with GITHUB_TOKEN.
Pre-commit & commit-msg hooks
lefthook.yml
Added Lefthook configuration: parallel pre-commit hooks running gofmt, goimports, golangci-lint on staged Go files and a commit-msg hook invoking commitlint via GOBIN/GOPATH bin.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble code and tidy strings,
Hooks and CI give tidy things,
Titles checked before they land,
Tests and lint held in my hand,
Hooray — the rabbit hops, well-planned! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add pre-commit hooks and PR title validation' directly and accurately describes the main changes: adding pre-commit hooks (lefthook.yml) and PR title validation (CI workflow). It is clear, specific, and follows conventional commit format.
Description check ✅ Passed The PR description includes most required sections: Summary explaining what and why, detailed Changes with bullet points, Architecture diagram, Test Plan with verification steps, and notes on design decisions. All key template sections are covered.
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
  • Commit unit tests in branch chore/s4-precommit-hooks

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

@codecov-commenter
Copy link

codecov-commenter commented Feb 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

🤖 Fix all issues with AI agents
In `@lefthook.yml`:
- Around line 4-20: The gofmt/goimports hooks hang and hide real failures when
no Go files are staged because the current run uses command substitution and
allows formatters to read stdin; update the gofmt and goimports command entries
(the "gofmt" and "goimports" commands) to first check whether {staged_files} is
empty and skip early if so, otherwise run the formatter directly on the file
list and return the formatter's exit status (do not wrap the formatter in test
-z "$(…)" which masks its exit code); ensure the implementation preserves and
propagates the formatter exit code so failures are visible in the pre-commit
hook.

- Guard when no Go files staged
- Preserve formatter exit codes

Co-authored-by: Cursor <cursoragent@cursor.com>
@aryeko aryeko merged commit 62e4733 into main Feb 5, 2026
8 checks passed
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