Skip to content

Prepare the binary for installing: version, example config, config location - #43

Merged
taskinen merged 2 commits into
mainfrom
feat/installed-binary-flags
Oct 16, 2026
Merged

taskinen merged 2 commits into
mainfrom
feat/installed-binary-flags

Conversation

@taskinen

@taskinen taskinen commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Why

Mailbox Zero will be released as v1.0.0. Users will install it with go install github.com/taskinen/mailboxzero@latest or download a binary from the GitHub release, and then run it from anywhere, with no source and no config.yaml.example. This is the first of three PRs before that release:

  1. this PR, the installed binary;
  2. Build release binaries with GoReleaser #44, GoReleaser builds;
  3. the README install instructions.

Changes

Version (new internal/version, read from the build information Go records in every binary; no version variable or -X linker flags):

  • -version prints mailboxzero <version> (<Go version>, <OS>/<arch>). The startup log shows the same string. The version is:
    • v1.0.0 for a release binary and for go install …@v1.0.0;
    • a pseudo-version for go build in a checkout (for example v0.0.0-20261016172523-59b1469d2f82), with +dirty for uncommitted changes;
    • (devel) for go run.
  • In the page header, next to the title: the release version (v1.0.0), otherwise the build's commit (59b1469, or 59b1469-dirty), or dev for go run. Hovering shows the full -version text.

Config file

  • -example-config prints the built-in config.yaml.example (//go:embed).
  • Default location: without -config, the file is now ~/.config/mailboxzero/config.yaml, or $XDG_CONFIG_HOME/mailboxzero/config.yaml when that is set, on every OS.
    • Before, it was config.yaml in the current directory. An installed binary runs from anywhere, and an unrelated config.yaml in the current folder must not be picked up.
    • A relative $XDG_CONFIG_HOME is ignored, as the XDG spec says.
  • The log names the config file it uses.
  • A missing config file explains how to create it:
    config file /Users/you/.config/mailboxzero/config.yaml not found: create it with mkdir -p /Users/you/.config/mailboxzero && mailboxzero -example-config > /Users/you/.config/mailboxzero/config.yaml and add your Fastmail API token, or give another file with -config: …

Also

  • A package doc comment on main.go, which pkg.go.dev shows as the command's description.
  • config.yaml.example: its header names the default location and the commands.
  • e2e/playwright.config.js: runs go run . instead of go run main.go. A file list builds without the version stamp and would leave out any other file in package main.
  • CLAUDE.md: the commands use . and the new config location, plus the version package, the header label and the new tests.

Note for your current setup: your config.yaml in the repository folder is no longer read by default. Run go run . -config config.yaml, or move it once with mkdir -p ~/.config/mailboxzero && mv config.yaml ~/.config/mailboxzero/. The README's commands are updated in PR 3.

Tests

  • internal/version: String() for a tag, a pseudo-version, +dirty, (devel), an empty version and no build info. Short() for:
    • a release (installed, or built at its tag);
    • a pre-release;
    • a checkout build, clean or dirty;
    • a dirty build at a tag;
    • go install of a commit (the hash comes from the pseudo-version);
    • a pseudo-version after a pre-release;
    • go run;
    • no build info.
  • main_test.go:
    • the default path with XDG_CONFIG_HOME set, unset and relative;
    • the built-in example loads once a token is filled in, and starts in dry run mode;
    • a missing file's error names the path, the mkdir -p and the -example-config commands, and wraps fs.ErrNotExist;
    • an invalid file isn't reported as missing.
  • server_test.go: the index page renders the version label with its hover text.
  • New e2e/tests/version.spec.js: the header shows a version label (dev under go run) and its title.

Results:

  • go test -race ./... and go vet ./... pass.
  • All 31 Playwright tests pass.

Checked by hand with a built binary in mock mode: the header showed 59b1469-dirty and the hover text mailboxzero v0.0.0-20261016172523-59b1469d2f82+dirty (go1.27.2, darwin/arm64). I also checked -version, -example-config (identical to config.yaml.example), -h, and the missing-config message.

Testing on Fastmail

  1. Move your config once: mkdir -p ~/.config/mailboxzero && mv config.yaml ~/.config/mailboxzero/ (or keep it and add -config config.yaml in step 2).
  2. go run . in the repository. The log shows Using config file /Users/…/.config/mailboxzero/config.yaml. Use the app as usual; the header shows dev next to the title.
  3. go build -o mailboxzero . && ./mailboxzero. The header shows the commit (for example 1dd0957), and hovering shows the full version.
  4. ./mailboxzero -version and ./mailboxzero -example-config | head -6.
  5. ./mailboxzero -config /tmp/nothing.yaml explains how to create a config.

Users will install the binary with go install or download it from a
release, and then have neither the source nor config.yaml.example.

- -version prints the version Go records in the binary: the tag for a
  release or go install ...@vX.Y.Z, a pseudo-version for go build in a
  checkout, "(devel)" for go run. The startup log shows it too.
- -example-config prints the built-in config.yaml.example, so a config
  file is one command away.
- A missing config file now says how to create one.

The e2e tests and the docs run the package (go run ., go build .)
instead of main.go: a file list builds without the version stamp and
would leave out any other file of package main.
- The page header shows which version is running: the release version
  (v1.0.0), otherwise the commit of the build (59b1469, -dirty with
  uncommitted changes), or "dev" for go run. Hovering shows the full
  description that -version prints. The version code moves to
  internal/version so the command and the server share it.
- Without -config, the config file is now
  ~/.config/mailboxzero/config.yaml ($XDG_CONFIG_HOME/mailboxzero/
  config.yaml when that is set) on every OS, instead of config.yaml in
  the current directory. An installed binary is run from anywhere, and
  an unrelated config.yaml in the current directory must not be picked
  up. The log names the file used, and a missing file's error says how
  to create the folder and the file.
@taskinen taskinen changed the title Add -version and -example-config for installed binaries Prepare the binary for installing: version, example config, config location Oct 16, 2026
@taskinen
taskinen merged commit 9620a3d into main Oct 16, 2026
6 checks passed
@taskinen
taskinen deleted the feat/installed-binary-flags branch October 16, 2026 19:50
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.

1 participant