go.mod asks for go 1.27.1 and the builder stage was golang:1.26.8-alpine,
whose GOTOOLCHAIN=local fails that build; the publish gate refuses it
before it starts. The stage now uses golang:1.27.1-alpine and sets
GOTOOLCHAIN=auto, so a later go.mod bump fetches its Go instead of
failing.
Co-authored-by: Hanzo Dev <[email protected]>
One toolchain across the estate. The tree carried 1.26.0, .1, .3, .4 and .5
at once, so which compiler built a binary depended on which repo it came
from.
Co-authored-by: Hanzo Dev <[email protected]>
The engine took a PORT and the SDK an Options.HostPort, so neither end
could use a unix socket for traffic that never leaves the host. The
field name was not the only obstacle: luxfi/zap bound net.Listen("tcp",
":port") and reached a peer with net.DialTimeout("tcp", addr), so a path
was refused at the dialer with "missing port in address" and could not
be bound at all. That is fixed upstream (luxfi/zap Address + Network);
this pins the commit until it is tagged.
EmbedConfig.Address, Embedded.Address, ServeGated(addr) and
client.Options.Address each take ONE address, because a port is a detail
of one transport rather than a thing every listener has. A path binds or
dials a unix socket; anything else is host:port.
TestDialRequiresHostPort became TestDialRequiresAddress: Dial needs an
address, and asserts a socket path is refused for being absent rather
than for being portless. TestE2E_UnixSocket runs a real workflow over a
socket end to end, and TestE2E_UnixSocketRebind proves the socket is
unlinked on stop so a restart binds cleanly.
Co-authored-by: Hanzo Dev <[email protected]>
go.mod declares `go 1.26.5` while the builder pinned golang:1.26.4. The golang
images set GOTOOLCHAIN=local, so the base can never fetch a newer toolchain to
satisfy the directive and the build dies immediately:
go: go.mod requires go >= 1.26.5 (running go 1.26.4; GOTOOLCHAIN=local)
A release build that fails in under a second did not fail to compile — it
failed to acquire a toolchain.
Found by sweeping every hanzoai repo with a go.mod against its Dockerfile base:
25 declare go >= 1.26.5, and 16 pin an explicit 1.26.4 that cannot satisfy it.
Repos on a floating `1.26` / `1.26-alpine` are already fine — both now resolve
to 1.26.5 (verified by digest: golang:1.26-alpine and golang:1.26.5-alpine are
the same sha256:0178a641).
Patch bump only, image variant preserved, and the target tag verified to exist
before the change.
Co-authored-by: Hanzo Dev <[email protected]>
The canonical CI image build failed at go mod download: the alpine build
stage has no git and no auth for the private module. Same dual-mount
(gh_token / GIT_AUTH_TOKEN) pattern as hanzoai/iam's Dockerfile; public
modules stay on proxy+sumdb (retag-proof).
Co-authored-by: hanzo-dev <[email protected]>
Per SCALE_STANDARD.md §2 — every Go production Dockerfile that emits
JSON to a client builds with GOEXPERIMENT=jsonv2. Verified on
hanzoai/zip's json_bench_test.go:
- Edge POST roundtrip: -12% time, -23% allocs
- Marshal-only: -22% time
- Unmarshal-only: -19% time, -25% allocs
The conn-memory regression test is deferred to a follow-up that
migrates tasksd's net/http listener to zip per §9 step-1; net/http
has a fixed 3-goroutine-per-request overhead that violates §3's 1:1
goroutine-to-conn invariant.
The embedded UI in tasksd is now the @hanzo/gui Tamagui build from
~/work/hanzo/gui/code/admin-tasks/. v1 React/shadcn deleted.
What's still here:
ui/embed.go — Go //go:embed wrapper (handler unchanged)
ui/dist/ — synced from admin-tasks build output
ui/README.md — explains the bundle is built externally
scripts/sync-admin-ui.sh — copies admin-tasks/dist → ui/dist + stamp
Makefile — `ui` target now calls the sync script
Dockerfile — drops the node ui-build stage; expects pre-built
dist/ in the repo or built upstream via CI
What's deleted (62 files):
ui/{src,public,node_modules}/ entire trees
ui/{package.json, vite.config.ts, tailwind.config.js, postcss.config.js,
tsconfig.json, index.html, PERF.md, .gitignore, pnpm-lock.yaml,
vite.perf2.config.ts, tsconfig.tsbuildinfo}
UI-TAMAGUI-MOVED.md (no longer accurate)
Live bundle (verified curl http://127.0.0.1:7243/):
/_/tasks/ → 200
/_/tasks/assets/index-BKuZ1al1.js → 200, 674,748 bytes
/_/tasks/assets/index-DTXHKKx4.css → 200, 9,104 bytes
/v1/tasks/namespaces → 200
Bundle: 339 KB → 675 KB raw / 104 KB → 199 KB gzip. Larger because
Tamagui ships react-native-web + Tamagui core + theme primitives
that shadcn doesn't. Trade: design-system consistency across all
Hanzo admin UIs (kms, commerce, console, etc.) vs 95 KB gzip.
CI note: .github/workflows/build.yml's docker build needs a pre-step
that checks out hanzo/gui and builds admin-tasks, OR commits ui/dist/
to this repo. Dockerfile fails fast with a clear message until then.
Tag v3.0.0 because this is a meaningful UI architecture change.
Self-contained admin UI for hanzoai/tasks. Lives in ui/, builds to
ui/dist/ via Vite 8, gets embedded into the tasksd binary with
go:embed, and is served at / on the HTTP API port (default :7234).
Stack:
- Vite 8
- React 18 + TypeScript strict
- react-router (client-side routing, deep-link safe)
- SWR (zero-config fetch + revalidation)
- Tailwind 3 (dark-first palette; no webfont)
- @hanzogui/lucide-icons-2 (shared Hanzo icon set)
v1 pages:
- /namespaces — list all namespaces + retention
- /namespaces/:ns/workflows — running + recent executions
- /namespaces/:ns/workflows/:id — describe single execution
- /namespaces/:ns/schedules — schedule list + spec
The UI talks to the existing Temporal HTTP gateway at /api/v1/*
(auto-generated from the workflowservice + operatorservice protos),
so no new backend routes were added. mux.Router registers /api/*
first, then falls through to ui.Handler() for everything else; the
SPA's client-side router takes over for unknown paths.
Build integration:
- ui/embed.go exposes Handler() over an embed.FS rooted at dist/
- Dockerfile adds a node:22-alpine UI build stage that produces
ui/dist, then the Go build stage overlays that onto the
placeholder dist/index.html already committed (so `go build`
works on a developer laptop without running pnpm first).
- service/frontend/http_api_server.go imports tasksui and mounts
at /. The existing catch-all was split:
1. PathPrefix("/api/") → Temporal gRPC-Gateway
2. PathPrefix("/") → embedded SPA
- Anything that isn't a registered /api/... handler renders the
SPA shell, which lets react-router resolve the path.
Dev workflow:
pnpm --prefix ui install
pnpm --prefix ui dev # Vite on :5173, proxies /api to :7234
go run ./cmd/tasksd embedded-sqlite # :7234 backs the API
Next: ZAP port for the internal gRPC services (task #41).
The plain `start` command on tasksd does not run sqlite/v1 schema migrations,
so a fresh /data PVC crashes with "no such table: cluster_metadata_info".
Add a new `embedded-sqlite` command that wraps temporaltest/embedded.LiteServer,
which calls sqlite.SetupSchema() before binding the frontend.
Also expose the HTTP API by default on port 7234 (gRPC stays on 7233). Without
HTTPPort the frontend is gRPC-only and clients that POST workflows/schedules
over HTTP get connection refused.
Image v2.0.2.
- GitHub Actions: parallel amd64 + arm64 on self-hosted runners
(lqd-build-amd64/arm64), multi-arch manifest, push to GAR
- Dockerfile: CGO-enabled Go build with sqlite support
- embedded-sqlite.yaml: file-based WAL persistence at /data/
- Build tags on test utility files to fix production builds
- Removed luxfi/zap local replace, using published v0.2.1
* Extract base docker image
* Move base docker images to separate files
Separate deployment and configuration steps that don't change often to base images to save time and resources.
* Cleanup, moving images from temporaliotest to temporalio
* Minor fixes
Added openssl, fixed syntax
* cleanup
Co-authored-by: Alex Shtin <[email protected]>
* Allow dynamic config editting from outside of container for
docker-compose configurations
* Stop copying dynamic config in the Dockerfile
* Make dynamic config dir configurable via DYNAMIC_CONFIG_DIR env var
Docker container can be configured to automatically register a
default domain when container starts up. Use the flag
'SKIP_DEFAULT_DOMAIN_CREATION' to skip creation of default domain.
Removed tcheck layer from Dockerfile as all tchannel rpc is now
removed. Also cleaned up unnecessary ports from docker-compose
definition.
Change all cadence references to temporal references throughout
source code and documentation.
Change docker entry point to tctl as we renamed it from temporal
to tctl.
Update mysql user login info.