feat(v3): first-class production server build (parity with desktop Taskfiles) - #5695
Conversation
…p tasks Server mode previously only built a dev-tagged binary: `build:server` passed just `-tags server`, so deployed headless servers shipped with dev-only code paths and no build hardening, with no parity to the desktop build/package matrix. `server` and `production` are orthogonal, composable tags, so this wires the existing capability into the build tooling: - build:server now builds a production binary by default (-tags server,production -trimpath -buildvcs=false -ldflags="-w -s"), mirroring the desktop `build` task; DEV=true builds a development server, OBFUSCATED=true builds via garble, and EXTRA_TAGS adds build tags. - run:server runs a development server (DEV=true). - Dockerfile.server / build:docker build the production server statically (CGO_ENABLED=0, -tags server,production) and build the production frontend first so the embedded assets are current. Verified end-to-end via a generated project: production build is -tags=server,production -trimpath, stripped (~28% smaller than the dev server). Closes #5693
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
WalkthroughUpdates the server build tasks and Dockerfile so server binaries build in production mode by default, with dev and obfuscated modes still supported. ChangesProduction Server Build
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@v3/internal/commands/build_assets/Taskfile.tmpl.yml`:
- Line 263: The server binary path handling in the Taskfile template is
vulnerable to shell-splitting when APP_NAME contains spaces. Update the build
command in the build_assets Taskfile template and the related run:server command
so the generated server binary path is quoted consistently, using the existing
.BIN_DIR, .APP_NAME, and exeExt template symbols. Keep the quoting applied
wherever the server binary path is passed to go build -o and when the server is
launched.
- Around line 283-286: The build:docker dependency on build:frontend is leaving
BUILD_FLAGS unset, so generate:bindings can produce the wrong frontend bindings
while the Docker image compiles the Go binary with server,production tags.
Update the build:docker task in Taskfile.tmpl.yml to pass BUILD_FLAGS through to
build:frontend (or set it explicitly) so the frontend binding generation matches
the same server,production tag set used by the Docker build.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 25491111-f2f6-4dec-be76-21f7b4f6752e
📒 Files selected for processing (3)
v3/UNRELEASED_CHANGELOG.mdv3/internal/commands/build_assets/Taskfile.tmpl.ymlv3/internal/commands/build_assets/docker/Dockerfile.server
…ding off Hardcoding CGO_ENABLED=0 blocked projects that need CGO. Expose CGO_ENABLED, GO_IMAGE and RUNTIME_IMAGE as Docker build args (defaults unchanged: pure-Go static binary on distroless/static), pass them through `task build:docker`, and install a C toolchain in the builder only when CGO is enabled (apk or apt). CGO apps: task build:docker CGO_ENABLED=1 GO_IMAGE=golang:bookworm RUNTIME_IMAGE=gcr.io/distroless/base-debian12 The native `build:server` task is unchanged and remains CGO-neutral (inherits the environment), so CGO projects already build correctly outside Docker.
|
Updated to not hardcode The native
Default behaviour is unchanged; CGO is now a one-flag opt-in rather than being blocked. |
Address CodeRabbit review on #5695: - Quote the server binary path in build:server (-o "...") and run:server, so an APP_NAME containing spaces is not shell-split (matches the desktop tasks). - build:docker now passes BUILD_FLAGS="-tags server,production" to build:frontend so generate:bindings analyses the same build the image compiles, rather than the default-tag build.
What
Makes server mode (
-tags server) a first-class production build, consistent with the desktop build tasks. Closes #5693.Previously
build:serverpassed only-tags server, so every server binary was dev-tagged — it pulled in the!productioncode paths (dev logger/menu/asset middleware) and skipped-trimpath/strip, with no parity to the desktop production/DEV/obfuscated matrix.serverandproductionare orthogonal, composable build tags (application_server.gois//go:build server,application_dev.gois//go:build !production), so this just wires the already-working-tags server,productioncombination into the generated build tooling.Changes (build-asset templates)
build:servernow builds a production binary by default —-tags server,production -trimpath -buildvcs=false -ldflags="-w -s", mirroring the desktopbuildtask. New options, matching desktop:DEV=true→ development server (-tags server, inlining kept, no strip)OBFUSCATED=true→ build viagarble(wails_obfuscatedtag + precondition)EXTRA_TAGS=...→ extra build tagsbuild:frontend).run:serverruns a development server (DEV=true).Dockerfile.server/build:dockerbuild the production server statically (CGO_ENABLED=0 -tags server,production -trimpath -ldflags="-s -w") into distroless, andbuild:dockernow builds the production frontend first so the embedded assets are current.No Go API change:
application.Options.Server(ServerOptions{Host, Port, TLS, timeouts}) +WAILS_SERVER_HOST/WAILS_SERVER_PORTalready cover runtime config. The gap was purely build tooling + tag wiring.Verification
Generated a throwaway project with a
wails3built from this branch and ran both profiles:task build:server(default)go build -tags server,production -trimpath -buildvcs=false -ldflags="-w -s"-tags=server,production -trimpath, stripped — ~10.1 MBtask build:server DEV=truego build -tags server -buildvcs=false -gcflags=all="-l"-tags=server, ~14.1 MB(
go version -mconfirms the tags/trimpath; production is ~28% smaller.)bindingsgeneration picks up the matching flags.go test ./internal/commands/(build-assets/taskfile/obfuscation tests) passes.Notes
task build:serveris now production by default (was effectively always dev). This matchestask buildfor desktop.desctext documents the new flags. Happy to add a guide page if wanted.Summary by CodeRabbit
server,productionbuild tags, whileDEVbuilds a development-oriented server.OBFUSCATED=true) and support for additional custom build tags (EXTRA_TAGS).CGO_ENABLED=0), and allow overridable runtime image settings.