From de109b65d8b2325675c96f3992037b5b493304bd Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 8 Jul 2026 01:04:36 +0100 Subject: [PATCH] Lint nested Go modules from their own module root in pre-commit golangci-lint was invoked from the repo root for every staged Go package, so files in nested modules like tests/integration/mock-github-server failed typechecking with 'main module does not contain package' and could never be committed. Group staged package dirs by their nearest enclosing go.mod and lint nested modules from their own root. --- .husky/pre-commit | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 080d7ea80..d19bff8bd 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -144,9 +144,27 @@ python3 scripts/release_control/format_staged_go.py if command -v golangci-lint >/dev/null 2>&1; then if staged_files_match '(^|/).*\.go$|(^|/)go\.(mod|sum|work|work\.sum)$|^\.golangci\.ya?ml$'; then echo "Running golangci-lint..." - # Lint only packages containing staged Go files, not the entire repo - STAGED_GO_PKGS=$(git diff --cached --name-only | grep '\.go$' | xargs -I{} dirname {} 2>/dev/null | sort -u | sed 's|^|./|' | tr '\n' ' ') - if [ -z "$STAGED_GO_PKGS" ]; then + # Lint only packages containing staged Go files, not the entire repo. + # Packages in nested Go modules (own go.mod, e.g. + # tests/integration/mock-github-server) must lint from their module + # root or the typecheck fails with "main module does not contain + # package"; group staged dirs by nearest enclosing go.mod. + STAGED_GO_DIRS=$(git diff --cached --name-only | grep '\.go$' | xargs -I{} dirname {} 2>/dev/null | sort -u) + STAGED_GO_PKGS="" + NESTED_GO_MODULES="" + for staged_dir in $STAGED_GO_DIRS; do + module_root="$staged_dir" + while [ "$module_root" != "." ] && [ ! -f "$module_root/go.mod" ]; do + module_root=$(dirname "$module_root") + done + if [ "$module_root" = "." ]; then + STAGED_GO_PKGS="$STAGED_GO_PKGS ./$staged_dir" + else + NESTED_GO_MODULES=$(printf '%s\n%s' "$NESTED_GO_MODULES" "$module_root") + fi + done + NESTED_GO_MODULES=$(printf '%s\n' "$NESTED_GO_MODULES" | sed '/^$/d' | sort -u) + if [ -z "$STAGED_GO_PKGS" ] && [ -z "$NESTED_GO_MODULES" ]; then STAGED_GO_PKGS="./..." fi # Report only issues introduced by the staged diff. Pre-existing @@ -158,7 +176,13 @@ if command -v golangci-lint >/dev/null 2>&1; then if [ -n "$NEW_FROM_REV" ]; then NEW_FROM_FLAG="--new-from-rev=$NEW_FROM_REV" fi - GOMAXPROCS="${GOMAXPROCS:-2}" golangci-lint run --concurrency "${GOLANGCI_LINT_CONCURRENCY:-2}" --timeout "${GOLANGCI_LINT_TIMEOUT:-5m}" $NEW_FROM_FLAG $STAGED_GO_PKGS + if [ -n "$STAGED_GO_PKGS" ]; then + GOMAXPROCS="${GOMAXPROCS:-2}" golangci-lint run --concurrency "${GOLANGCI_LINT_CONCURRENCY:-2}" --timeout "${GOLANGCI_LINT_TIMEOUT:-5m}" $NEW_FROM_FLAG $STAGED_GO_PKGS + fi + for nested_module in $NESTED_GO_MODULES; do + echo "Running golangci-lint in nested module $nested_module..." + (cd "$nested_module" && GOMAXPROCS="${GOMAXPROCS:-2}" golangci-lint run --concurrency "${GOLANGCI_LINT_CONCURRENCY:-2}" --timeout "${GOLANGCI_LINT_TIMEOUT:-5m}" $NEW_FROM_FLAG ./...) + done else echo "Skipping golangci-lint (no staged Go/module/linter changes)." fi