Skip to content

Publish build and generated-app output transactionally #669

Description

@cssbruno

Priority

High

Context

Disk builds currently write CSS, runtime assets, page HTML, manifests, reports, and generated application files directly to their final destinations in sequence. Later stages can still fail during final security audit, AsyncAPI generation, generated-app emission, Go formatting, binary compilation, WASM generation, or deployment recipe generation.

The low-level build writer ultimately uses direct os.WriteFile, and app generation similarly copies/writes files incrementally into the target directory.

Problem

A failed build or dev rebuild can leave a mixture of old and new files. A server, watcher, deployment process, or subsequent build may observe a partially published generation. Individual file writes are also not atomic.

Proposed direction

Make planning and publication separate phases:

  1. Produce the complete artifact set in memory or a staging directory.
  2. Format and validate all generated Go and metadata.
  3. Run final artifact audits against the staged snapshot.
  4. Write files through temporary files plus atomic rename.
  5. Publish the complete generation atomically, or publish a generation manifest last and serve only committed generations.

BuildMemoryFromIR already provides a useful foundation and should become the canonical planning path for disk builds.

Acceptance criteria

  • Disk builds and memory builds share one canonical artifact planner.
  • No final output file is modified until all planning, formatting, and final audits succeed.
  • Individual file replacement uses a same-filesystem temporary file and atomic rename.
  • A failed build leaves the previously committed output generation intact.
  • Stale files are removed only as part of committing a successful generation.
  • Generated app output (go.mod, app source, lifecycle files, embedded assets, audit tests, addon files, and main.go) is committed as one generation.
  • Dev serving/restart logic observes only committed generations.
  • Failure-injection tests cover errors at early, middle, and final publication stages.
  • Interrupted publication has a deterministic cleanup/recovery path.

Affected areas

internal/buildgen, internal/appgen, cmd/gowdk/build.go, dev-loop publication and restart logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions