Skip to content

feat(v3): first-class production server build (parity with desktop Taskfiles) - #5695

Merged
leaanthony merged 4 commits into
masterfrom
worktree-v3-production-server-build
Jun 29, 2026
Merged

leaanthony merged 4 commits into
masterfrom
worktree-v3-production-server-build

Conversation

@taliesin-ai

@taliesin-ai taliesin-ai commented Jun 29, 2026 •

Copy link
Copy Markdown
Collaborator

What

Makes server mode (-tags server) a first-class production build, consistent with the desktop build tasks. Closes #5693.

Previously build:server passed only -tags server, so every server binary was dev-tagged — it pulled in the !production code paths (dev logger/menu/asset middleware) and skipped -trimpath/strip, with no parity to the desktop production/DEV/obfuscated matrix.

server and production are orthogonal, composable build tags (application_server.go is //go:build server, application_dev.go is //go:build !production), so this just wires the already-working -tags server,production combination into the generated build tooling.

Changes (build-asset templates)

  • build:server now builds a production binary by default — -tags server,production -trimpath -buildvcs=false -ldflags="-w -s", mirroring the desktop build task. New options, matching desktop:
    • DEV=true → development server (-tags server, inlining kept, no strip)
    • OBFUSCATED=true → build via garble (wails_obfuscated tag + precondition)
    • EXTRA_TAGS=... → extra build tags
    • the production frontend is built first (DEV passed through to build:frontend).
  • run:server runs a development server (DEV=true).
  • Dockerfile.server / build:docker build the production server statically (CGO_ENABLED=0 -tags server,production -trimpath -ldflags="-s -w") into distroless, and build:docker now 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_PORT already cover runtime config. The gap was purely build tooling + tag wiring.

Verification

Generated a throwaway project with a wails3 built from this branch and ran both profiles:

Profile Emitted build Binary
task build:server (default) go build -tags server,production -trimpath -buildvcs=false -ldflags="-w -s" -tags=server,production -trimpath, stripped — ~10.1 MB
task build:server DEV=true go build -tags server -buildvcs=false -gcflags=all="-l" -tags=server, ~14.1 MB

(go version -m confirms the tags/trimpath; production is ~28% smaller.) bindings generation picks up the matching flags. go test ./internal/commands/ (build-assets/taskfile/obfuscation tests) passes.

Notes

  • Behavior change worth calling out: task build:server is now production by default (was effectively always dev). This matches task build for desktop.
  • Docs: there's no dedicated server-mode page to update; the task desc text documents the new flags. Happy to add a guide page if wanted.

Summary by CodeRabbit

  • New Features
    • Server builds now default to production output using server,production build tags, while DEV builds a development-oriented server.
    • Added optional build obfuscation (OBFUSCATED=true) and support for additional custom build tags (EXTRA_TAGS).
    • The server run workflow now starts a development server.
    • Docker server builds produce a fully static production server by default (CGO_ENABLED=0), and allow overridable runtime image settings.
  • Documentation
    • Updated the Unreleased changelog to reflect the revised server and Docker build/run behavior.

…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
@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e9e15c4b-64be-4c93-9514-f35125449c4f

📥 Commits

Reviewing files that changed from the base of the PR and between 6827ff2 and 3c72583.

📒 Files selected for processing (1)
  • v3/UNRELEASED_CHANGELOG.md
✅ Files skipped from review due to trivial changes (1)
  • v3/UNRELEASED_CHANGELOG.md

Walkthrough

Updates the server build tasks and Dockerfile so server binaries build in production mode by default, with dev and obfuscated modes still supported. run:server now uses dev settings, build:docker depends on frontend output, and the changelog documents the new behavior.

Changes

Production Server Build

Layer / File(s) Summary
Taskfile server and Docker task updates
v3/internal/commands/build_assets/Taskfile.tmpl.yml
build:server now computes dev or production build flags, supports DEV, OBFUSCATED, and EXTRA_TAGS, conditionally uses garble, and passes build inputs into build:frontend; run:server passes DEV=true; build:docker depends on build:frontend with server,production tags.
Dockerfile.server production build
v3/internal/commands/build_assets/docker/Dockerfile.server
The Dockerfile adds configurable builder and runtime images, conditional C toolchain setup for CGO builds, and a static production server build with server,production tags and stripped linker flags.
Unreleased changelog entry
v3/UNRELEASED_CHANGELOG.md
The Unreleased changelog adds a note describing the new server build, run, and Docker behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • wailsapp/wails#4023: Also changes the shared Taskfile build flag plumbing around BUILD_FLAGS and task dependencies.
  • wailsapp/wails#4903: Related server-mode build and Docker support in the same build-assets area.
  • wailsapp/wails#4968: Also forwards extra build tags through the Taskfile build flow.

Suggested labels

reviewed ✅

Suggested reviewers

  • leaanthony

Poem

🐇 Hop, hop — the server now bakes bright,
Production tags gleam in the build light.
Docker goes static, lean as a breeze,
Frontend first, then a binary with ease.
Garble may join for a masked little spree,
And this bunny approves with a happy “hee-hee!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: making server builds production-first and aligned with desktop Taskfiles.
Description check ✅ Passed The description includes the change summary, linked issue, motivation/context, and verification details; missing checklist fill-outs are non-critical.
Linked Issues check ✅ Passed The PR implements the requested Taskfile and Dockerfile parity: production-by-default server builds, DEV mode, obfuscation, and static Docker packaging.
Out of Scope Changes check ✅ Passed The changes stay within build tooling, Docker packaging, and changelog documentation, with no unrelated code paths introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-v3-production-server-build

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between e69080b and 355240c.

📒 Files selected for processing (3)
  • v3/UNRELEASED_CHANGELOG.md
  • v3/internal/commands/build_assets/Taskfile.tmpl.yml
  • v3/internal/commands/build_assets/docker/Dockerfile.server

Comment thread v3/internal/commands/build_assets/Taskfile.tmpl.yml Outdated
Comment thread v3/internal/commands/build_assets/Taskfile.tmpl.yml
…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.
@taliesin-ai

Copy link
Copy Markdown
Collaborator Author

Updated to not hardcode CGO_ENABLED=0.

The native task build:server was already CGO-neutral (it inherits the environment), so CGO apps build fine outside Docker. The hardcode was only in Dockerfile.server, coupled to the distroless/static base.

Dockerfile.server now exposes overridable build args — CGO_ENABLED, GO_IMAGE, RUNTIME_IMAGE — defaulting to the lean pure-Go static path (distroless/static), and installs a C toolchain in the builder only when CGO is enabled (apk or apt). task build:docker passes them through:

task build:docker CGO_ENABLED=1 GO_IMAGE=golang:bookworm RUNTIME_IMAGE=gcr.io/distroless/base-debian12

Default behaviour is unchanged; CGO is now a one-flag opt-in rather than being blocked.

taliesin-ai and others added 2 commits June 29, 2026 12:00
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.
@leaanthony
leaanthony enabled auto-merge (squash) June 29, 2026 05:11
@leaanthony
leaanthony merged commit eb80855 into master Jun 29, 2026
41 of 43 checks passed
@leaanthony
leaanthony deleted the worktree-v3-production-server-build branch June 29, 2026 05:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v3] First-class production server build (parity with desktop Taskfiles)

2 participants