mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
The WebSocket message-type schema is the one artifact in this repository that neither component owns: `Server/ws/message_types.go` and `Client/src/lib/protocolTypes.ts` are both generated from it, and neither may be hand-edited. It nonetheless lived at `docs/protocol-schema.json` — filed under the directory for prose, whose own README calls it "Reference" material — and its generator lived at `Server/scripts/genprotocol/`, i.e. inside one of the two consumers. Ownership was legible from neither location. The obvious fix — move the generator to the repository root alongside the schema, so the whole tool is at the cross-component boundary — is wrong here. The generator is a Go `package main`, and Go modules are directory-rooted: `Server/go.mod` roots at `Server/`, so a root-level Go program needs a second module or a `go.work`. That second module would sit outside every path filter this repository already has — `golangci-lint` runs with `working-directory: Server/` (ci.yml), `go vet ./...` runs from `Server/` (scripts/run.mjs, .githooks/pre-commit), `.githooks/pre-commit` selects Go files with `^Server/.*\.go$`, `.githooks/pre-push` sets `server_changed` on `^Server/`, setup-go caches on `Server/go.sum`, and dependabot has one gomod block for `/Server`. Six gates would silently stop covering the generator, each failing open. The schema is data and moves freely; the generator is Go and stays where the Go toolchain already runs. Done instead: - `docs/protocol-schema.json` -> `protocol/schema.json`. A new top-level `protocol/` is the cross-component boundary, with a `README.md` naming the two generated consumers, the one command, and the four gates. - `Server/scripts/genprotocol/` -> `Server/cmd/genprotocol/`, the module's conventional home for an executable. This also empties `Server/scripts/` of Go entry points except `seed.go`, which RL-10 moves next. - `Server/cmd/` added to `Server/.dockerignore` and `Server/.air.toml`, which both already excluded `Server/scripts/`. Without this the move would have silently widened the Docker build context and the air watch set. 27 files, 115 insertions, 76 deletions. Two runtime path resolvers re-pointed (`cmd/genprotocol/main.go:41` `-schema` default, `ws/protocol_contract_test.go:67` `filepath.Join`); two git-hook grep patterns (`pre-commit:53`, `pre-push:57`); eight generator call sites across five files (Makefile x2, scripts/run.mjs x2, pre-commit x2, ci-check skill, bughunt-fix.js); two broken relative markdown links (docs/README.md:47, docs/protocol.md:1497); two generated files regenerated, header lines only, zero constants changed; two ledger prose hits plus a `render-ledger.mjs` re-render. No new verify was written: the regenerate-and-diff check is already enforced three times (CI `make protocol-verify`, `.githooks/pre-commit`, `npm run check:server`) and `ws/protocol_contract_test.go` independently checks the schema against the constants a fourth time. Verified: both directions, for both resolvers. With `protocol/schema.json` removed, `go test ./ws/ -run TestProtocol` fails with `reading protocol schema at /home/user/OwnCord/protocol/schema.json: no such file or directory` (two tests) and `go run ./cmd/genprotocol` exits 1 with `read schema: open ../protocol/schema.json: no such file or directory`; with the file restored both pass. So the new path is genuinely resolved, not merely spelled in a comment. The hook patterns were exercised directly: the pre-commit pattern matches `protocol/schema.json` and `Server/cmd/genprotocol/main.go` and no longer matches `docs/protocol-schema.json`; the pre-push pattern matches `protocol/schema.json`. `go run ./cmd/genprotocol` twice in a row leaves `git diff --exit-code ws/message_types.go ../Client/src/lib/protocolTypes.ts` clean, so the committed outputs are exactly what the generator emits. `go build ./...` and `go vet ./...` pass; `npx prettier --check .`, `npm run typecheck` and `npm run lint` pass; `node .superpowers/render-ledger.mjs --check` reports 348 findings valid. Not included: the four dated `docs/audit-*.md` files, the older `docs/plans/*`, and `CHANGELOG.md` keep the old path — they are point-in-time records, and `.prettierignore` and `scripts/check-doc-counts.mjs` already treat them as deliberately unmaintained. The B1 plan itself keeps its own wording, since it states intent rather than current state. `Server/scripts/` is not deleted: it still holds `seed.go` (RL-10), `k6/`, `toxiproxy/` and two shell scripts. `Server/telemetry/metrics.go:19` declares a scope for a `Server/voice` package that does not exist — spotted here, unrelated to this move, left for RL-13's sweep to carry forward verbatim rather than fixed inside a relocation. No `seed:` Make target was added. Refs RL-09, L-09
104 lines
4.4 KiB
Makefile
104 lines
4.4 KiB
Makefile
# OwnCord Server — developer convenience targets
|
|
#
|
|
# test Run the test suite the way CI does (race + timeout).
|
|
# test-deadlock Run the deadlock-detection pass CI also runs.
|
|
# fuzz Actually fuzz. CI (and plain `go test`) only replays the
|
|
# committed seed corpus; this generates new inputs.
|
|
# cover Per-package coverage (what CI uploads) + a function summary.
|
|
# cover-all Cross-package coverage — the honest number. See below.
|
|
# sqlc-generate Regenerate type-safe Go from sqlc.yaml (db/dbgen).
|
|
# sqlc-verify Fail if the committed dbgen output is stale (used by CI).
|
|
# sqlc-install Install the pinned sqlc version into $GOBIN.
|
|
# protocol-generate Regenerate WS message-type constants (Go + TS) from ../protocol/schema.json.
|
|
# protocol-verify Fail if the committed protocol constants are stale (used by CI).
|
|
# otel-up Start Jaeger + Prometheus for local tracing development.
|
|
# otel-down Stop and remove the OTel dev containers.
|
|
|
|
SQLC_VERSION := $(shell cat sqlc.version)
|
|
|
|
.PHONY: test test-deadlock fuzz cover cover-all sqlc-install sqlc-generate sqlc-verify \
|
|
protocol-generate protocol-verify otel-up otel-down
|
|
|
|
test:
|
|
go test -race -timeout 20m ./...
|
|
|
|
test-deadlock:
|
|
go test -tags deadlock -count=1 ./...
|
|
|
|
# Every Fuzz* target, one at a time. `go test ./...` (and therefore CI) runs a
|
|
# Fuzz function against its committed seed corpus only — one pass per seed,
|
|
# zero generated inputs — so the harnesses find nothing new until this runs.
|
|
# Go fuzzes exactly one target per package per invocation, hence the loop.
|
|
#
|
|
# Deliberately local-only: a crasher is written to testdata/fuzz/<Target>/<hash>
|
|
# and that file IS a working reproducer. This repo is public, so a crasher stays
|
|
# uncommitted until its fix exists, then corpus entry and fix land together as
|
|
# one regression test.
|
|
#
|
|
# No make on Windows? The same loop, straight into Git Bash:
|
|
# for pkg in $(go list ./...); do for fn in $(go test -list='^Fuzz' $pkg \
|
|
# 2>/dev/null | grep '^Fuzz'); do go test $pkg -run='^$' -fuzz="^$fn$" \
|
|
# -fuzztime=30s || break 2; done; done
|
|
FUZZTIME ?= 30s
|
|
fuzz:
|
|
@for pkg in $$(go list ./...); do \
|
|
for fn in $$(go test -list='^Fuzz' $$pkg 2>/dev/null | grep '^Fuzz'); do \
|
|
echo "── $$pkg $$fn"; \
|
|
go test $$pkg -run='^$$' -fuzz="^$$fn$$" -fuzztime=$(FUZZTIME) || exit 1; \
|
|
done; \
|
|
done
|
|
|
|
# Matches the CI invocation. Note that `go test ./... -coverprofile` instruments
|
|
# each package only for itself, so a package whose code is mostly exercised
|
|
# through another package's tests reports far lower than its real coverage
|
|
# (`service` reads ~37% here versus ~85% cross-package). Use cover-all for the
|
|
# number to reason about; this target exists to reproduce the CI artifact.
|
|
cover:
|
|
go test ./... -coverprofile=coverage.out -cover
|
|
@go tool cover -func=coverage.out | tail -1
|
|
|
|
# Cross-package coverage: every package is instrumented for every test binary,
|
|
# so code reached indirectly is counted. Prints the functions no test reaches at
|
|
# all — the list to work from when closing gaps.
|
|
cover-all:
|
|
go test -count=1 -coverpkg=./... -coverprofile=coverage-all.out ./...
|
|
@echo
|
|
@echo "── functions with no coverage ──────────────────────────────────────"
|
|
@go tool cover -func=coverage-all.out | awk '$$NF=="0.0%"' | sed 's|github.com/owncord/server/||'
|
|
@echo
|
|
@go tool cover -func=coverage-all.out | tail -1
|
|
|
|
sqlc-install:
|
|
go install github.com/sqlc-dev/sqlc/cmd/sqlc@$(SQLC_VERSION)
|
|
|
|
sqlc-generate:
|
|
sqlc generate
|
|
|
|
sqlc-verify:
|
|
sqlc generate
|
|
@git diff --exit-code db/dbgen || ( \
|
|
echo "ERROR: generated sqlc output is stale. Run 'make sqlc-generate' and commit the result." ; \
|
|
exit 1 ; \
|
|
)
|
|
|
|
protocol-generate:
|
|
go run ./cmd/genprotocol
|
|
|
|
protocol-verify:
|
|
go run ./cmd/genprotocol
|
|
@git diff --exit-code ws/message_types.go ../Client/src/lib/protocolTypes.ts || ( \
|
|
echo "ERROR: generated protocol constants are stale. Run 'make protocol-generate' and commit the result." ; \
|
|
exit 1 ; \
|
|
)
|
|
|
|
# Phase B Step 8 — local OTel development stack.
|
|
# Starts Jaeger (traces) and Prometheus (metrics) in Docker.
|
|
# Jaeger UI: http://localhost:16686
|
|
# Prometheus UI: http://localhost:9090
|
|
# Run the server with: go build -tags otel . && ./owncord-server
|
|
otel-up:
|
|
docker compose -f docker-compose.otel.yml up -d
|
|
|
|
otel-down:
|
|
docker compose -f docker-compose.otel.yml down
|