build(seaweedfs): re-pin the in-tree build from make update

The in-tree build pinned its source, base image and toolchain by hand,
and nothing moved them when `make update` vendored a new chart, so a
bump would build one release's weed into another release's image, or
keep patching a release that already carries the fix.

Pin the source archive by checksum and the upstream image by digest as
build arguments, compile with the toolchain upstream's own builder uses
for the tag, and let `make update` re-pin all of them from the vendored
chart and fail when the patches no longer apply. The tests of the
patched packages now run once rather than once per target platform,
and `weed version` names the build.

Assisted-by: LLM
Signed-off-by: Alexey Artamonov <aleksei.artamonov@aenix.io>
This commit is contained in:
Alexey Artamonov authored and Aleksei Sviridkin committed 2026-10-13 16:22:44 +03:00
1 parent d2c6b85cac
commit 5592a3f65d
2 files changed
+66 -17

No files matched your search

+31
View File
@@ -4,6 +4,7 @@ SEAWEEDFS_TAG=$(shell grep -F 'ARG VERSION=' images/seaweedfs/Dockerfile | cut -
include ../../../hack/common-envs.mk
include ../../../hack/package.mk
.PHONY: image
image:
docker buildx build images/seaweedfs \
$(call image-tags,seaweedfs,$(SEAWEEDFS_TAG)) \
@@ -61,4 +62,34 @@ update:
patch --no-backup-if-mismatch -p4 < patches/s3-service-name-consumers.patch
patch --no-backup-if-mismatch -p4 < patches/cluster-scoped-names-per-namespace.patch
#patch --no-backup-if-mismatch -p4 < patches/retention-policy-delete.yaml
$(MAKE) update-image
# Re-pins images/seaweedfs/Dockerfile to the vendored chart's appVersion: the
# source archive checksum, the upstream image digest and upstream's builder
# toolchain for that tag. The patches are Go, so they are checked against the
# whole source tree of the tag; once a release carries a fix, its patch stops
# applying here and is dropped.
.PHONY: update-image
update-image:
version=$$(yq e '.appVersion' charts/seaweedfs/Chart.yaml) && \
upstream=$$(docker buildx imagetools inspect "chrislusf/seaweedfs:$${version}" --format '{{json .Manifest}}' | yq e '.digest' -) && \
case "$$upstream" in sha256:*) ;; *) echo "ERROR: no digest for chrislusf/seaweedfs:$${version}" >&2; exit 1;; esac && \
$(SED_INPLACE) -e "s/^ARG VERSION=.*/ARG VERSION=$${version}/" -e "s/^ARG UPSTREAM_DIGEST=.*/ARG UPSTREAM_DIGEST=$${upstream}/" images/seaweedfs/Dockerfile && \
tmpdir=$$(mktemp -d) && \
{ curl --fail --silent --show-error --location -o "$$tmpdir/source.tar.gz" \
"https://github.com/seaweedfs/seaweedfs/archive/refs/tags/$${version}.tar.gz" && \
mkdir "$$tmpdir/src" && tar -xzf "$$tmpdir/source.tar.gz" --strip-components=1 -C "$$tmpdir/src" || { rm -rf "$$tmpdir"; exit 1; }; } && \
source=$$(sha256sum "$$tmpdir/source.tar.gz" | cut -d' ' -f1) && \
$(SED_INPLACE) "s/^ARG SOURCE_SHA256=.*/ARG SOURCE_SHA256=$${source}/" images/seaweedfs/Dockerfile && \
{ git -C "$$tmpdir/src" apply --check $(CURDIR)/images/seaweedfs/patches/*.diff || \
{ echo "ERROR: images/seaweedfs/patches/*.diff no longer apply to seaweedfs $${version}; regenerate them, or drop the ones the new tag already carries" >&2; \
rm -rf "$$tmpdir"; exit 1; }; } && \
golang=$$(sed -n 's/^FROM --platform=\$$BUILDPLATFORM \([^ ]*\) AS builder$$/\1/p' "$$tmpdir/src/docker/Dockerfile.go_build") && \
{ [ -n "$$golang" ] || { echo "ERROR: no builder FROM line in upstream docker/Dockerfile.go_build $${version}" >&2; rm -rf "$$tmpdir"; exit 1; }; } && \
builder=$$(docker buildx imagetools inspect "$$golang" --format '{{json .Manifest}}' | yq e '.digest' -) && \
{ case "$$builder" in sha256:*) ;; *) echo "ERROR: no digest for $${golang}" >&2; rm -rf "$$tmpdir"; exit 1;; esac; } && \
$(SED_INPLACE) "s|^FROM --platform=\$$BUILDPLATFORM [^ ]* AS builder$$|FROM --platform=\$$BUILDPLATFORM $${golang}@$${builder} AS builder|" images/seaweedfs/Dockerfile && \
{ grep -qF "FROM --platform=\$$BUILDPLATFORM $${golang}@$${builder} AS builder" images/seaweedfs/Dockerfile || \
{ echo "ERROR: the builder FROM line in images/seaweedfs/Dockerfile was not re-pinned; its shape no longer matches the update recipe" >&2; rm -rf "$$tmpdir"; exit 1; }; } && \
rm -rf "$$tmpdir"
@@ -12,39 +12,57 @@
# about a gigabyte of a single object in memory, is OOM-killed under the 512Mi
# limit the S3 deployment gets from its resources preset, and the client sees
# the response cut off tens of megabytes in:
# https://github.com/cozystack/cozystack/issues/3782. Upstream carries the same
# defect on master, tracked as seaweedfs/seaweedfs#11672; drop the patch on the
# first release that carries a fix.
# Keep in step with the chart appVersion pulled by `make update`, and with the
# base image below: the patched binary replaces this version's, so building it
# from another tag would run one version's weed against the rest of another's
# image.
# https://github.com/cozystack/cozystack/issues/3782. Upstream fixed it in
# seaweedfs/seaweedfs#11674 after 4.48; drop the patch on the first vendored
# release that carries it.
#
# `make update` re-pins VERSION from the vendored chart, SOURCE_SHA256 from the
# source archive of that tag, UPSTREAM_DIGEST from the upstream image of that
# tag and the builder from upstream's docker/Dockerfile.go_build, and checks
# that the patches still apply.
ARG VERSION=4.45
ARG SOURCE_SHA256=800a91693e2a4e974ef0e2a157b6a04eff9f4df507303b1cff31b0601081fc30
ARG UPSTREAM_DIGEST=sha256:fc9f76fa993ad69966ffeb2f65d0318fcae39c6f8e20cf68ef7b3a5cb97769e5
FROM --platform=$BUILDPLATFORM golang:1.26@sha256:eb36c1664dd974cde625f736e02c204383deebe03977365caaec5bf49f794348 AS builder
# The Go toolchain of upstream's builder (docker/Dockerfile.go_build), which
# compiles the upstream weed.
FROM --platform=$BUILDPLATFORM golang:1.26-alpine@sha256:3082400e369fa24d5fc60bca20edab3f6d604e0c5a690ec66b295eff4dd87ade AS builder
ARG GOPROXY
ARG VERSION
ARG TARGETOS
ARG TARGETARCH
ARG SOURCE_SHA256
WORKDIR /workspace
RUN apk add --no-cache git curl
RUN curl -sSL https://github.com/seaweedfs/seaweedfs/archive/refs/tags/${VERSION}.tar.gz | tar -xzf- --strip=1
WORKDIR /go/src/github.com/seaweedfs/seaweedfs
RUN curl -fsSL -o /tmp/source.tar.gz https://github.com/seaweedfs/seaweedfs/archive/refs/tags/${VERSION}.tar.gz && \
echo "${SOURCE_SHA256} /tmp/source.tar.gz" | sha256sum -c - && \
tar -xzf /tmp/source.tar.gz --strip-components=1 && rm /tmp/source.tar.gz
COPY patches /patches
RUN git apply /patches/*.diff
ENV CGO_ENABLED=0
# go build never compiles a _test.go, so nothing else runs the tests the
# patches carry. The list is read into a variable first: a for loop drops the
# exit status of a command substitution, so a patch git cannot read would leave
# the list empty and the step green.
RUN files=$(git apply --numstat /patches/*.diff) || exit 1; \
for dir in $(printf '%s\n' "$files" | cut -f3 | grep '\.go$' | xargs -r -n1 dirname | sort -u); do \
go test -race "./$dir" || exit 1; \
go test "./$dir" || exit 1; \
done
RUN cd weed && GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o /workspace/weed-bin .
# Declared after the tests so they run once on the build platform rather than
# once per target platform.
ARG TARGETOS
ARG TARGETARCH
FROM chrislusf/seaweedfs:${VERSION}@sha256:fc9f76fa993ad69966ffeb2f65d0318fcae39c6f8e20cf68ef7b3a5cb97769e5
COPY --from=builder /workspace/weed-bin /usr/bin/weed
# The source archive carries no git history for upstream's `git rev-parse`, so
# the commit field of `weed version` names this build instead.
RUN cd weed && GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-X github.com/seaweedfs/seaweedfs/weed/util/version.COMMIT=cozystack-patched" \
-o /out/weed .
FROM chrislusf/seaweedfs:${VERSION}@${UPSTREAM_DIGEST}
COPY --from=builder /out/weed /usr/bin/weed