From 4f30e2d57b5f6b014882398f71a7cfc699139302 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 29 Aug 2026 07:40:57 +0800 Subject: [PATCH] fix(docker): repair embed packaging for backend/ module layout The Dockerfiles and the release workflow still assumed the pre-refactor tree: go.mod, go.sum and main.go now live under backend/, so `COPY go.mod go.sum` failed outright, and the Go module is the bare `Wavelet`, so the buildinfo ldflags pointed at github.com/Rain-kl/Wavelet and stamped nothing. The frontend export was also overlaid onto ./plugins/... rather than the driver_http path that `//go:embed all:dist` actually reads. Repoint every packaging path at backend/, correct the ldflags module prefix, and assert dist/index.html in both docker stages, in build-embedded and in the release workflow, so a silently empty static export can no longer ship an API-only binary. Also carry pnpm-workspace.yaml into the cached install layer. --- .github/workflows/build-release.yml | 14 +++++++++----- Makefile | 1 + docker/Dockerfile | 23 ++++++++++++++++------- docker/Dockerfile.backend | 8 +++++--- docker/Dockerfile.cross | 20 +++++++++++++------- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index ae89e8fe..796c6330 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -12,6 +12,7 @@ on: env: APP_NAME: wavelet + GO_DIR: backend GO_MAIN: ./main.go GO_BUILD_TAGS: embed_frontend GO_LDFLAGS: -s -w @@ -20,7 +21,7 @@ env: FRONTEND_DIR: frontend FRONTEND_BUILD_COMMAND: pnpm build:embed FRONTEND_OUT_DIR: frontend/out - EMBED_DIST_DIR: internal/router/root/dist + EMBED_DIST_DIR: backend/plugins/drivers/driver_http/dist EXTRA_FILES: | LICENSE README.md @@ -192,7 +193,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version-file: go.mod + go-version-file: ${{ env.GO_DIR }}/go.mod cache: true - name: Build binary @@ -212,18 +213,21 @@ jobs: binary_name="${binary_name}.exe" fi - ldflags="$GO_LDFLAGS -X github.com/Rain-kl/Wavelet/internal/buildinfo.Version=$VERSION -X github.com/Rain-kl/Wavelet/internal/buildinfo.BuildTime=$BUILD_DATE" + # Assert the embedded UI is present so a release cannot ship an API-only binary. + test -f "$EMBED_DIST_DIR/index.html" + + ldflags="$GO_LDFLAGS -X Wavelet/pkg/buildinfo.Version=$VERSION -X Wavelet/pkg/buildinfo.BuildTime=$BUILD_DATE" build_args=( -trimpath -ldflags "$ldflags" - -o "dist/$binary_name" + -o "$GITHUB_WORKSPACE/dist/$binary_name" ) if [[ -n "$GO_BUILD_TAGS" ]]; then build_args=(-tags "$GO_BUILD_TAGS" "${build_args[@]}") fi - go build "${build_args[@]}" "$GO_MAIN" + (cd "$GO_DIR" && go build "${build_args[@]}" "$GO_MAIN") - name: Package artifact id: package diff --git a/Makefile b/Makefile index f0bd7f54..46e21363 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ build-embedded: pnpm build:embed rm -rf backend/plugins/drivers/driver_http/dist cp -R frontend/out backend/plugins/drivers/driver_http/dist + test -f backend/plugins/drivers/driver_http/dist/index.html cd backend && go build \ -tags embed_frontend \ -ldflags "-s -w -X '$(MODULE)/pkg/buildinfo.Version=$(VERSION)' -X '$(MODULE)/pkg/buildinfo.BuildTime=$(BUILD_DATE)'" \ diff --git a/docker/Dockerfile b/docker/Dockerfile index 68345150..f6148c66 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,12 +20,13 @@ RUN corepack enable && corepack prepare pnpm@10.10.0 --activate WORKDIR /workspace/frontend -COPY frontend/package.json frontend/pnpm-lock.yaml ./ +COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile COPY frontend/ ./ -RUN pnpm build:embed +# Assert index.html so a silent export failure cannot ship an API-only binary. +RUN pnpm build:embed && test -f out/index.html FROM golang:${GO_VERSION}-alpine AS backend-builder @@ -36,16 +37,24 @@ RUN apk add --no-cache ca-certificates git WORKDIR /workspace -COPY go.mod go.sum ./ -RUN go mod download +# Cache dependency layer +COPY backend/go.mod backend/go.sum ./backend/ +RUN cd backend && go mod download COPY . . -COPY --from=frontend-builder /workspace/frontend/out ./plugins/drivers/driver_http/dist -RUN CGO_ENABLED=0 GOOS=linux go build \ +# Drop any stale bundle carried in the context, then overlay the fresh export so +# `//go:embed all:dist` in driver_http picks up exactly this frontend build. +RUN rm -rf backend/plugins/drivers/driver_http/dist +COPY --from=frontend-builder /workspace/frontend/out backend/plugins/drivers/driver_http/dist + +WORKDIR /workspace/backend + +RUN test -f plugins/drivers/driver_http/dist/index.html && \ + CGO_ENABLED=0 GOOS=linux go build \ -tags embed_frontend \ -trimpath \ - -ldflags="-s -w -X github.com/Rain-kl/Wavelet/pkg/buildinfo.Version=${VERSION} -X github.com/Rain-kl/Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ + -ldflags="-s -w -X Wavelet/pkg/buildinfo.Version=${VERSION} -X Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ -o /out/wavelet \ ./main.go diff --git a/docker/Dockerfile.backend b/docker/Dockerfile.backend index b8291501..a76bfa19 100644 --- a/docker/Dockerfile.backend +++ b/docker/Dockerfile.backend @@ -12,14 +12,16 @@ RUN apk add --no-cache ca-certificates git WORKDIR /workspace -COPY go.mod go.sum ./ -RUN go mod download +COPY backend/go.mod backend/go.sum ./backend/ +RUN cd backend && go mod download COPY . . +WORKDIR /workspace/backend + RUN CGO_ENABLED=0 GOOS=linux go build \ -trimpath \ - -ldflags="-s -w -X github.com/Rain-kl/Wavelet/pkg/buildinfo.Version=${VERSION} -X github.com/Rain-kl/Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ + -ldflags="-s -w -X Wavelet/pkg/buildinfo.Version=${VERSION} -X Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ -o /out/wavelet \ ./main.go diff --git a/docker/Dockerfile.cross b/docker/Dockerfile.cross index a6c6f294..4b411d52 100644 --- a/docker/Dockerfile.cross +++ b/docker/Dockerfile.cross @@ -43,12 +43,13 @@ RUN corepack enable && corepack prepare pnpm@10.10.0 --activate WORKDIR /workspace/frontend # Cache dependency layer -COPY frontend/package.json frontend/pnpm-lock.yaml ./ +COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile COPY frontend/ ./ -RUN pnpm build:embed +# Assert index.html so a silent export failure cannot ship API-only binaries. +RUN pnpm build:embed && test -f out/index.html # ── Stage 2: Cross-compile Go backend ────────────────────────────────────── FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS builder @@ -66,13 +67,17 @@ RUN apk add --no-cache ca-certificates git WORKDIR /workspace # Cache dependency layer -COPY go.mod go.sum ./ -RUN go mod download +COPY backend/go.mod backend/go.sum ./backend/ +RUN cd backend && go mod download COPY . . -# Overlay the compiled frontend into the embed path -COPY --from=frontend-builder /workspace/frontend/out ./plugins/drivers/driver_http/dist +# Drop any stale bundle carried in the context, then overlay the fresh export so +# `//go:embed all:dist` in driver_http picks up exactly this frontend build. +RUN rm -rf backend/plugins/drivers/driver_http/dist +COPY --from=frontend-builder /workspace/frontend/out backend/plugins/drivers/driver_http/dist + +WORKDIR /workspace/backend # Build matrix: GOOS × GOARCH # CGO_ENABLED=0 — fully static, no libc dependency, required for cross-compilation. @@ -81,6 +86,7 @@ COPY --from=frontend-builder /workspace/frontend/out ./plugins/drivers/driver_ht # -X — stamp version string at link time. # TARGET_OS / TARGET_ARCH — when non-empty, skip non-matching combinations. RUN set -e; \ + test -f plugins/drivers/driver_http/dist/index.html; \ mkdir -p /out; \ FILTER_OS="${TARGET_OS}"; \ FILTER_ARCH="${TARGET_ARCH}"; \ @@ -96,7 +102,7 @@ RUN set -e; \ go build \ -tags embed_frontend \ -trimpath \ - -ldflags="-s -w -X github.com/Rain-kl/Wavelet/pkg/buildinfo.Version=${VERSION} -X github.com/Rain-kl/Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ + -ldflags="-s -w -X Wavelet/pkg/buildinfo.Version=${VERSION} -X Wavelet/pkg/buildinfo.BuildTime=${BUILD_DATE}" \ -o "${OUTPUT}" \ ./main.go; \ done; \