# The lint phase, the test phase and the build. script/lint and # script/test each build one phase alone; a plain `docker build .` builds # both, because the build stage copies a file from each. Formatting is # checked on the host by script/fmt-check, not here. # Lint phase # golangci/golangci-lint:v2.12.2, 2026-09-07 FROM golangci/golangci-lint@sha256:5cceeef04e53efe1470638d4b4b4f5ceefd574955ab3941b2d9a68a8c9ad5240 AS lint WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN golangci-lint run --config .golangci.yml ./... # Test phase # golang:1.26-alpine, 2026-09-07 FROM golang@sha256:ce864e7223ac17b1775e6fd0b4c0db580c2eb50e7953a427916379e4b92a1628 AS test # -race needs cgo, and cgo needs a C toolchain. RUN apk add --no-cache gcc musl-dev WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go test -timeout 90s -race -cover ./... || \ { echo "--- Rerunning with -v for details ---"; \ go test -timeout 90s -race -v ./...; exit 1; } # Build stage. Nothing is wanted from either phase above; the copies # are what make BuildKit build them first, so this stage cannot run # unless lint and test passed. # golang:1.26-alpine, 2026-09-07 FROM golang@sha256:ce864e7223ac17b1775e6fd0b4c0db580c2eb50e7953a427916379e4b92a1628 AS builder COPY --from=lint /src/go.sum /dev/null COPY --from=test /src/go.sum /dev/null RUN apk add --no-cache make git WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . # The version stamped into the binary: the VERSION build argument when one # is given, otherwise `git describe --tags --always` of the .git in the # build context. A context that carries .git and still yields no version # fails the build; with neither, as from a source tarball, it is "dev". ARG VERSION RUN version="${VERSION:-$(git describe --tags --always || echo dev)}"; \ if [ -e .git ] && { [ -z "$version" ] || [ "$version" = dev ] || \ [ "$version" = unknown ]; }; then \ echo "no version could be derived although the build context carries .git" >&2; \ exit 1; \ fi; \ make build VERSION="$version" # alpine:3.23, 2026-09-07 FROM alpine@sha256:fd791d74b68913cbb027c6546007b3f0d3bc45125f797758156952bc2d6daf40 COPY --from=builder /src/keyfunc /usr/local/bin/keyfunc ENTRYPOINT ["keyfunc"]