diff --git a/.gitea/workflows/fbs-codegen.yaml b/.gitea/workflows/fbs-codegen.yaml new file mode 100644 index 0000000..d3db2f6 --- /dev/null +++ b/.gitea/workflows/fbs-codegen.yaml @@ -0,0 +1,80 @@ +name: Tests · FBS codegen + +# Guards that the committed FlatBuffers bindings (Go under +# pkg/schema/fbs// and TS under ui/frontend/src/proto/galaxy/fbs/) +# are exactly what the pinned flatc produces from the .fbs schemas. +# Catches both "changed a schema but forgot to regenerate" and +# "regenerated with the wrong flatc version" (e.g. a distro's older +# flatbuffers-compiler), which silently churns output and can flip +# nullable-scalar wire defaults. Path-filtered so it only runs when the +# schemas, the generated trees, the fbs Makefiles, or this workflow change. + +on: + push: + paths: + - 'pkg/schema/fbs/**' + - 'ui/frontend/src/proto/galaxy/fbs/**' + - 'ui/Makefile' + - '.gitea/workflows/fbs-codegen.yaml' + pull_request: + paths: + - 'pkg/schema/fbs/**' + - 'ui/frontend/src/proto/galaxy/fbs/**' + - 'ui/Makefile' + - '.gitea/workflows/fbs-codegen.yaml' + +concurrency: + group: fbs-codegen-${{ github.ref }} + cancel-in-progress: true + +env: + FLATC_VERSION: 25.9.23 + +jobs: + codegen: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Cache flatc + id: cache-flatc + uses: actions/cache@v4 + with: + path: ${{ runner.temp }}/flatc-bin + key: flatc-${{ env.FLATC_VERSION }}-linux-g++13 + + - name: Install pinned flatc + if: steps.cache-flatc.outputs.cache-hit != 'true' + run: | + mkdir -p "${{ runner.temp }}/flatc-bin" + curl -sSL -o /tmp/flatc.zip \ + "https://github.com/google/flatbuffers/releases/download/v${FLATC_VERSION}/Linux.flatc.binary.g++-13.zip" + python3 -m zipfile -e /tmp/flatc.zip "${{ runner.temp }}/flatc-bin" + chmod +x "${{ runner.temp }}/flatc-bin/flatc" + + - name: Add flatc to PATH + run: echo "${{ runner.temp }}/flatc-bin" >> "$GITHUB_PATH" + + - name: Verify flatc version + run: flatc --version + + - name: Regenerate Go + TS bindings + run: | + make -C pkg/schema/fbs fbs-go + make -C ui fbs-ts + + - name: Assert no drift + run: | + if ! git diff --exit-code || [ -n "$(git status --porcelain)" ]; then + echo "::error::Committed FlatBuffers bindings differ from a flatc ${FLATC_VERSION} regeneration." + echo "Run 'make -C pkg/schema/fbs fbs-go' and 'make -C ui fbs-ts' with flatc ${FLATC_VERSION} and commit the result." + git status --porcelain + git --no-pager diff + exit 1 + fi diff --git a/gateway/go.mod b/gateway/go.mod index c1cef6f..f8ea7ee 100644 --- a/gateway/go.mod +++ b/gateway/go.mod @@ -11,7 +11,7 @@ require ( github.com/alicebob/miniredis/v2 v2.37.0 github.com/getkin/kin-openapi v0.135.0 github.com/gin-gonic/gin v1.12.0 - github.com/google/flatbuffers v25.12.19+incompatible + github.com/google/flatbuffers v25.9.23+incompatible github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.23.2 github.com/redis/go-redis/v9 v9.18.0 diff --git a/gateway/go.sum b/gateway/go.sum index a06e0b0..69f1cc8 100644 --- a/gateway/go.sum +++ b/gateway/go.sum @@ -73,8 +73,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= -github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs= -github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v25.9.23+incompatible h1:rGZKv+wOb6QPzIdkM2KxhBZCDrA0DeN6DNmRDrqIsQU= +github.com/google/flatbuffers v25.9.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= diff --git a/integration/go.mod b/integration/go.mod index 94ce8f4..f2bfdeb 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -36,7 +36,7 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/google/flatbuffers v25.12.19+incompatible // indirect + github.com/google/flatbuffers v25.9.23+incompatible // indirect github.com/jackc/pgx/v5 v5.9.2 // indirect github.com/klauspost/compress v1.18.5 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect diff --git a/integration/go.sum b/integration/go.sum index 1e861b7..40ff839 100644 --- a/integration/go.sum +++ b/integration/go.sum @@ -47,8 +47,8 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs= -github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v25.9.23+incompatible h1:rGZKv+wOb6QPzIdkM2KxhBZCDrA0DeN6DNmRDrqIsQU= +github.com/google/flatbuffers v25.9.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= diff --git a/pkg/schema/fbs/Makefile b/pkg/schema/fbs/Makefile new file mode 100644 index 0000000..e2bd32d --- /dev/null +++ b/pkg/schema/fbs/Makefile @@ -0,0 +1,26 @@ +.PHONY: help fbs-go flatc-check + +# Pinned flatc version. The committed Go bindings under / and the +# flatbuffers Go runtime (go.mod) are on this version; the TS side mirrors +# it via `make -C ui fbs-ts`. Generating with a different flatc silently +# churns output and can flip nullable-scalar wire defaults, so fbs-go +# refuses to run on a mismatch. Distro packages (e.g. Debian's +# flatbuffers-compiler) are too old — use the release binary at $(FLATC_URL). +REQUIRED_FLATC := 25.9.23 +FLATC_URL := https://github.com/google/flatbuffers/releases/tag/v$(REQUIRED_FLATC) +# Every schema in this directory. Listed explicitly (not a wildcard) so a +# stray .fbs cannot silently change the generated set. +FBS_INPUTS := common.fbs lobby.fbs user.fbs report.fbs order.fbs diplomail.fbs battle.fbs gateway.fbs notification.fbs + +help: + @echo "schema/fbs targets:" + @echo " fbs-go FlatBuffers Go generation from *.fbs into / (requires flatc $(REQUIRED_FLATC))" + +flatc-check: + @command -v flatc >/dev/null || { echo "flatc not found; install flatc $(REQUIRED_FLATC) from $(FLATC_URL) (distro packages such as Debian's flatbuffers-compiler are too old)"; exit 1; } + @flatc --version | grep -q "$(REQUIRED_FLATC)" || { echo "flatc $(REQUIRED_FLATC) required; found '$$(flatc --version)'. Get the pinned binary from $(FLATC_URL)"; exit 1; } + +# --go-module-name rewrites cross-namespace imports to the fully-qualified +# module path so the generated code links without local replace directives. +fbs-go: flatc-check + flatc --go --go-module-name galaxy/schema/fbs $(FBS_INPUTS) diff --git a/pkg/schema/fbs/README.md b/pkg/schema/fbs/README.md index d8443dd..61dfc98 100644 --- a/pkg/schema/fbs/README.md +++ b/pkg/schema/fbs/README.md @@ -1,9 +1,32 @@ # Flatbuffers schemas +## Pinned flatc version + +The committed bindings — Go under `/` and TS under +`ui/frontend/src/proto/galaxy/fbs/` — and the flatbuffers runtimes +(`github.com/google/flatbuffers` in the Go modules, `flatbuffers` in +`ui/frontend/package.json`) are all on **flatc 25.9.23**. Regenerate +only with that exact version: a different flatc silently churns output +and can flip nullable-scalar wire defaults (`= null` builder slots +switch between the presence-preserving `null` form and the value-omitting +`0` form). The `fbs-go` / `fbs-ts` targets refuse to run on a mismatch, +and the `fbs-codegen` CI workflow fails if the committed bindings differ +from a pinned-flatc regeneration. + +Distro packages are too old (e.g. Debian trixie ships `flatbuffers-compiler` +23.5.26). Install the pinned binary from the release page: +. + ## Generating sources -Given a `.fbs` file, source code can be generated using `flatc` from -this directory: +Regenerate both sides with the pinned `flatc` on `PATH`: + +```shell +make -C pkg/schema/fbs fbs-go # Go bindings into pkg/schema/fbs// +make -C ui fbs-ts # TS bindings into ui/frontend/src/proto/galaxy/fbs/ +``` + +`fbs-go` runs, for every schema in this directory: ```shell flatc --go --go-module-name galaxy/schema/fbs {file}.fbs diff --git a/pkg/schema/go.mod b/pkg/schema/go.mod index a8e7edf..29bd16b 100644 --- a/pkg/schema/go.mod +++ b/pkg/schema/go.mod @@ -2,4 +2,4 @@ module galaxy/schema go 1.26.0 -require github.com/google/flatbuffers v25.12.19+incompatible +require github.com/google/flatbuffers v25.9.23+incompatible diff --git a/pkg/schema/go.sum b/pkg/schema/go.sum index 799c59f..ebeec69 100644 --- a/pkg/schema/go.sum +++ b/pkg/schema/go.sum @@ -1,2 +1,4 @@ +github.com/google/flatbuffers v25.9.23+incompatible h1:rGZKv+wOb6QPzIdkM2KxhBZCDrA0DeN6DNmRDrqIsQU= +github.com/google/flatbuffers v25.9.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs= github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= diff --git a/pkg/transcoder/go.mod b/pkg/transcoder/go.mod index e8a8427..25c2dd3 100644 --- a/pkg/transcoder/go.mod +++ b/pkg/transcoder/go.mod @@ -3,6 +3,6 @@ module galaxy/transcoder go 1.26.0 require ( - github.com/google/flatbuffers v25.12.19+incompatible + github.com/google/flatbuffers v25.9.23+incompatible github.com/google/uuid v1.6.0 ) diff --git a/pkg/transcoder/go.sum b/pkg/transcoder/go.sum index d065e30..b86ce23 100644 --- a/pkg/transcoder/go.sum +++ b/pkg/transcoder/go.sum @@ -1,2 +1,4 @@ -github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs= +github.com/google/flatbuffers v25.9.23+incompatible h1:rGZKv+wOb6QPzIdkM2KxhBZCDrA0DeN6DNmRDrqIsQU= +github.com/google/flatbuffers v25.9.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/ui/Makefile b/ui/Makefile index db05e4f..b96b7c4 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -1,4 +1,4 @@ -.PHONY: help web wasm ts-protos fbs-ts gomobile desktop-mac desktop-win desktop-linux ios android all +.PHONY: help web wasm ts-protos fbs-ts flatc-check gomobile desktop-mac desktop-win desktop-linux ios android all .DEFAULT_GOAL := help @@ -7,12 +7,20 @@ WASM_EXEC := frontend/static/wasm_exec.js TINYGO_ROOT := $(shell tinygo env TINYGOROOT 2>/dev/null) FBS_OUT := frontend/src/proto/galaxy/fbs FBS_INPUTS := ../pkg/schema/fbs/common.fbs ../pkg/schema/fbs/lobby.fbs ../pkg/schema/fbs/user.fbs ../pkg/schema/fbs/report.fbs ../pkg/schema/fbs/order.fbs ../pkg/schema/fbs/diplomail.fbs ../pkg/schema/fbs/battle.fbs +# Pinned flatc version. The committed bindings (Go + TS) and the +# flatbuffers Go/TS runtimes are all on this version; generating with a +# different flatc silently churns output and can flip nullable-scalar +# wire defaults, so fbs-ts refuses to run on a mismatch. Distro packages +# (e.g. Debian's flatbuffers-compiler) are too old — use the release +# binary at $(FLATC_URL). +REQUIRED_FLATC := 25.9.23 +FLATC_URL := https://github.com/google/flatbuffers/releases/tag/v$(REQUIRED_FLATC) help: @echo "ui targets:" @echo " wasm TinyGo build of ui/core to core.wasm + wasm_exec.js shim (Phase 5)" @echo " ts-protos Connect-ES + Protobuf-ES generation from gateway/proto (Phase 5)" - @echo " fbs-ts FlatBuffers TS generation from pkg/schema/fbs/*.fbs (Phase 8)" + @echo " fbs-ts FlatBuffers TS generation from pkg/schema/fbs/*.fbs (requires flatc $(REQUIRED_FLATC))" @echo " web Vite production build (Phase 5+)" @echo " gomobile gomobile bind for iOS .framework + Android .aar (Phase 32+)" @echo " desktop-mac Wails build for darwin/{arm64,amd64} (Phase 31)" @@ -33,8 +41,11 @@ ts-protos: @test -x frontend/node_modules/.bin/protoc-gen-es || { echo "protoc-gen-es not installed; run 'pnpm install' inside ui/frontend"; exit 1; } buf generate ../gateway --template buf.gen.yaml --include-imports -fbs-ts: - @command -v flatc >/dev/null || { echo "flatc not found; install via 'brew install flatbuffers' (macOS) or 'apt-get install -y flatbuffers-compiler' (Linux)"; exit 1; } +flatc-check: + @command -v flatc >/dev/null || { echo "flatc not found; install flatc $(REQUIRED_FLATC) from $(FLATC_URL) (distro packages such as Debian's flatbuffers-compiler are too old)"; exit 1; } + @flatc --version | grep -q "$(REQUIRED_FLATC)" || { echo "flatc $(REQUIRED_FLATC) required; found '$$(flatc --version)'. Get the pinned binary from $(FLATC_URL)"; exit 1; } + +fbs-ts: flatc-check mkdir -p $(FBS_OUT) flatc --ts --gen-object-api -o $(FBS_OUT) $(FBS_INPUTS) diff --git a/ui/frontend/src/proto/galaxy/fbs/order/command-item.ts b/ui/frontend/src/proto/galaxy/fbs/order/command-item.ts index 7cbb98e..ffee5ac 100644 --- a/ui/frontend/src/proto/galaxy/fbs/order/command-item.ts +++ b/ui/frontend/src/proto/galaxy/fbs/order/command-item.ts @@ -91,11 +91,11 @@ static addCmdId(builder:flatbuffers.Builder, cmdIdOffset:flatbuffers.Offset) { } static addCmdApplied(builder:flatbuffers.Builder, cmdApplied:boolean) { - builder.addFieldInt8(1, +cmdApplied, 0); + builder.addFieldInt8(1, +cmdApplied, null); } static addCmdErrorCode(builder:flatbuffers.Builder, cmdErrorCode:bigint) { - builder.addFieldInt64(2, cmdErrorCode, BigInt(0)); + builder.addFieldInt64(2, cmdErrorCode, null); } static addPayloadType(builder:flatbuffers.Builder, payloadType:CommandPayload) {