Files
x/Makefile
T
sneak 09ec70009d Verify .golangci.yml against the linter schema in make lint
golangci-lint ignores keys it does not know and silently runs with
defaults, which is how the v1-era settings went unapplied. make lint now
runs golangci-lint config verify before golangci-lint run, in both the
Docker and the in-image paths.
2026-11-01 16:31:30 -08:00

116 lines
3.7 KiB
Makefile

# sneak.berlin/go/x
#
# This Makefile is the single source of truth for how this repo is built,
# tested, linted, and formatted. Always use these targets rather than
# invoking the underlying tools directly.
.PHONY: all build install test lint fmt fmt-go fmt-md fmt-check \
fmt-check-go fmt-check-md check docker hooks tidy setup clean
BINARY := sutil
VERSION := $(shell git describe --always --dirty 2>/dev/null || echo dev)
GOLDFLAGS := -X main.Version=$(VERSION)
GO_DIRS := cmd internal pkg
# golangci/golangci-lint:v2.15.0, 2026-10-16 (keep in sync with Dockerfile)
GOLANGCI_LINT_IMAGE := golangci/golangci-lint@sha256:fbfcfd12a6f8d7f1b97b3362ca80fc2a244d46863148c73cb88e7793af96c481
# flags are repeated here (also in .prettierrc) so this Makefile works
# standalone when copied as a template
PRETTIER := yarn run --silent prettier
PRETTIER_FLAGS := --tab-width 4 --prose-wrap always
MARKDOWN_GLOB := '**/*.md'
all: build
# cgo stays off everywhere: builds are static and the tests do not use
# -race, which would require a C toolchain.
export CGO_ENABLED := 0
# Build the sutil binary in the repo root with the git version embedded.
build:
go build -trimpath -ldflags "$(GOLDFLAGS)" -o $(BINARY) ./cmd/$(BINARY)
# Install sutil into $(go env GOBIN) (or $GOPATH/bin).
install:
go install -trimpath -ldflags "$(GOLDFLAGS)" ./cmd/$(BINARY)
# Run the tests quietly; on failure rerun verbosely for diagnostics and
# still fail.
test:
@go test -timeout 30s -cover ./... || \
{ echo "--- Rerunning with -v for details ---"; \
go test -timeout 30s -v ./...; exit 1; }
# Lint with the pinned golangci-lint image when docker is available so local
# results match CI exactly. Inside the Docker build (where there is no
# docker) the image's own golangci-lint binary is used. The host module
# cache is shared read-only; the linter and build caches live in named
# volumes so repeated runs are fast.
#
# .golangci.yml is verified against the linter's schema first: golangci-lint
# otherwise ignores keys it does not know and silently runs with defaults.
LINT_COMMAND := golangci-lint config verify && golangci-lint run ./...
lint:
@if command -v docker >/dev/null 2>&1; then \
docker run --rm \
-v "$(CURDIR)":/src \
-v "$$(go env GOMODCACHE)":/go/pkg/mod:ro \
-v sutil-golangci-lint-cache:/root/.cache/golangci-lint \
-v sutil-go-build-cache:/root/.cache/go-build \
-w /src $(GOLANGCI_LINT_IMAGE) sh -c '$(LINT_COMMAND)'; \
else \
$(LINT_COMMAND); \
fi
# Format everything (writes files).
fmt: fmt-go fmt-md
fmt-go:
gofmt -w $(GO_DIRS)
fmt-md:
$(PRETTIER) --write $(MARKDOWN_GLOB) $(PRETTIER_FLAGS)
# Check formatting without writing anything.
fmt-check: fmt-check-go fmt-check-md
fmt-check-go:
@unformatted="$$(gofmt -l $(GO_DIRS))"; \
if [ -n "$$unformatted" ]; then \
echo "gofmt: the following files need formatting:"; \
echo "$$unformatted"; \
exit 1; \
fi
fmt-check-md:
$(PRETTIER) --check $(MARKDOWN_GLOB) $(PRETTIER_FLAGS)
# Everything CI gates on. Must not modify any files.
check: test lint fmt-check
# Build the Docker image; the Dockerfile runs the same checks as `make check`.
docker:
docker build -t $(BINARY) .
# Install the pre-commit hook.
hooks:
@printf '#!/bin/sh\nset -e\n' > .git/hooks/pre-commit
@if [ -f go.mod ]; then \
printf 'go mod tidy\ngo fmt ./...\ngit diff --exit-code -- go.mod go.sum || { echo "go mod tidy changed files; please stage and retry"; exit 1; }\n' >> .git/hooks/pre-commit; \
fi
@printf 'make check\n' >> .git/hooks/pre-commit
@chmod +x .git/hooks/pre-commit
# Tidy go.mod and go.sum.
tidy:
go mod tidy
# One-time developer setup: install the pinned prettier for markdown checks.
setup:
yarn install --frozen-lockfile
clean:
rm -f $(BINARY)