From 1100080f11e8304a9191bc82b3e66f3ef7eb3cbf Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Wed, 6 May 2026 10:16:16 +0200 Subject: [PATCH 1/2] fix(envrc): correct hooks detection for worktrees and refresh tooling hints The hooks check used a literal `.git/hooks/pre-commit` path, which fails in git worktrees (where `.git` is a file pointing to the worktree's gitdir). Replace with `git rev-parse --git-path hooks` so detection works for both regular repos and worktrees. While here: - Drop the dead Husky branch and the missing `install-husky.sh` reference (project migrated to lefthook; only `install-hooks.sh` remains). - Bump `REQUIRED_VERSION` from 1.25 to 1.26 to match `go.mod`. - Fix the `gosec` install hint (404 repo + non-existent snap package) to the canonical `go install github.com/securego/gosec/v2/cmd/gosec@latest`. - Stop forcing `CGO_ENABLED=0`, `GOOS=linux`, `GOARCH=amd64`. These belong in build commands, not a per-shell env: forcing CGO off silently breaks `go test -race`, and pinning GOOS/GOARCH breaks non-amd64 dev hosts. - Replace the hardcoded "60.1% coverage" claim with a pointer to `make test-coverage` so the help text doesn't drift. Signed-off-by: Sebastian Mendel --- .envrc | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/.envrc b/.envrc index 3bf474406a..4d61bd3ff2 100644 --- a/.envrc +++ b/.envrc @@ -25,7 +25,7 @@ if ! command -v go &> /dev/null; then fi GO_VERSION=$(go version | grep -o 'go[0-9]\+\.[0-9]\+' | sed 's/go//') -REQUIRED_VERSION="1.25" +REQUIRED_VERSION="1.26" if echo "$GO_VERSION $REQUIRED_VERSION" | awk '{exit ($1 < $2)}'; then echo -e "${GREEN}✅ Go $GO_VERSION detected${NC}" @@ -49,54 +49,39 @@ check_tool() { echo -e "${BLUE}🛠️ Checking required tools...${NC}" check_tool "golangci-lint" "go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" -check_tool "gosec" "sudo snap install gosec (or download from https://github.com/securecodewarrior/gosec/releases)" +check_tool "gosec" "go install github.com/securego/gosec/v2/cmd/gosec@latest" check_tool "docker" "https://docs.docker.com/get-docker/" # CRITICAL: Git hooks verification and enforcement echo "" echo -e "${BLUE}🪝 Verifying Git hooks setup...${NC}" -HOOK_FILE=".git/hooks/pre-commit" -HUSKY_HOOK=".husky/pre-commit" -HOOKS_CONFIGURED=false +# Resolve via git rev-parse so this works in worktrees (.git is a file, not a dir) +HOOK_FILE="$(git rev-parse --git-path hooks 2>/dev/null)/pre-commit" if [[ -f "$HOOK_FILE" ]] && grep -q "lefthook" "$HOOK_FILE" 2>/dev/null; then - echo -e "${GREEN}✅ Native Git hooks properly configured (lefthook)${NC}" - HOOKS_CONFIGURED=true -elif [[ -f "$HUSKY_HOOK" ]] && [[ -f "package.json" ]]; then - echo -e "${GREEN}✅ Husky hooks properly configured${NC}" - HOOKS_CONFIGURED=true -fi - -if [[ "$HOOKS_CONFIGURED" == "false" ]]; then + echo -e "${GREEN}✅ Git hooks configured (lefthook)${NC}" +else echo -e "${RED}❌ CRITICAL: Git hooks not configured!${NC}" echo -e "${YELLOW} Without pre-commit hooks, your commits WILL FAIL the CI pipeline${NC}" echo "" - echo -e "${YELLOW}🔧 Choose hook installation method:${NC}" - echo -e " ${BLUE}Native (recommended):${NC} ./scripts/install-hooks.sh" - echo -e " ${BLUE}Husky (Node.js teams):${NC} ./scripts/install-husky.sh" - echo "" - - # Auto-install option + if [[ -t 0 ]]; then # Only if running interactively - read -p "🤔 Auto-install native Git hooks now? [Y/n] " -n 1 -r + read -p "🤔 Auto-install lefthook hooks now? [Y/n] " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then - echo -e "${BLUE}🔧 Installing native Git hooks...${NC}" + echo -e "${BLUE}🔧 Installing lefthook hooks...${NC}" if ./scripts/install-hooks.sh >/dev/null 2>&1; then echo -e "${GREEN}✅ Hooks installed successfully!${NC}" else - echo -e "${RED}❌ Hook installation failed - please run manually${NC}" + echo -e "${RED}❌ Hook installation failed — run: make setup${NC}" fi fi + else + echo -e "${YELLOW} Run: make setup${NC}" fi fi -# Set Go-specific environment variables -export CGO_ENABLED=0 -export GOOS=linux -export GOARCH=amd64 - # Add project tools to PATH if command -v go >/dev/null 2>&1; then export PATH="$(go env GOPATH)/bin:$PATH" @@ -130,7 +115,7 @@ echo "" echo -e "${YELLOW}🚀 Quick Commands:${NC}" echo " make help # Show all available commands" echo " make build # Build binary" -echo " make test # Run tests (current: 60.1% coverage)" +echo " make test # Run tests (see: make test-coverage)" echo " make lint-full # Complete linting suite (45+ rules)" echo " make dev-check # Run all development checks" echo " make dev-setup # Set up development environment" From 2a1c59355bc055577e1b6d349b0b5aa49b73de7d Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Wed, 6 May 2026 11:40:46 +0200 Subject: [PATCH 2/2] fix: address review feedback on .envrc/lefthook/Makefile cleanup - .envrc:23 missed the Go-version bump message; align with REQUIRED_VERSION. - .envrc:30 numeric awk comparison treated 1.9 as >= 1.26; split major/minor and compare as integers. - .envrc:60 git rev-parse can fail (no git, not in a repo) and set -e would abort the whole .envrc; guard the call and skip the hooks check cleanly. - lefthook.yml:174 had the same `.git/hooks/pre-commit` hardcoded path that fails in worktrees; mirror the .envrc fix. - Makefile: drop the snap/securecodewarrior/gosec install hints (snap pkg doesn't exist; the repo URL is 404) and use `go install github.com/securego/gosec/v2/cmd/gosec@latest` consistently. - Makefile:300 still hardcoded "60.1%" coverage; replace with a pointer to `make test-coverage` so it can't drift. Addresses gemini-code-assist and Copilot review comments on PR #598. Signed-off-by: Sebastian Mendel --- .envrc | 28 ++++++++++++++++++++++------ Makefile | 18 ++++++------------ lefthook.yml | 8 ++++++-- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/.envrc b/.envrc index 4d61bd3ff2..b505d083a3 100644 --- a/.envrc +++ b/.envrc @@ -19,15 +19,23 @@ fi echo -e "${BLUE}🔧 Verifying Ofelia development environment...${NC}" # Check Go version requirement +REQUIRED_VERSION="1.26" + if ! command -v go &> /dev/null; then - echo -e "${RED}❌ Go not found. Please install Go 1.25+${NC}" + echo -e "${RED}❌ Go not found. Please install Go ${REQUIRED_VERSION}+${NC}" exit 1 fi GO_VERSION=$(go version | grep -o 'go[0-9]\+\.[0-9]\+' | sed 's/go//') -REQUIRED_VERSION="1.26" -if echo "$GO_VERSION $REQUIRED_VERSION" | awk '{exit ($1 < $2)}'; then +# Compare major.minor as integers, not floats — naive numeric comparison +# would incorrectly treat 1.9 as greater than 1.26. +go_major=${GO_VERSION%%.*} +go_minor=${GO_VERSION#*.} +req_major=${REQUIRED_VERSION%%.*} +req_minor=${REQUIRED_VERSION#*.} + +if (( go_major > req_major )) || { (( go_major == req_major )) && (( go_minor >= req_minor )); }; then echo -e "${GREEN}✅ Go $GO_VERSION detected${NC}" else echo -e "${YELLOW}⚠️ Go $GO_VERSION found, but Go $REQUIRED_VERSION+ is recommended for this project${NC}" @@ -56,11 +64,19 @@ check_tool "docker" "https://docs.docker.com/get-docker/" echo "" echo -e "${BLUE}🪝 Verifying Git hooks setup...${NC}" -# Resolve via git rev-parse so this works in worktrees (.git is a file, not a dir) -HOOK_FILE="$(git rev-parse --git-path hooks 2>/dev/null)/pre-commit" +# Resolve via git rev-parse so this works in worktrees (.git is a file, not a dir). +# Tolerate failure (no git installed, direnv loaded outside a repo) so set -e +# doesn't abort the entire .envrc — just skip the hooks check. +HOOKS_DIR="" +if command -v git >/dev/null 2>&1; then + HOOKS_DIR="$(git rev-parse --git-path hooks 2>/dev/null || true)" +fi +HOOK_FILE="${HOOKS_DIR:+$HOOKS_DIR/pre-commit}" -if [[ -f "$HOOK_FILE" ]] && grep -q "lefthook" "$HOOK_FILE" 2>/dev/null; then +if [[ -n "$HOOK_FILE" ]] && [[ -f "$HOOK_FILE" ]] && grep -q "lefthook" "$HOOK_FILE" 2>/dev/null; then echo -e "${GREEN}✅ Git hooks configured (lefthook)${NC}" +elif [[ -z "$HOOK_FILE" ]]; then + echo -e "${YELLOW}⚠️ Skipping hooks check (not in a git repository)${NC}" else echo -e "${RED}❌ CRITICAL: Git hooks not configured!${NC}" echo -e "${YELLOW} Without pre-commit hooks, your commits WILL FAIL the CI pipeline${NC}" diff --git a/Makefile b/Makefile index d83c8079cb..f823f2d519 100644 --- a/Makefile +++ b/Makefile @@ -96,9 +96,8 @@ security-check: echo "✅ Security check passed"; \ else \ echo "❌ gosec not found. Install with:"; \ - echo " - Snap: sudo snap install gosec"; \ - echo " - Binary: https://github.com/securecodewarrior/gosec/releases"; \ - echo " - Or run: make dev-setup"; \ + echo " go install github.com/securego/gosec/v2/cmd/gosec@latest"; \ + echo " Or run: make dev-setup"; \ exit 1; \ fi @@ -214,14 +213,9 @@ dev-setup: @if command -v gosec >/dev/null 2>&1; then \ echo "✅ gosec already available"; \ else \ - echo "📥 Installing gosec via snap..."; \ - if command -v snap >/dev/null 2>&1; then \ - sudo snap install gosec; \ - else \ - echo "⚠️ gosec not found and snap unavailable. Install manually:"; \ - echo " - Snap: sudo snap install gosec"; \ - echo " - Binary: https://github.com/securecodewarrior/gosec/releases"; \ - fi; \ + echo "📥 Installing gosec..."; \ + go install github.com/securego/gosec/v2/cmd/gosec@latest; \ + echo "✅ gosec installed"; \ fi @go install github.com/daixiang0/gci@latest @echo "✅ gci installed" @@ -297,7 +291,7 @@ help: @echo " ci - Run CI checks locally" @echo " tidy - Tidy Go modules" @echo "" - @echo "📊 Current Test Coverage: 60.1%" + @echo "📊 Test Coverage: run 'make test-coverage' for current numbers" @echo "🎯 Quality: 45+ linting rules, security scanning, pre-commit hooks" build: diff --git a/lefthook.yml b/lefthook.yml index 017aa11037..1729258725 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -170,8 +170,12 @@ post-checkout: echo "" fi - # Check if hooks are installed (in case this is first checkout) - if [ ! -f .git/hooks/pre-commit ] || ! grep -q "lefthook" .git/hooks/pre-commit 2>/dev/null; then + # Check if hooks are installed (in case this is first checkout). + # Use git rev-parse so this works in worktrees, where .git is a file + # pointing at the worktree's gitdir rather than a directory. + hooks_dir=$(git rev-parse --git-path hooks 2>/dev/null || true) + hook_file="${hooks_dir:+$hooks_dir/pre-commit}" + if [ -z "$hook_file" ] || [ ! -f "$hook_file" ] || ! grep -q "lefthook" "$hook_file" 2>/dev/null; then echo "" echo "⚠️ Git hooks not installed! Run:" echo " make setup"