From d3dcd1d8bd74f7bca54c3abd25ebece489e610d5 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 9 May 2026 16:49:42 +0200 Subject: [PATCH] ci: build frontend bundle before Go compile in release.yml + Dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 8 cut all panel HTML routes over to web/dist/ and embedded the Vite bundle into the Go binary via //go:embed all:dist. web/dist/ is .gitignored, so on a fresh CI checkout it doesn't exist — every Go build since Phase 8 has been failing with "pattern dist: no matching files found" or producing a binary that 404s on first asset request. release.yml: add a setup-node@v4 + npm ci + npm run build trio before the existing go build step in both the Linux matrix job (7 arches) and the Windows job. npm cache is keyed on frontend/package-lock.json. Dockerfile: add a node:22-alpine frontend stage that runs npm ci + npm run build and emits to /src/web/dist (via vite.config.js's outDir). The golang builder stage then COPY --from=frontend /src/web/dist into ./web/dist before the go build, so embed.FS sees the bundle. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/release.yml | 34 ++++++++++++++++++++++++++++++++++ Dockerfile | 18 ++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 228c1625..a3fe93cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,6 +83,23 @@ jobs: go-version-file: go.mod check-latest: true + # Frontend dist must be built BEFORE go build — Go's //go:embed + # all:dist directive in web/web.go requires web/dist/ to exist + # at compile time. web/dist/ is .gitignored, so on a fresh CI + # checkout it doesn't exist until vite emits it. + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Build frontend bundle + run: | + npm ci + npm run build + working-directory: frontend + - name: Build 3X-UI run: | export CGO_ENABLED=1 @@ -209,6 +226,23 @@ jobs: go-version-file: go.mod check-latest: true + # Frontend dist must be built BEFORE go build — see comment on the + # Linux job above. This step is identical except npm runs on the + # Windows runner here. + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Build frontend bundle + shell: pwsh + run: | + npm ci + npm run build + working-directory: frontend + - name: Install MSYS2 uses: msys2/setup-msys2@v2 with: diff --git a/Dockerfile b/Dockerfile index dabaf7f1..31dcee4f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,20 @@ +# ======================================================== +# Stage: Frontend (Vite) +# ======================================================== +# web/dist/ is .gitignored and embedded into the Go binary via +# //go:embed all:dist in web/web.go, so the SPA bundle MUST be built +# before the Go compile step. We build it in its own stage so the +# Go builder image doesn't need Node installed. +FROM node:22-alpine AS frontend +WORKDIR /src/frontend +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build +# Vite outDir is set to ../web/dist (see frontend/vite.config.js), so +# the bundle lands at /src/web/dist — that's what we copy into the +# next stage. + # ======================================================== # Stage: Builder # ======================================================== @@ -12,6 +29,7 @@ RUN apk --no-cache --update add \ unzip COPY . . +COPY --from=frontend /src/web/dist ./web/dist ENV CGO_ENABLED=1 ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE"