Files
gbld/README.md
T
2026-07-27 17:07:25 +02:00

8.1 KiB

gbld — Simple Go Builder & Live-Reloader

gbld is a hot-reloader and build-automation utility for Go projects. It automatically tracks build numbers, formats source files using goimports, compiles the binary, manages the running process, and watches the project directory for changes to trigger automatic rebuilding and restarting.


Key Features

  • 🔄 Hot Reloader: Automatically watches for file changes (via fsnotify), recursively including subdirectories, and rebuilds/restarts your application instantly.
  • 🔢 Build Counter: Increments a build number in build.go automatically with every compiled build.
  • 🧹 Auto-Import: Runs goimports on save (optional via -i) to keep your imports clean — without touching the rest of your formatting.
  • 🖥️ Interactive Menu: Uses a select menu (gbld.menu.json) if run without arguments, letting you define and run custom build tasks.
  • 🚀 Cross-Compilation: Easily builds binaries for multiple target operating systems (macOS, Linux, Windows) and architectures (amd64, arm64) using a single command.
  • ☁️ Remote Uploads: Integrated command to upload build artifacts to a deployment server (gozilla).
  • 🔐 Verified Self-Update: Downloads updates over HTTPS and refuses to install anything that does not match its published SHA-256 checksum.

Installation

Prerequisites

Make sure you have Go installed and available in your system path. goimports is only required if you use the -i flag:

go install golang.org/x/tools/cmd/goimports@latest

Building from Source

Clone the repository and compile gbld:

git clone https://git.fhi.mpg.de/mike/gbld.git
cd gbld
go build -o /usr/local/bin/gbld

Usage

gbld [flags] [target_name]

Note

If target_name is omitted, the name of the current directory is used. The tool expects a main source file matching that name (e.g., target_name.go). The binary is always built from the package in the current directory, so the module path does not have to match the target name.

CLI Flags

Flag Argument Description
-b None Build-only mode (compiles the binary but does not run it).
-1 None Run once (does not watch the directory for changes), see Exit Codes.
-i None Runs goimports to clean up imports before building.
-x None Exits after the first successful build and leaves the started binary running.
-o <args> Space-separated arguments to pass to the compiled binary on execution.
-c <command> Command to execute immediately after a successful build (before execution).
-a None Builds binaries for all supported platforms (Windows, macOS, Linux for AMD64/ARM64).
-u None Uploads built binaries via SSH/SCP to the gozilla server.
-v None Displays the current version of gbld.
-h None Displays help and usage information.

Environment

Variable Description
GBLD_NO_UPDATE Set to any value to skip the update check at startup (useful offline or in CI).

Configuration (gbld.menu.json)

To make running common tasks easier, you can place a gbld.menu.json file in your project directory. If you run gbld without any flags, it will parse this file and present an interactive selection menu (entries are shown in alphabetical order):

{
  "Build and Run (hot reload)": ["-i"],
  "Build Only": ["-b", "-i", "-1"],
  "Show Help": ["-h"]
}

Under the Hood

Build Increment

When compiling, gbld parses build.go to find a pattern matching var build = "<number>". It increments this number by 1 and updates the file automatically, leaving the rest of the line (including trailing comments) untouched. This is useful for stamping build numbers/versions inside your binary. If there is no build.go, this step is silently skipped.

Target Version

-a and -u name their artifacts after the first var version = "x.y.z" found in the *.go files of the project. Ordinary builds do not need this variable.

Automatic Backups

Before gbld runs goimports on a file or modifies build.go, it creates a timestamped backup in a ./tmp/ directory inside the project workspace (the directory is created on demand):

./tmp/gbld.go.20260625145800

If a backup cannot be written, the file is not modified.

File Watching

The project directory is watched recursively; directories created while gbld is running are picked up automatically. Hidden entries (.git, …) as well as bin, tmp, vendor, node_modules and testdata are skipped. Only writes and newly created .go files trigger a rebuild — a pure touch (mtime only) does not. Rebuilds are debounced by 100 ms and never run in parallel.

Process Management

When hot-reloading, gbld handles process termination gracefully:

  1. It sends an os.Interrupt (SIGINT) to the running binary.
  2. It waits up to 1 second for the process to exit clean.
  3. If it does not exit within the timeout, it terminates the process forcefully (SIGKILL).

gbld itself also traps SIGINT/SIGTERM and stops the started binary before exiting, so no orphaned processes are left behind — except with -x, where detaching is the point.

Exit Codes

With -1, gbld is usable from scripts and CI:

Situation Exit code
Build failed 1
-b -1, build succeeded 0
-1 without -b exit code of the built program (gbld waits for it)

Cross-Compilation and Upload

gbld -a          # build bin/<name>_<version>_<os>_<arch> for all 6 targets
gbld -u          # upload them to gozilla

-a writes Windows artifacts with an .exe suffix and additionally produces:

  • bin/checksums.txt — SHA-256 of every artifact, in the format used by shasum -a 256 -c
  • bin/version.txt — the published version

If any target fails to build, version.txt is not written and gbld exits with 1, so a half-published version can never be announced. -u refuses build names containing anything but A-Za-z0-9._- and uploads the artifacts together with checksums.txt and version.txt.

Self-Update

On startup gbld fetches version.txt from the update server (3 s timeout — an unreachable server never blocks a build). If a newer version is published, it asks before downloading, then verifies the download against the SHA-256 from checksums.txt before replacing itself. If no matching checksum is published, the update is refused. Publish new versions with gbld -a followed by gbld -u.


Colors

Output uses the Catppuccin Mocha palette as 24-bit color:

Helper Palette Hex
Cr / Crb Red #f38ba8
Cg / Cgb Green #a6e3a1
Cy / Cyb Yellow #f9e2af
Cb / Cbb Blue #89b4fa
Cm / Cmb Pink #f5c2e7
Cc / Ccb Teal #94e2d5
Cw Subtext1 #bac2de
Cwb Text #cdd6f4

Mocha maps identical values to the normal and bright ANSI slots, so the bold helpers keep their hue and only add weight. The full palette is available as CatMauve, CatPeach, CatLavender, … in tools.go.

The interactive prompts (survey) are themed as well: their templates resolve colors through {{color "green+hb"}}-style names, and tools.go replaces that template function with one that maps those names onto the palette. This covers every prompt including its icons — question mark, select arrow, help and error markers — without copying any template.

Terminals that do not announce 24-bit color via COLORTERM fall back to the basic ANSI colors, so their own theme keeps deciding. NO_COLOR and non-TTY output disable colors entirely.


Development

go test ./...          # unit tests (build counter, version detection, update verification, toolbox)
go vet ./...

Note

The sources are deliberately not gofmt-formatted (2-space indentation). The -i flag only replaces the import (...) block of a file and leaves the rest of the formatting alone — do not run gofmt over the tree.