Help us shape the future of Go! Take the 2026 Go Developer Survey

dev

package
v3.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 21 Imported by: 0

README

Wails development sessions

This is a Wails-specific internal subsystem for the experimental YAML CLI (issue #6021), not a public library or a general process supervisor.

WAILS_EXP_USE_WAKE must be present and the project must have wails.yaml. With the variable unset, the CLI keeps its existing Taskfile/Refresh path and none of the new flags are registered. WAILS_USE_WAKE remains ignored.

The CLI owns flags and signals. Run owns the session context, build generations, transactional watch replacement, readiness, restarts, rollback, and cleanup. Its operations are adapters to Wails' existing manifest pipeline, watcher and platform process tools. Build plans remain finite.

Output serialises lifecycle events, build reporting and attributed child stdout/stderr. Incomplete lines and diagnostic tails are bounded to 64 KiB. --verbose includes build commands and live build output; --quiet shows failures. Errors retain component, phase, generation, command, exit status, output and cause where available. The shared internal/report rendered-error marker prevents duplicate CLI diagnostics. YAML builds do not install a global reporter. Canceled/superseded work is not a build failure.

Frontend readiness requires an HTTP response below 500, with normal certificate validation for HTTPS. Backend readiness requires a per-launch authenticated callback from Wails' runtime-ready message; a previous process cannot satisfy its replacement's handshake. Windowless apps use the application-started event. The protocol is inert in ordinary launches and absent from production readiness hooks. Android debug launches forward Go stdout/stderr into the attached logcat.

Commands

export WAILS_EXP_USE_WAKE=1
wails3 dev
wails3 dev --verbose
wails3 dev --target ios/arm64 --device SIMULATOR_UDID
wails3 dev --target ios/arm64 --destination device --device DEVICE_ID --host MAC_LAN_IP
wails3 dev --target android/arm64 --emulator AVD_NAME
wails3 dev --target android/arm64 --device ADB_SERIAL

An iOS simulator must already be booted when --device is omitted. An explicitly selected simulator is booted if needed. Physical iOS uses the project's Apple development signing configuration and a Mac LAN address reachable from the phone/tablet. The generated development bundle includes local-network metadata; allow the device's local-network prompt when requested. Android uses loopback and owns only its newly created adb reverse mappings. The emulator remains running after the dev session; the app, log attachment and owned reverse mappings are stopped. Mobile replacement retains only the current artifact and the candidate needed for rollback. Package workspaces and outputs stay under .wails/dev/ and production artifacts remain untouched.

--plan prints the finite development build and effective application arguments without connecting to devices. dev.args and target-specific dev.args provide defaults; CLI arguments after -- replace them, with a bare -- clearing them. --appargs is a compatibility spelling accepting one POSIX-quoted string. Production run.args never supplies development defaults.

The session owns the active argument vector. Every rebuilt candidate gets the newly resolved vector; a failed candidate retains the previous one. A runtime-only argument edit restarts the backend while reusing its compile result and frontend. Windows rollback reads the previous process's argument vector; mobile rollback retains the arguments with the staged artifact. Android rejects nonempty vectors before device discovery. iOS forwards them through its native launcher. See the argument reference. For HTTPS, configure the frontend server and trust its certificate; readiness never silently disables certificate validation.

Acceptance

Fast regression suites run with:

go test -race ./internal/dev ./internal/devruntime ./internal/report ./internal/commands ./cmd/wails3 ./internal/wake/...
go vet ./internal/dev ./internal/devruntime ./internal/report ./internal/commands ./cmd/wails3 ./internal/wake/...

The existing commands lifecycle/adapter/process suites exercise failed builds, rapid edits, superseded generations, watcher configuration failures, unexpected frontend/backend exits, startup failure, cancellation and descendant cleanup. The mobile plan tests check development-only outputs and network configuration.

testdata/native_acceptance.py creates a disposable Wails fixture, using the runtime from this checkout. First build the CLI and runtime package:

go build -o /tmp/wails3-dev ./cmd/wails3
npm --prefix internal/runtime/desktop/@wailsio/runtime ci
npm --prefix internal/runtime/desktop/@wailsio/runtime run build:code
python3 internal/dev/testdata/native_acceptance.py --cli /tmp/wails3-dev --output /tmp/wails-dev-acceptance -- --port 9351

On headless Linux, run the last command through xvfb-run -a dbus-run-session --. On Windows, run it from an interactive console so Ctrl+Break reaches the child process group. Mobile flags can follow --; use a separate, correctly signed fixture for physical iOS. Native acceptance checks actual runtime readiness, frontend-to-Go calls, frontend hot reload without a backend restart, a failed build that keeps the session alive, recovery/relaunch and clean CLI shutdown. It returns nonzero if any check fails and keeps JSON results and logs for review.

The platform acceptance matrix must cover macOS arm64, Windows amd64, Linux amd64, iOS simulator and physical device, and an Android emulator/device. Native GUI testing is required: compilation alone is not a passing platform acceptance result. macOS Intel remains community-supported.

Documentation

Overview

Package dev owns the Wails YAML development session. It is an internal, Wails-specific controller, not a general-purpose process supervisor.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FrontendSessionChanged

func FrontendSessionChanged(current, next manifest.Config) bool

func Generation

func Generation(ctx context.Context) uint64

func IsForcedRebuild

func IsForcedRebuild(ctx context.Context) bool

func Run

func Run(ctx context.Context, options Options, ops Operations) (resultErr error)

func WaitHTTP

func WaitHTTP(ctx context.Context, p Process, address string, timeout time.Duration) error

WaitHTTP requires an actual HTTP response, rather than merely an open port. Client errors are accepted for custom root routes; server errors keep waiting.

func WatchSessionChanged

func WatchSessionChanged(current, next manifest.Config) bool

func WithForcedRebuild

func WithForcedRebuild(ctx context.Context) context.Context

func WithGeneration

func WithGeneration(ctx context.Context, g uint64) context.Context

func WithOutput

func WithOutput(ctx context.Context, o *Output) context.Context

Types

type BuildResult

type BuildResult struct {
	Plan    pipeline.Plan
	Results map[pipeline.NodeKey]pipeline.Result
}

type Diagnostic

type Diagnostic struct {
	Component, Phase string
	Generation       uint64
	Command          []string
	ExitCode         int
	Output           string
	Err              error
}

Diagnostic retains the cause and launch/build identity for CLI diagnostics.

func (*Diagnostic) Error

func (d *Diagnostic) Error() string

func (*Diagnostic) Unwrap

func (d *Diagnostic) Unwrap() error

type Event

type Event struct {
	Generation                uint64
	Component, Phase, Message string
	Diagnostic                *Diagnostic
}

Event is a Wails dev lifecycle notification. Child output remains text so multiline compiler diagnostics and application stack traces stay intact.

type EventKind

type EventKind int
const (
	Source EventKind = iota
	Ignore
	Directory
	GitIgnore
)

type Operations

type Operations struct {
	GenerateBindings  func(context.Context, *manifest.Loaded) error
	ValidateTarget    func(string, string) error
	Getwd             func() (string, error)
	Load              func(string, string) (*manifest.Loaded, error)
	Target            func(string) (string, string, error)
	Plan              func(*manifest.Loaded, string, string, []string) error
	CheckPort         func(string, int) error
	Build             func(context.Context, *manifest.Loaded, string, string, string, int) (BuildResult, error)
	StartFrontend     func(string, manifest.Config, string, int, string) (Process, error)
	WaitFrontendReady func(context.Context, Process, string, time.Duration) error
	BinaryPath        func(string, BuildResult, string, string) (string, error)
	StartApp          func(string, string, string, int, []string) (Process, error)
	WaitReady         func(context.Context, Process, time.Duration) error
	StartWatches      func(string, manifest.Config) (WatchSet, error)
	RestartWatches    func(string, manifest.Config, WatchSet) (WatchSet, error)
	RestoreFrontend   func(context.Context, string, manifest.Config, int, string, string) (Process, error)
	RestoreApp        func(context.Context, string, Process, string, int) (Process, error)
	BackendChanged    func(BuildResult, string, string) bool
}

Operations adapts Wails build and host tools; Run owns their lifetime.

type Options

type Options struct {
	Controls        <-chan string
	Host            string
	Profile, Target string
	Plan, Secure    bool
	VitePort        int
	Args            []string // nil inherits manifest defaults; empty clears them.
	Output          *Output
}

type Output

type Output struct {
	// contains filtered or unexported fields
}

Output serialises builds, lifecycle events and child output on one sink. It deliberately uses stable lines: a long-lived application must never race a build spinner for ownership of terminal cursor positions.

func NewOutput

func NewOutput(w io.Writer, level report.Verbosity) *Output

func OutputFrom

func OutputFrom(ctx context.Context) *Output

func (*Output) BuildReporter

func (o *Output) BuildReporter(generation ...uint64) report.Reporter

func (*Output) Clear

func (o *Output) Clear()

func (*Output) Failure

func (o *Output) Failure(g uint64, c, p string, err error, message string)

func (*Output) Observe

func (o *Output) Observe(f func(Event))

Observe must be configured before the session starts. The callback must not re-enter Output; delivery is ordered with terminal output.

func (*Output) Status

func (o *Output) Status(g uint64, c, p, m string)

func (*Output) Writer

func (o *Output) Writer(component, stream string) io.WriteCloser

type Process

type Process interface {
	Done() <-chan struct{}
	Stop(time.Duration)
	Err() error
	NeedsStopBeforeReplacement() bool
}

type Readiness

type Readiness struct {
	// contains filtered or unexported fields
}

Readiness is unique to one candidate launch; an old application cannot mark its replacement ready. Desktop listeners bind loopback; physical iOS uses the explicitly selected LAN interface.

func NewReadiness

func NewReadiness() (*Readiness, error)

func NewReadinessOn

func NewReadinessOn(host string) (*Readiness, error)

func (*Readiness) Close

func (r *Readiness) Close()

func (*Readiness) Environment

func (r *Readiness) Environment() []string

func (*Readiness) Port

func (r *Readiness) Port() string

func (*Readiness) Wait

func (r *Readiness) Wait(ctx context.Context, p Process, timeout time.Duration) error

type Tail

type Tail struct {
	// contains filtered or unexported fields
}

Tail retains bounded diagnostic context even when ordinary output is quiet.

func (*Tail) String

func (t *Tail) String() string

func (*Tail) Write

func (t *Tail) Write(p []byte) (int, error)

type WatchSet

type WatchSet interface {
	Events() <-chan notify.EventInfo
	Stop()
	Classify(manifest.Config, notify.EventInfo) EventKind
	ContainsInput(manifest.Config, string) bool
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL