@@ -428,20 +428,69 @@ nilaway-golangci-build:
428428 golangci-lint custom --version " $( GOLANGCI_LINT_VERSION) " --name custom-gcl
429429
430430# Run NilAway through the custom golangci-lint module plugin.
431+ #
432+ # NilAway is run once per package instead of once over ./... because a single
433+ # whole-module run blows up memory. Each invocation therefore keeps its own
434+ # tight caps (GOMAXPROCS=1, GOGC=10, GOMEMLIMIT=512MiB). Those caps are
435+ # per-process, so the ~45 invocations can safely overlap: NILAWAY_JOBS of them
436+ # run at a time, bounding peak usage at roughly NILAWAY_JOBS x GOMEMLIMIT.
437+ # Concurrent invocations share one GOLANGCI_LINT_CACHE, so they need
438+ # --allow-parallel-runners; without it golangci-lint's start-up file lock makes
439+ # every overlapping run fail with "parallel golangci-lint is running".
440+ #
441+ # Each invocation writes its output to its own scratch file, which the parent
442+ # prints in package order once the run finishes. Writing straight to stdout
443+ # would interleave one package's findings with another's as soon as a report
444+ # exceeded the pipe's atomic-write size. NILAWAY_JOBS must be a positive
445+ # integer: `xargs -P 0` means "unlimited" and would remove the memory bound
446+ # this whole arrangement depends on.
447+ NILAWAY_JOBS ?= 4
448+
431449nilaway : pricing-snapshot ensure-embed-dir nilaway-golangci-build
432450 @set -e; \
451+ case " $( NILAWAY_JOBS) " in \
452+ ' ' | * [! 0-9]* ) \
453+ echo " nilaway: NILAWAY_JOBS must be a positive integer (got '$( NILAWAY_JOBS) ')" >&2 ; \
454+ exit 1;; \
455+ esac ; \
456+ njobs=$$(( $(NILAWAY_JOBS ) + 0 ) ); \
457+ if [ " $$ njobs" -lt 1 ]; then \
458+ echo " nilaway: NILAWAY_JOBS must be at least 1 (got '$( NILAWAY_JOBS) ')" >&2 ; \
459+ exit 1; \
460+ fi ; \
433461 root=$$(pwd ) ; \
434462 dirs=$$(go list -f '{{.Dir}}' ./... ) ; \
435- for dir in $$ dirs; do \
463+ pkgs= $$( for dir in $$dirs; do \
436464 if [ " $$ dir" = " $$ root" ]; then \
437- pkg= " ." ; \
465+ printf ' %s\n ' " ." ; \
438466 else \
439- pkg= " ./$$ {dir#$$ root/}" ; \
467+ printf ' %s\n ' " ./$$ {dir#$$ root/}" ; \
440468 fi ; \
441- echo " $( CUSTOM_GCL) run --config .golangci.nilaway.yml $$ pkg" ; \
442- GOMAXPROCS=$$ {GOMAXPROCS:-1} GOGC=$$ {GOGC:-10} GOMEMLIMIT=$$ {GOMEMLIMIT:-512MiB} \
443- $(CUSTOM_GCL ) run --config .golangci.nilaway.yml " $$ pkg" ; \
444- done
469+ done); \
470+ if [ -z " $$ pkgs" ]; then echo " nilaway: no packages to lint" >&2 ; exit 1; fi ; \
471+ NILAWAY_OUT_DIR=$$(mktemp -d ) ; \
472+ export NILAWAY_OUT_DIR; \
473+ trap ' rm -f "$$NILAWAY_OUT_DIR"/*; rmdir "$$NILAWAY_OUT_DIR"' EXIT HUP INT TERM; \
474+ set +e; \
475+ printf ' %s\n' " $$ pkgs" | awk ' { printf "%d:%s\n", NR, $$0 }' | tr ' \n' ' \0' \
476+ | xargs -0 -n 1 -P " $$ njobs" sh -c ' \
477+ n=$$ {1%%:* }; \
478+ pkg=$$ {1#* :}; \
479+ cmd=" $( CUSTOM_GCL) run --allow-parallel-runners --config .golangci.nilaway.yml $$ pkg" ; \
480+ out=$$(GOMAXPROCS=$${GOMAXPROCS:-1} GOGC=$${GOGC:-10} GOMEMLIMIT=$${GOMEMLIMIT:-512MiB} \
481+ $(CUSTOM_GCL ) run --allow-parallel-runners \
482+ --config .golangci.nilaway.yml " $$ pkg" 2>&1 ); \
483+ status=$$? ; \
484+ { printf " %s\n" " $$ cmd" ; \
485+ if [ -n " $$ out" ]; then printf " %s\n" " $$ out" ; fi ; \
486+ } > " $$ NILAWAY_OUT_DIR/$$ n" ; \
487+ exit $$ status' sh; \
488+ rc=$$? ; \
489+ set -e; \
490+ ls " $$ NILAWAY_OUT_DIR" | sort -n | while IFS= read -r n; do \
491+ cat " $$ NILAWAY_OUT_DIR/$$ n" ; \
492+ done ; \
493+ exit $$ rc
445494
446495# Install pinned local lint tools.
447496lint-tools :
0 commit comments