Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ repos:
entry: bash -lc 'go vet ./...'
language: system
pass_filenames: false
- id: require-issue-reference
name: issue reference check (warning)
description: Warn if commit message lacks a GitHub issue reference like #123
entry: bash -lc 'scripts/require_issue_ref.sh "$1"'
language: system
stages: [commit-msg]
pass_filenames: true
- id: line-count-limit
name: line count limit (warn >500, block >750)
description: Warn on files 501–750 lines; fail if any >750 lines
entry: bash -lc 'scripts/line_count_check.sh'
language: system
pass_filenames: true

# GolangCI-Lint (static analysis)
- repo: https://github.com/golangci/golangci-lint
Expand Down
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Our pre-commit `no-commit-to-branch` hook blocks commits on non-conforming branc
```
or commit normally and the `commit-msg` hook will validate.

- Issue reference: include a GitHub issue reference (`#<issue>`) somewhere in the commit
message (body or footer). Examples: `Refs #29`, `Closes #102`.
The commit-msg hook only warns if missing; commits still proceed.

## Development Workflow

- Create or pick up an issue. For new features, propose design via an issue first.
Expand All @@ -86,6 +90,13 @@ Our pre-commit `no-commit-to-branch` hook blocks commits on non-conforming branc
- `go fmt ./...` and `go vet ./...` run via pre-commit.
- `golangci-lint` runs as part of pre-commit; CI integration may run it on PRs as well.

## File Size Guidelines

- Keep source files concise. The pre-commit hook warns when a changed file exceeds 500 lines and blocks commits for files over 750 lines.
- Warning: 501–750 lines (message only; commit proceeds)
- Error: >750 lines (commit blocked)
- Consider splitting large files into smaller units for readability and maintainability.

## Security & Secrets

- `detect-secrets` scans for potential credentials.
Expand Down
61 changes: 61 additions & 0 deletions scripts/line_count_check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail

# Pre-commit hook: Warn for files >500 lines (up to 750),
# block commit if any file exceeds 750 lines.

warn_threshold=500
block_threshold=750

warned=0
blocked=0
declare -a blocked_files
declare -a warned_files

is_regular_file() {
[[ -f "$1" ]]
}

line_count() {
# Use wc -l; handle files with no trailing newline
wc -l < "$1" | awk '{print $1}'
}

for f in "$@"; do
# Skip if not a regular file (deleted, dir, symlink, etc.)
if ! is_regular_file "$f"; then
continue
fi

# Skip binary files: if grep treating binary as non-text, skip
if ! LC_ALL=C grep -Iq . "$f"; then
continue
fi

cnt=$(line_count "$f" || echo 0)

if (( cnt > block_threshold )); then
blocked=1
blocked_files+=("$f ($cnt lines)")
elif (( cnt > warn_threshold )); then
warned=1
warned_files+=("$f ($cnt lines)")
fi
done

if (( warned == 1 )); then
echo "[line-count] Warning: some files exceed ${warn_threshold} lines:" >&2
for w in "${warned_files[@]}"; do
echo " - $w" >&2
done
fi

if (( blocked == 1 )); then
echo "[line-count] Error: files exceed ${block_threshold} lines; reduce size or split files:" >&2
for b in "${blocked_files[@]}"; do
echo " - $b" >&2
done
exit 1
fi

exit 0
39 changes: 39 additions & 0 deletions scripts/require_issue_ref.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail

# pre-commit commit-msg hook: check commit message references a GitHub issue
# Usage: scripts/require_issue_ref.sh <commit_msg_file>

msg_file="${1:-}"
if [[ -z "${msg_file}" || ! -f "${msg_file}" ]]; then
echo "commit-msg hook error: commit message file not found" >&2
exit 1
fi

# Read first line (subject)
subject="$(head -n1 "$msg_file" | tr -d '\r')"
lower_subject="$(printf '%s' "$subject" | tr '[:upper:]' '[:lower:]')"

# Allow merges and reverts to pass without extra checks
if [[ "$lower_subject" =~ ^merge\ || "$lower_subject" =~ ^revert\ ]]; then
exit 0
fi

# Allow automated release/version bump commits
if [[ "$lower_subject" =~ ^chore\(release\):\ || "$lower_subject" =~ ^bump: ]]; then
exit 0
fi

# Require a #<num> anywhere in the message (subject or body)
if rg -N --pcre2 -q "#[0-9]{1,7}\b" "$msg_file" 2>/dev/null; then
exit 0
fi

# Fallback to grep if ripgrep is unavailable
if command -v grep >/dev/null 2>&1 && grep -Eq "#[0-9]{1,7}(\b|$)" "$msg_file"; then
exit 0
fi

echo "[issue-ref] Warning: no GitHub issue reference found (e.g., 'refs #123' or 'closes #123')." >&2
echo "Include '#<num>' in the message body or footer when possible." >&2
exit 0