From af3f91a78f64ce8d96f9a48978feb02bf10b650c Mon Sep 17 00:00:00 2001 From: Marcus Vorwaller Date: Tue, 31 Mar 2026 03:10:58 -0700 Subject: [PATCH] Pin lint tooling and format checks Nightshift-Task: lint-fix Nightshift-Ref: https://github.com/marcus/nightshift --- .github/workflows/ci.yml | 17 +++++++++---- Makefile | 54 +++++++++++++++++++++++++++++++++------- scripts/pre-commit.sh | 51 +++++++++++++------------------------ 3 files changed, 74 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8fc5686..70426dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version-file: go.mod - name: Download dependencies run: go mod download @@ -44,9 +44,16 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version-file: go.mod + + - name: Download dependencies + run: go mod download + + - name: Check formatting + run: make fmt-check + + - name: Run go vet + run: make vet - name: Run golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - version: latest + run: make lint diff --git a/Makefile b/Makefile index 088be01..5c5725e 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,13 @@ -.PHONY: build test test-verbose test-race coverage coverage-html lint clean deps check install calibrate-providers install-hooks help +.PHONY: build test test-verbose test-race coverage coverage-html fmt fmt-check vet lint lint-install clean deps check install calibrate-providers install-hooks help # Binary name BINARY=nightshift PKG=./cmd/nightshift +GO_FILES := $(shell git ls-files '*.go') +TOOLS_BIN := $(CURDIR)/bin +GOLANGCI_LINT := $(TOOLS_BIN)/golangci-lint +GOLANGCI_LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint +GOLANGCI_LINT_VERSION := v1.64.8 # Build the binary build: @@ -41,10 +46,38 @@ coverage-html: coverage go tool cover -html=coverage.out -o coverage.html @echo "Coverage report generated: coverage.html" -# Run golangci-lint (if installed) -lint: - @which golangci-lint > /dev/null || (echo "golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" && exit 1) - golangci-lint run +# Format Go source files +fmt: + @if [ -n "$(strip $(GO_FILES))" ]; then gofmt -w $(GO_FILES); fi + +# Verify Go source files are formatted +fmt-check: + @files='$(strip $(GO_FILES))'; \ + if [ -z "$$files" ]; then \ + exit 0; \ + fi; \ + unformatted="$$(gofmt -l $$files)"; \ + if [ -n "$$unformatted" ]; then \ + echo "$$unformatted"; \ + exit 1; \ + fi + +# Run go vet +vet: + go vet ./... + +# Install pinned golangci-lint version into the repo-local tool bin +lint-install: + @mkdir -p "$(TOOLS_BIN)" + @current_version="$$(if [ -x "$(GOLANGCI_LINT)" ]; then "$(GOLANGCI_LINT)" version --format short 2>/dev/null || true; fi)"; \ + if [ "$$current_version" != "$(GOLANGCI_LINT_VERSION)" ]; then \ + echo "Installing golangci-lint $(GOLANGCI_LINT_VERSION)"; \ + GOBIN="$(TOOLS_BIN)" go install "$(GOLANGCI_LINT_PKG)@$(GOLANGCI_LINT_VERSION)"; \ + fi + +# Run pinned golangci-lint +lint: lint-install + "$(GOLANGCI_LINT)" run ./... # Clean build artifacts clean: @@ -57,8 +90,8 @@ deps: go mod download go mod tidy -# Run all checks (test + lint) -check: test lint +# Run all checks +check: fmt-check vet test lint # Show help help: @@ -69,10 +102,13 @@ help: @echo " test-race - Run tests with race detection" @echo " coverage - Run tests with coverage report" @echo " coverage-html - Generate HTML coverage report" - @echo " lint - Run golangci-lint" + @echo " fmt - Format Go files" + @echo " fmt-check - Verify Go files are formatted" + @echo " vet - Run go vet" + @echo " lint - Run pinned golangci-lint" @echo " clean - Clean build artifacts" @echo " deps - Download and tidy dependencies" - @echo " check - Run tests and lint" + @echo " check - Run formatting, vet, tests, and lint" @echo " install - Build and install to Go bin directory" @echo " calibrate-providers - Compare local Claude/Codex session usage for calibration" @echo " install-hooks - Install git pre-commit hook" diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index c597d65..5586208 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -3,53 +3,36 @@ # Install: make install-hooks (or: ln -sf ../../scripts/pre-commit.sh .git/hooks/pre-commit) set -euo pipefail +ROOT_DIR="$(git rev-parse --show-toplevel)" +cd "$ROOT_DIR" + PASS=0 FAIL=0 echo "🪡 pre-commit checks" -# --- gofmt: only staged .go files --- -STAGED_GO=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$' || true) +run_check() { + local target="$1" + local output -if [[ -n "$STAGED_GO" ]]; then - printf " %-20s" "gofmt" - UNFORMATTED=$(echo "$STAGED_GO" | xargs gofmt -l 2>&1) - if [[ -z "$UNFORMATTED" ]]; then + printf " %-20s" "$target" + if output=$(make "$target" 2>&1); then echo "✓" PASS=$((PASS+1)) - else - echo "✗ FAILED — run: gofmt -w ." - echo "$UNFORMATTED" | sed 's/^/ /' - FAIL=$((FAIL+1)) + return 0 fi -else - printf " %-20s" "gofmt" - echo "– (no .go files staged)" -fi -# --- go vet --- -printf " %-20s" "go vet" -VET_OUT=$(go vet ./... 2>&1) -if [[ $? -eq 0 ]]; then - echo "✓" - PASS=$((PASS+1)) -else echo "✗ FAILED" - echo "$VET_OUT" | sed 's/^/ /' + if [[ -n "$output" ]]; then + echo "$output" | sed 's/^/ /' + fi FAIL=$((FAIL+1)) -fi + return 0 +} -# --- go build --- -printf " %-20s" "go build" -BUILD_OUT=$(go build ./... 2>&1) -if [[ $? -eq 0 ]]; then - echo "✓" - PASS=$((PASS+1)) -else - echo "✗ FAILED" - echo "$BUILD_OUT" | sed 's/^/ /' - FAIL=$((FAIL+1)) -fi +run_check "fmt-check" +run_check "vet" +run_check "lint" echo "" if [[ $FAIL -gt 0 ]]; then