What problem would this solve?
The next Nabat release requires go 1.27 and ships breaking / new consumer APIs (Confirm tiers, Theme on Context, delayed Spinner, Prefill/Initial, Fields/Badge, highlight helpers, nabattest Capture). Deployah is still on Go 1.26.5 and an older Nabat, so we cannot take the dependency bump without a toolchain move and a consumer migration in the same change set.
Nabat already solved the Nix-side Go 1.27 problems in its own flake: pin pkgs.go_1_27, disable golangci-lint until upstream supports 1.27, keep GOTOOLCHAIN=local on test apps. We should mirror that here, then delete Deployah workarounds that the new Nabat covers.
Note: current nixpkgs-unstable's go_1_27 is still 1.27rc2. That is fine for this PR; we can re-pin when stable lands in nixpkgs.
What do you want?
A. Go 1.27 toolchain
- Pin Go in
flake.nix: go = pkgs.go_1_27; (same pattern as Nabat).
- Bump
go.mod to go 1.27 and run go mod tidy.
- Thread the pinned
go into nix/apps/quality.nix for tidy / gen-docs (today they call pkgs.go and would stay on 1.26).
- Disable golangci-lint in
nix/checks.nix and stub nix run .#lint / .#fmt until golangci-lint#6643 ships Go 1.27 support. Override the gofmt hook to ${go}/bin/gofmt so git-hooks does not keep using Go 1.26.
- Bump the Dockerfile base image from
golang:1.26.5-alpine to golang:1.27-alpine (or 1.27.0-alpine once stable) with a fresh digest pin.
- Recompute
deployahVendorHash via nix run .#update-vendor-hash.
B. Nabat dependency + consumer migration
- Bump
nabat.dev in go.mod to the new release and tidy.
- Confirm: use
WithYes / WithBypassHint (and ErrConfirmationRequired) for deploy, delete, cluster down (--force), and init overwrite. Drop custom "refusing without --yes" / string matching on "requires interactive terminal".
- Prefill / Initial: replace Form pointer pre-seed and Confirm-as-Form-bool hacks in init with
WithPrefill / WithInitial.
- Spinner: adopt
c.Spinner(fn, WithTitle(...)) (delayed start). Delete runMaybeSpinner in cluster.
- Theme: stop closing over
app.Theme() in deploy/plan/cluster status; use c.Theme() / c.Render at the command boundary (leaf internal/plan can keep an injected ResolvedTheme).
- Fields / Badge: replace hand-rolled cluster status label printers and
statusBadge with c.Fields + c.Badge (app owns word→icon mapping).
- Structured output: prefer
c.JSON where we still MarshalIndent+print (resolve); for plan's owned JSON schema, encode locally then FprintHighlight / PrintHighlight on the CLI path only (keep unit goldens byte-stable if needed).
- Tests: collapse mini-app harnesses to
nabattest.Capture / nabattest.Context where it fits.
Do not invent severe type-to-confirm (WithConfirmValue) unless we add a --confirm= flag. Keep Deployah-specific pieces out of Nabat: DeployWatcher, plan +/-/~ token mapping, shell raw TTY.
Alternatives considered
- Stay on Go 1.26 and pin an older Nabat: blocks the consumer migration entirely.
- Split into two PRs (Go first, Nabat second): possible, but the Go bump exists only to unblock Nabat, so one PR is simpler to review and land.
- Keep golangci-lint enabled and hope nixpkgs rebuilds it: fails today; nixpkgs' binary is still built with Go 1.26.
- Wait for Go 1.27 stable in nixpkgs before any work: slows the Nabat bump; rc2 is enough to land the migration and re-pin later.
Notes
Follow-up after golangci-lint gains 1.27 support: re-enable the pre-commit hook and restore real nix run .#lint / .#fmt apps.
What problem would this solve?
The next Nabat release requires
go 1.27and ships breaking / new consumer APIs (Confirm tiers, Theme on Context, delayed Spinner, Prefill/Initial, Fields/Badge, highlight helpers, nabattest Capture). Deployah is still on Go 1.26.5 and an older Nabat, so we cannot take the dependency bump without a toolchain move and a consumer migration in the same change set.Nabat already solved the Nix-side Go 1.27 problems in its own flake: pin
pkgs.go_1_27, disable golangci-lint until upstream supports 1.27, keepGOTOOLCHAIN=localon test apps. We should mirror that here, then delete Deployah workarounds that the new Nabat covers.Note: current nixpkgs-unstable's
go_1_27is still 1.27rc2. That is fine for this PR; we can re-pin when stable lands in nixpkgs.What do you want?
A. Go 1.27 toolchain
flake.nix:go = pkgs.go_1_27;(same pattern as Nabat).go.modtogo 1.27and rungo mod tidy.gointonix/apps/quality.nixfortidy/gen-docs(today they callpkgs.goand would stay on 1.26).nix/checks.nixand stubnix run .#lint/.#fmtuntil golangci-lint#6643 ships Go 1.27 support. Override the gofmt hook to${go}/bin/gofmtso git-hooks does not keep using Go 1.26.golang:1.26.5-alpinetogolang:1.27-alpine(or1.27.0-alpineonce stable) with a fresh digest pin.deployahVendorHashvianix run .#update-vendor-hash.B. Nabat dependency + consumer migration
nabat.devingo.modto the new release and tidy.WithYes/WithBypassHint(andErrConfirmationRequired) for deploy, delete, cluster down (--force), and init overwrite. Drop custom "refusing without --yes" / string matching on"requires interactive terminal".WithPrefill/WithInitial.c.Spinner(fn, WithTitle(...))(delayed start). DeleterunMaybeSpinnerin cluster.app.Theme()in deploy/plan/cluster status; usec.Theme()/c.Renderat the command boundary (leafinternal/plancan keep an injectedResolvedTheme).statusBadgewithc.Fields+c.Badge(app owns word→icon mapping).c.JSONwhere we stillMarshalIndent+print (resolve); for plan's owned JSON schema, encode locally thenFprintHighlight/PrintHighlighton the CLI path only (keep unit goldens byte-stable if needed).nabattest.Capture/nabattest.Contextwhere it fits.Do not invent severe type-to-confirm (
WithConfirmValue) unless we add a--confirm=flag. Keep Deployah-specific pieces out of Nabat: DeployWatcher, plan+/-/~token mapping, shell raw TTY.Alternatives considered
Notes
Follow-up after golangci-lint gains 1.27 support: re-enable the pre-commit hook and restore real
nix run .#lint/.#fmtapps.