# The lint phase, the test phase and a development environment.
# script/lint and script/test each build one phase alone; a plain
# `docker build .` builds both, because the last stage copies a file from
# each. Formatting is checked on the host by script/fmt-check, not here.

# Lint phase
# golangci/golangci-lint:v2.14.0, 2026-10-04
FROM golangci/golangci-lint@sha256:ad862ba6b3798cbe0fd9fd7408d498fd74fbd2623a92406b2fd3898faf0bf98f AS lint

WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN golangci-lint run --config .golangci.yml ./...

# Test phase. -race needs cgo and so a C compiler, which the Debian Go
# image ships.
# golang:1.26.8-trixie, 2026-10-04. It carries Go 1.26.8, the version
# script/bootstrap installs on the host; change both together, and the
# same image in the last stage.
FROM golang@sha256:eae2aaa6add2936cbf350dd0d2628b363461542f0c4b3c0b558957e0f2997379 AS test

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; }

# Development environment, and the last stage: a plain `docker build .`
# builds this one. It holds the source tree in /src, what
# script/bootstrap installs, and keyfunc built from that tree on the
# PATH. 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.8-trixie, 2026-10-04
FROM golang@sha256:eae2aaa6add2936cbf350dd0d2628b363461542f0c4b3c0b558957e0f2997379

COPY --from=lint /src/go.sum /dev/null
COPY --from=test /src/go.sum /dev/null

# A tar-stream context keeps the sender's file owners, which git refuses.
RUN git config --system --add safe.directory /src

WORKDIR /src

# script/bootstrap needs only script/ and the dependency manifests.
COPY script/ script/
COPY go.mod go.sum package.json yarn.lock ./
RUN script/bootstrap

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" && mv keyfunc /usr/local/bin/keyfunc
