build: Dockerfile.backend multistage lint stage (closes #17)
All checks were successful
check / check (push) Successful in 16s

Dockerfile.backend did not follow the Go multistage lint-stage pattern
REPO_POLICIES.md mandates, and dragged the whole git history into the
build context to resolve a version string.

- Add an `AS lint` stage on the hash-pinned golangci/golangci-lint
  image (v2.7.2, the same golangci-lint commit main already pins), which
  ships Go, gofmt, make and the linter, so nothing is installed in it.
  It runs `make fmt-check` then `make lint`.
- Add `COPY --from=lint /src/go.sum /dev/null` to the build stage so
  BuildKit cannot run the two stages in parallel and let a lint failure
  through.
- Stop compiling golangci-lint from source in the build stage.
- Drop `COPY .git /repo/.git`; the version now comes from
  `ARG VERSION=dev`, passed to the build via `make build VERSION=...`.
- Drop gcc and musl-dev, and the corresponding
  `-linkmode external -extldflags -static` in backend/Makefile. The
  build is now `CGO_ENABLED=0 go build -trimpath` with
  `-ldflags "-s -w -X main.Version=... -X main.Buildarch=..."`, which is
  static without a C toolchain.
- backend/Makefile's VERSION is now overridable and degrades to `dev`
  when git or .git is unavailable instead of emitting a git error and
  building an empty version string.
- Every FROM stays pinned by @sha256 with a version and date comment.

Runtime stage, exposed port and entrypoint are unchanged.
This commit is contained in:
2026-08-09 10:09:32 +00:00
parent fbfe1df349
commit bd2bc9f626
3 changed files with 46 additions and 20 deletions

View File

@@ -1,25 +1,22 @@
UNAME_S := $(shell uname -s)
VERSION := $(shell git describe --always --dirty)
# VERSION is overridable (the Dockerfile passes its ARG VERSION in) and
# degrades to "dev" when git is unavailable or there is no .git — the
# build must not depend on the repository history being in the build
# context.
VERSION ?= $(shell { git describe --always --dirty; } 2>/dev/null || echo dev)
BUILDARCH := $(shell uname -m)
BINARY := netwatch-server
GOLDFLAGS += -s -w
GOLDFLAGS += -X main.Version=$(VERSION)
GOLDFLAGS += -X main.Buildarch=$(BUILDARCH)
ifeq ($(UNAME_S),Darwin)
GOFLAGS := -ldflags "$(GOLDFLAGS)"
else
GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)"
endif
.PHONY: all build test lint fmt fmt-check check docker hooks run clean
all: build
build: ./$(BINARY)
./$(BINARY): $(shell find . -name '*.go' -type f) go.mod go.sum
go build -o $@ $(GOFLAGS) ./cmd/netwatch-server/
build:
CGO_ENABLED=0 go build -trimpath -ldflags "$(GOLDFLAGS)" \
-o ./$(BINARY) ./cmd/netwatch-server/
test:
timeout 30 go test ./...