Two small infrastructure gaps that cost real verification signal. Both surfaced while reviewing #212.
1. Example modules are never tested in CI
examples/*/ are separate Go modules. scripts/run_tests.sh and .github/workflows/ci.yml only build and test the root module, so nothing in examples/ is compiled or run on a PR.
Today that means these test files never execute:
examples/market-data-unwrap/discard_unknown_test.go
examples/market-data-unwrap/unwrap_shapes_test.go
examples/market-data-unwrap/unwrap_quick_check_test.go
examples/enum-encoding/…_test.go
The market-data-unwrap trio (~260 lines added in #212) is the end-to-end proof that DiscardUnknownFields reaches unwrap responses at runtime — the strongest evidence in that PR, and it runs nowhere.
There is also no drift check: examples ship checked-in generated code that no job regenerates or diffs. #212 had to absorb ~300 lines of unrelated regen churn from features merged in earlier PRs (marshalOpts threading, Accept-based content negotiation, body-first binding) purely because the example had been stale for months.
Fix: add a CI step that walks example modules, plus optionally a regen-and-diff step.
for d in examples/*/; do
[ -f "$d/go.mod" ] || continue
(cd "$d" && go build ./... && go test ./...) || exit 1
done
2. make build does not rebuild when internal/ changes
Makefile:51:
$(BIN_DIR)/%: $(CMD_DIR)/%/*.go | $(BIN_DIR)
@go build -o $@ ./$(CMD_DIR)/$*
The prerequisites list only cmd/<name>/*.go. Every generator lives in internal/, so editing generation logic does not invalidate the target and make build is a no-op.
This is actively misleading because the golden tests reuse a stale binary when one exists — e.g. internal/httpgen/unwrap_test.go:31:
if _, buildStatErr := os.Stat(pluginPath); os.IsNotExist(buildStatErr) {
// only builds when the binary is entirely absent
}
Reviewing #212 locally, this produced 5 test failures against two-month-old binaries; they vanished after rm -f bin/* && make build. A contributor verifying a codegen change can get either a false failure or a false pass with no indication why. CI is unaffected (clean checkout, no bin/), which is precisely why it stays hidden.
Fix: include the generator sources in the prerequisites, e.g.
GEN_SRCS := $(shell find internal -name '*.go' -not -name '*_test.go')
$(BIN_DIR)/%: $(CMD_DIR)/%/*.go $(GEN_SRCS) | $(BIN_DIR)
Related: #212.
Two small infrastructure gaps that cost real verification signal. Both surfaced while reviewing #212.
1. Example modules are never tested in CI
examples/*/are separate Go modules.scripts/run_tests.shand.github/workflows/ci.ymlonly build and test the root module, so nothing inexamples/is compiled or run on a PR.Today that means these test files never execute:
examples/market-data-unwrap/discard_unknown_test.goexamples/market-data-unwrap/unwrap_shapes_test.goexamples/market-data-unwrap/unwrap_quick_check_test.goexamples/enum-encoding/…_test.goThe market-data-unwrap trio (~260 lines added in #212) is the end-to-end proof that
DiscardUnknownFieldsreaches unwrap responses at runtime — the strongest evidence in that PR, and it runs nowhere.There is also no drift check: examples ship checked-in generated code that no job regenerates or diffs. #212 had to absorb ~300 lines of unrelated regen churn from features merged in earlier PRs (marshalOpts threading, Accept-based content negotiation, body-first binding) purely because the example had been stale for months.
Fix: add a CI step that walks example modules, plus optionally a regen-and-diff step.
2.
make builddoes not rebuild wheninternal/changesMakefile:51:The prerequisites list only
cmd/<name>/*.go. Every generator lives ininternal/, so editing generation logic does not invalidate the target andmake buildis a no-op.This is actively misleading because the golden tests reuse a stale binary when one exists — e.g.
internal/httpgen/unwrap_test.go:31:Reviewing #212 locally, this produced 5 test failures against two-month-old binaries; they vanished after
rm -f bin/* && make build. A contributor verifying a codegen change can get either a false failure or a false pass with no indication why. CI is unaffected (clean checkout, nobin/), which is precisely why it stays hidden.Fix: include the generator sources in the prerequisites, e.g.
Related: #212.