#1 Bootstrap Go module + Cloudflare Worker build tooling #21

Merged
JMR-dev merged 1 commits from ticket-1-bootstrap into main 2026-07-02 18:22:48 +00:00
JMR-dev commented 2026-07-02 18:19:31 +00:00 (Migrated from github.com)

Bootstraps the Go module and the Go -> Cloudflare Workers build tooling — the foundation the rest of the ingest Worker builds on. Everything is structured so go test and a local dev server run on plain Go (no TinyGo), while the real Wasm Worker entrypoint is isolated behind build tags.

Approach

  • Go module: github.com/JMR-dev/LibreMail-Bug-Report-Ingest (Go 1.26).
  • Go -> Workers path: TinyGo -> Wasm via github.com/syumai/workers. Cloudflare Workers execute WebAssembly, and TinyGo produces far smaller modules than the stdlib GOOS=js GOARCH=wasm compiler — comfortably within the Worker size limit — which is why it is the standard path for Go on Workers. syumai/workers adapts Go's net/http handler model to the Workers fetch event, so a single http.Handler runs unchanged on the dev server and in the Worker.
  • Structure (works without TinyGo):
    • internal/handler/ — build-tag-free core http.Handler (GET /, GET /healthz, JSON, 404/405) plus net/http/httptest unit tests.
    • cmd/devserver/ — plain net/http server mounting the same handler for local dev.
    • worker/main.go — Workers (Wasm) entrypoint behind //go:build js && wasm, wiring the same handler; excluded from host builds/tests.
  • Node tooling: pnpm only. wrangler is a dev dependency; pnpm-workspace.yaml approves the wrangler toolchain build scripts (esbuild/sharp/workerd).
  • wrangler.jsonc: name = libremail-bug-report-ingest, main = ./build/worker.mjs, recent compatibility_date, build via pnpm run build.

Verification

go vet ./... is clean; go test ./...:

=== RUN   TestRoot
--- PASS: TestRoot (0.00s)
=== RUN   TestHealthz
--- PASS: TestHealthz (0.00s)
=== RUN   TestUnknownPathReturns404
--- PASS: TestUnknownPathReturns404 (0.00s)
=== RUN   TestNonGetReturns405
--- PASS: TestNonGetReturns405 (0.00s)
PASS
ok  	github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/handler

Hello-world runs locally via go run ./cmd/devserver:

$ curl -s localhost:8787/
{"service":"libremail-bug-report-ingest","status":"ok","message":"hello from the LibreMail bug-report ingest Worker"}
$ curl -s localhost:8787/healthz
{"status":"ok"}

As an extra signal the Wasm wiring is correct, the worker entrypoint compiles for the target — GOOS=js GOARCH=wasm go build ./worker succeeds — even though the real artifact is produced by TinyGo in CI.

TinyGo / Wasm build (documented; not run here — TinyGo intentionally absent)

pnpm run build runs, verbatim:

go run github.com/syumai/workers/cmd/workers-assets-gen && tinygo build -o ./build/app.wasm -target wasm -no-debug ./worker

TinyGo (0.35.0+) is required only for the Wasm build and is installed in CI. Local dev and tests need only plain Go. The pnpm exec wrangler dev/deploy path is documented in the README.

Out of scope / possible follow-ups

  • CI workflow (install TinyGo + pnpm, run go test, build Wasm, wrangler deploy).
  • Actual wrangler dev against a real Wasm build is not exercised locally because TinyGo is intentionally not installed on this machine.

Closes #1

Bootstraps the Go module and the Go -> Cloudflare Workers build tooling — the foundation the rest of the ingest Worker builds on. Everything is structured so `go test` and a local dev server run on **plain Go** (no TinyGo), while the real Wasm Worker entrypoint is isolated behind build tags. ## Approach - **Go module**: `github.com/JMR-dev/LibreMail-Bug-Report-Ingest` (Go 1.26). - **Go -> Workers path: TinyGo -> Wasm via [`github.com/syumai/workers`](https://github.com/syumai/workers).** Cloudflare Workers execute WebAssembly, and TinyGo produces far smaller modules than the stdlib `GOOS=js GOARCH=wasm` compiler — comfortably within the Worker size limit — which is why it is the standard path for Go on Workers. `syumai/workers` adapts Go's `net/http` handler model to the Workers `fetch` event, so a single `http.Handler` runs unchanged on the dev server and in the Worker. - **Structure (works without TinyGo)**: - `internal/handler/` — build-tag-free core `http.Handler` (`GET /`, `GET /healthz`, JSON, 404/405) plus `net/http/httptest` unit tests. - `cmd/devserver/` — plain `net/http` server mounting the same handler for local dev. - `worker/main.go` — Workers (Wasm) entrypoint behind `//go:build js && wasm`, wiring the same handler; excluded from host builds/tests. - **Node tooling**: pnpm only. `wrangler` is a dev dependency; `pnpm-workspace.yaml` approves the wrangler toolchain build scripts (esbuild/sharp/workerd). - **wrangler.jsonc**: `name = libremail-bug-report-ingest`, `main = ./build/worker.mjs`, recent `compatibility_date`, build via `pnpm run build`. ## Verification `go vet ./...` is clean; `go test ./...`: ``` === RUN TestRoot --- PASS: TestRoot (0.00s) === RUN TestHealthz --- PASS: TestHealthz (0.00s) === RUN TestUnknownPathReturns404 --- PASS: TestUnknownPathReturns404 (0.00s) === RUN TestNonGetReturns405 --- PASS: TestNonGetReturns405 (0.00s) PASS ok github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/handler ``` Hello-world runs locally via `go run ./cmd/devserver`: ``` $ curl -s localhost:8787/ {"service":"libremail-bug-report-ingest","status":"ok","message":"hello from the LibreMail bug-report ingest Worker"} $ curl -s localhost:8787/healthz {"status":"ok"} ``` As an extra signal the Wasm wiring is correct, the worker entrypoint compiles for the target — `GOOS=js GOARCH=wasm go build ./worker` succeeds — even though the real artifact is produced by TinyGo in CI. ## TinyGo / Wasm build (documented; not run here — TinyGo intentionally absent) `pnpm run build` runs, verbatim: ``` go run github.com/syumai/workers/cmd/workers-assets-gen && tinygo build -o ./build/app.wasm -target wasm -no-debug ./worker ``` TinyGo (0.35.0+) is required only for the Wasm build and is installed in CI. Local dev and tests need only plain Go. The `pnpm exec wrangler dev`/`deploy` path is documented in the README. ## Out of scope / possible follow-ups - CI workflow (install TinyGo + pnpm, run `go test`, build Wasm, `wrangler deploy`). - Actual `wrangler dev` against a real Wasm build is not exercised locally because TinyGo is intentionally not installed on this machine. Closes #1
Sign in to join this conversation.