From 610b02ba83cf87ac767ad2cbe973d899a886c190 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Thu, 2 Jul 2026 13:30:50 -0500 Subject: [PATCH 1/4] #3 GitHub Actions CI: build, lint, test Add .github/workflows/ci.yml running on pull_request (targeting main) and push to main. A single ubuntu-latest job "ci": - checks out the repo, sets up Go 1.26, pnpm 10 + Node 22 (pnpm store cache), and TinyGo 0.41.1 (Binaryen/wasm-opt included); - runs pnpm install --frozen-lockfile, go vet ./..., go test ./...; - conditionally vets/tests an infra/ Go module if infra/go.mod exists (no-op until ticket #2 adds it); - runs pnpm run build to confirm the TinyGo/Wasm Worker builds end to end. Every action is pinned by full commit SHA with a "# vX.Y.Z" comment, matching the supply-chain style of .github/workflows/autoupdate.yml. Validated with actionlint (clean). Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6dbab4c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +# Continuous integration for the LibreMail bug-report ingest Worker. +# +# Runs on every pull request targeting main and on every push to main. One job +# vets and tests the build-tag-free Go core and then builds the TinyGo/Wasm +# Cloudflare Worker end to end, so a red check reliably means "do not merge". +# +# Supply-chain note: every action (first- and third-party) is pinned to a full +# commit SHA with a trailing "# vX.Y.Z" comment tracking the human-readable +# release, matching the style of .github/workflows/autoupdate.yml. + +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + +# Least privilege: the job only needs read access to check the repo out. +permissions: + contents: read + +# Cancel superseded runs for the same ref so rapid pushes don't pile up. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ci: + name: ci + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up Go + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 + with: + go-version: '1.26' + + # TinyGo is needed only for the Wasm Worker build (pnpm run build). The + # 0.41.x line is the first with Go 1.26 support; install-binaryen (default + # true) provides wasm-opt, which TinyGo invokes for the -target wasm build. + - name: Set up TinyGo + uses: acifani/setup-tinygo@dd8a7075d951a7595b2ef2123ed0ab1af0c13e56 # v3.0.0 + with: + tinygo-version: '0.41.1' + + - name: Set up pnpm + uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + with: + version: '10' + + # setup-node's pnpm cache needs pnpm already on PATH (hence after + # action-setup); it caches the pnpm store keyed on pnpm-lock.yaml. + - name: Set up Node + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '22' + cache: pnpm + + - name: Install Node dependencies + run: pnpm install --frozen-lockfile + + - name: Vet Go + run: go vet ./... + + - name: Test Go + run: go test ./... + + # Robust to future modules: ticket #2 will add an infra/ Go module. Guarded + # with a dir check so this is a no-op until infra/go.mod exists. + - name: Vet and test infra module (if present) + run: | + if [ -f infra/go.mod ]; then + echo "infra/go.mod present; running go vet and go test in infra/" + ( cd infra && go vet ./... && go test ./... ) + else + echo "infra/go.mod not present; skipping (no-op until ticket #2)" + fi + + # Confirms the Wasm Worker builds end to end: workers-assets-gen emits the + # JS shim and TinyGo compiles ./worker into build/app.wasm. + - name: Build Wasm Worker + run: pnpm run build From f27ad42c244ac59bc886d7a79cfc86cf6e8c1c56 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Thu, 2 Jul 2026 13:42:17 -0500 Subject: [PATCH 2/4] #26 Pin Go 1.25 + TinyGo 0.41.1 so the Wasm build compiles TinyGo 0.41.1's bundled net/http override (roundtrip_js.go) fails to compile against the Go 1.26 stdlib: net/http/roundtrip_js.go:73:12: t.roundTrip undefined (type *Transport has no field or method roundTrip, but does have method RoundTrip) This is tinygo-org/tinygo#5467 (closed 2026-06-20, but not in any tagged TinyGo release as of 0.41.1, released 2026-04-22). Go 1.25.x is the newest line TinyGo 0.41.1 fully supports; syumai/workers v0.33.0 needs only go 1.21.3 and the handler uses only net/http + encoding/json, so downgrading is safe: - go.mod: go 1.26.2 -> go 1.25.0 (so GOTOOLCHAIN won't auto-upgrade past what TinyGo supports) - ci.yml: setup-go go-version 1.26 -> 1.25 (TinyGo pin stays 0.41.1) - README: document the pinned TinyGo/Go matrix and the #5467 rationale go vet ./..., go test ./..., and actionlint stay green locally. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 15 +++++++++++---- README.md | 5 ++++- go.mod | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dbab4c..78e055a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,14 +33,21 @@ jobs: - name: Check out repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + # Pinned to Go 1.25 (not 1.26) to match TinyGo. TinyGo 0.41.1's bundled + # net/http override (roundtrip_js.go) fails to compile against the Go 1.26 + # stdlib -- "t.roundTrip undefined ... has method RoundTrip" + # (tinygo-org/tinygo#5467, unfixed in any tagged TinyGo release as of + # 0.41.1). Go 1.25.x is the newest line TinyGo 0.41.1 fully supports. The + # go.mod `go` directive is pinned to 1.25 too, so GOTOOLCHAIN won't + # auto-upgrade. go vet/test also run on this version. - name: Set up Go uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: - go-version: '1.26' + go-version: '1.25' - # TinyGo is needed only for the Wasm Worker build (pnpm run build). The - # 0.41.x line is the first with Go 1.26 support; install-binaryen (default - # true) provides wasm-opt, which TinyGo invokes for the -target wasm build. + # TinyGo is needed only for the Wasm Worker build (pnpm run build). + # install-binaryen (default true) provides wasm-opt, which TinyGo invokes + # for the -target wasm build. - name: Set up TinyGo uses: acifani/setup-tinygo@dd8a7075d951a7595b2ef2123ed0ab1af0c13e56 # v3.0.0 with: diff --git a/README.md b/README.md index e953552..5c69968 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,10 @@ This runs the exact handler the deployed Worker uses, minus the Workers runtime. ### Build & run the real Worker (requires TinyGo) Node tooling is managed with **pnpm**; wrangler is a dev dependency. The Wasm -build uses [TinyGo](https://tinygo.org) 0.35.0+. +build uses [TinyGo](https://tinygo.org) 0.41.1 on the Go 1.25.x toolchain. +(TinyGo 0.41.1 cannot compile `net/http` against Go 1.26 — see +[tinygo-org/tinygo#5467](https://github.com/tinygo-org/tinygo/issues/5467) — +so the module pins `go 1.25` in `go.mod`; CI installs and enforces this.) ```console pnpm install # install wrangler diff --git a/go.mod b/go.mod index 51c962f..17ed853 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/JMR-dev/LibreMail-Bug-Report-Ingest -go 1.26.2 +go 1.25.0 require github.com/syumai/workers v0.33.0 From bd3637d8a6ed7c8504f2f73856bf1af2adcc8741 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Thu, 2 Jul 2026 13:53:46 -0500 Subject: [PATCH 3/4] Revert Go downgrade; keep Go 1.26 per maintainer mandate Undoes the go.mod/setup-go pin to 1.25 from the previous commit. The maintainer requires Go 1.26. The TinyGo net/http wasm build failure is an upstream toolchain bug (tinygo-org/tinygo#5467) and is being resolved separately without changing the Go version. Not pushed pending the toolchain-fix decision (issue #26). Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 15 ++++----------- README.md | 5 +---- go.mod | 2 +- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78e055a..6dbab4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,21 +33,14 @@ jobs: - name: Check out repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - # Pinned to Go 1.25 (not 1.26) to match TinyGo. TinyGo 0.41.1's bundled - # net/http override (roundtrip_js.go) fails to compile against the Go 1.26 - # stdlib -- "t.roundTrip undefined ... has method RoundTrip" - # (tinygo-org/tinygo#5467, unfixed in any tagged TinyGo release as of - # 0.41.1). Go 1.25.x is the newest line TinyGo 0.41.1 fully supports. The - # go.mod `go` directive is pinned to 1.25 too, so GOTOOLCHAIN won't - # auto-upgrade. go vet/test also run on this version. - name: Set up Go uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: - go-version: '1.25' + go-version: '1.26' - # TinyGo is needed only for the Wasm Worker build (pnpm run build). - # install-binaryen (default true) provides wasm-opt, which TinyGo invokes - # for the -target wasm build. + # TinyGo is needed only for the Wasm Worker build (pnpm run build). The + # 0.41.x line is the first with Go 1.26 support; install-binaryen (default + # true) provides wasm-opt, which TinyGo invokes for the -target wasm build. - name: Set up TinyGo uses: acifani/setup-tinygo@dd8a7075d951a7595b2ef2123ed0ab1af0c13e56 # v3.0.0 with: diff --git a/README.md b/README.md index 5c69968..e953552 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,7 @@ This runs the exact handler the deployed Worker uses, minus the Workers runtime. ### Build & run the real Worker (requires TinyGo) Node tooling is managed with **pnpm**; wrangler is a dev dependency. The Wasm -build uses [TinyGo](https://tinygo.org) 0.41.1 on the Go 1.25.x toolchain. -(TinyGo 0.41.1 cannot compile `net/http` against Go 1.26 — see -[tinygo-org/tinygo#5467](https://github.com/tinygo-org/tinygo/issues/5467) — -so the module pins `go 1.25` in `go.mod`; CI installs and enforces this.) +build uses [TinyGo](https://tinygo.org) 0.35.0+. ```console pnpm install # install wrangler diff --git a/go.mod b/go.mod index 17ed853..51c962f 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/JMR-dev/LibreMail-Bug-Report-Ingest -go 1.25.0 +go 1.26.2 require github.com/syumai/workers v0.33.0 From 47f9babe358f620d8279e8343c9a8047b033db41 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Thu, 2 Jul 2026 14:06:08 -0500 Subject: [PATCH 4/4] #26 Fix TinyGo net/http wasm build via pinned upstream patch (Go 1.26) TinyGo 0.41.1 and earlier vendor tinygo-org/net@e54965e, whose net/http js/wasm overlay (roundtrip_js.go) calls the private t.roundTrip fallback removed from Go 1.25+/1.26 net/http, so `pnpm run build` fails to compile on Go 1.26 (tinygo-org/tinygo#5467). No released TinyGo carries the fix yet: it landed in tinygo-org/net@1026408a on 2026-04-27, after 0.41.1 shipped 2026-04-22, and is already on TinyGo's dev branch. Keep Go 1.26 and apply the exact upstream fix in CI before the build: - .ci/tinygo-net-roundtrip.patch: byte-exact tinygo-org/net@1026408a diff (its parent e54965e is the commit 0.41.1 ships), targeting src/net/http/roundtrip_js.go. - ci.yml: new "Patch TinyGo net/http (temporary)" step applies it to $(tinygo env TINYGOROOT) via `git apply`, failing loudly on drift. - .gitattributes: force LF on *.patch so `git apply` works on the Linux runner regardless of the committer's platform. - README: document the temporary patch and its removal condition. Temporary: remove the patch and the CI step once a TinyGo release later than 0.41.1 ships the net fix. Tracking #26. Co-Authored-By: Claude Opus 4.8 --- .ci/tinygo-net-roundtrip.patch | 36 ++++++++++++++++++++++++++++++++++ .gitattributes | 4 ++++ .github/workflows/ci.yml | 26 +++++++++++++++++++++--- README.md | 12 +++++++++++- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 .ci/tinygo-net-roundtrip.patch create mode 100644 .gitattributes diff --git a/.ci/tinygo-net-roundtrip.patch b/.ci/tinygo-net-roundtrip.patch new file mode 100644 index 0000000..65db49f --- /dev/null +++ b/.ci/tinygo-net-roundtrip.patch @@ -0,0 +1,36 @@ +Temporary CI patch: fix the TinyGo net/http js/wasm build on Go 1.25/1.26. + +TinyGo <= 0.41.1 vendors github.com/tinygo-org/net at commit e54965e, whose +http/roundtrip_js.go calls the private t.roundTrip fallback that no longer +exists in Go 1.25+/1.26 net/http, so any wasm build importing net/http fails: + + net/http/roundtrip_js.go: t.roundTrip undefined (type *Transport has no + field or method roundTrip, but does have method RoundTrip) + +This is the exact upstream fix tinygo-org/net@1026408a ("http: fix t.roundTrip +undefined on js/wasm builds", whose parent is e54965e -- the commit TinyGo +0.41.1 ships), applied to the installed TinyGo source in CI before the wasm +build. The .patch is applied by the "Patch TinyGo net/http (temporary)" step +in .github/workflows/ci.yml. + +TODO: remove this file AND that CI step once a TinyGo release > 0.41.1 ships +the fix. It is already on TinyGo's dev branch (which pins tinygo-org/net@ +1026408a). Tracking: issue #26; upstream tinygo-org/tinygo#5467. + +diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go +--- a/src/net/http/roundtrip_js.go ++++ b/src/net/http/roundtrip_js.go +@@ -68,9 +68,11 @@ + // to fall back on the Fetch API, unless it's not available. + + // TINYGO: Dial/DialTLS & DialContext/DialTLSContext are not present in tinygo Transport struct, therefore the +- // corresponding if statements were removed ++ // corresponding if statements were removed. ++ // TINYGO: t.roundTrip (the private fallback used by upstream Go) is not present in the TinyGo stub ++ // Transport, so return an error when the Fetch API is unavailable instead of calling it. + if jsFetchMissing || jsFetchDisabled { +- return t.roundTrip(req) ++ return nil, errors.New("net/http: Fetch API is not available and no fallback transport is implemented for js/wasm") + } + + ac := js.Global().Get("AbortController") diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a518a5f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Keep CI-critical text files LF on every platform. .ci/*.patch is applied with +# `git apply` against TinyGo's Unix (LF) source in CI, so it must never be +# checked out with CRLF (which would make the patch fail to apply). +*.patch text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dbab4c..d43f1c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,10 @@ jobs: with: go-version: '1.26' - # TinyGo is needed only for the Wasm Worker build (pnpm run build). The - # 0.41.x line is the first with Go 1.26 support; install-binaryen (default - # true) provides wasm-opt, which TinyGo invokes for the -target wasm build. + # TinyGo is needed only for the Wasm Worker build (pnpm run build). + # install-binaryen (default true) provides wasm-opt, which TinyGo invokes + # for the -target wasm build. 0.41.1's vendored net/http js overlay is + # patched just before the build (see "Patch TinyGo net/http" below). - name: Set up TinyGo uses: acifani/setup-tinygo@dd8a7075d951a7595b2ef2123ed0ab1af0c13e56 # v3.0.0 with: @@ -79,6 +80,25 @@ jobs: echo "infra/go.mod not present; skipping (no-op until ticket #2)" fi + # TEMPORARY (tracking #26; tinygo-org/tinygo#5467): TinyGo 0.41.1 and + # earlier vendor tinygo-org/net@e54965e, whose net/http js/wasm overlay + # (roundtrip_js.go) calls the private t.roundTrip fallback that no longer + # exists in Go 1.25+/1.26 net/http, so the wasm build fails to compile. + # Apply the exact upstream fix (tinygo-org/net@1026408a) to the installed + # TinyGo source. git apply exits non-zero (failing the job loudly) if the + # source has drifted, so we notice when TinyGo changes upstream. + # TODO: delete this step and .ci/tinygo-net-roundtrip.patch once a TinyGo + # release later than 0.41.1 ships the fix (already on TinyGo's dev branch). + - name: Patch TinyGo net/http (temporary) + run: | + patch_file="$PWD/.ci/tinygo-net-roundtrip.patch" + tinygoroot="$(tinygo env TINYGOROOT)" + echo "Applying $patch_file to $tinygoroot/src/net/http/roundtrip_js.go" + git -C "$tinygoroot" apply --verbose "$patch_file" || { + echo "::error::TinyGo net/http patch did not apply cleanly; TinyGo source may have changed. Update or remove .ci/tinygo-net-roundtrip.patch (see #26)." + exit 1 + } + # Confirms the Wasm Worker builds end to end: workers-assets-gen emits the # JS shim and TinyGo compiles ./worker into build/app.wasm. - name: Build Wasm Worker diff --git a/README.md b/README.md index e953552..699570d 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,17 @@ This runs the exact handler the deployed Worker uses, minus the Workers runtime. ### Build & run the real Worker (requires TinyGo) Node tooling is managed with **pnpm**; wrangler is a dev dependency. The Wasm -build uses [TinyGo](https://tinygo.org) 0.35.0+. +build uses [TinyGo](https://tinygo.org) 0.41.1 on the Go 1.26 toolchain. + +> **Temporary toolchain patch.** TinyGo 0.41.1 and earlier vendor a `net/http` +> js/wasm overlay (`tinygo-org/net@e54965e`) that fails to compile against Go +> 1.25+/1.26 with `t.roundTrip undefined` (see +> [tinygo-org/tinygo#5467](https://github.com/tinygo-org/tinygo/issues/5467)). +> CI applies the exact upstream fix (`tinygo-org/net@1026408a`, checked in as +> `.ci/tinygo-net-roundtrip.patch`) to the installed TinyGo before building. +> Building locally on Go 1.26 needs the same one-file patch until a TinyGo +> release later than 0.41.1 ships it, at which point the patch and the CI step +> are removed (tracked in #26). ```console pnpm install # install wrangler