mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* feat(b3-6): contract drift — generated route, table and config-key indexes B3-6 item 9 (workstream 10). `check:server` already diffs the two generators; this adds a third for the three server contracts that only prose described until now. `Server/cmd/gendocs` rewrites one marked block per document: - `docs/api.md` "Route index (generated)" — 111 rows from `chi.Walk` over the production router built with uploads, voice and the GIF proxy on, the same scaffolding `api/absence_contract_test.go` uses. Carries that test's vacuity guards: fewer than 100 routes, or no `/admin/` route, fails the run. - `docs/schema.md` "Table index (generated)" — 34 rows from `sqlite_master` and `pragma_table_info` on an in-memory database with the migrations applied. sqlc exposes no catalog, so the migrated schema is the catalog. - `docs/server-configuration.md` "Key index (generated)" — 56 keys from the koanf struct tags, each mapped to the `###` section of the hand-written reference that names it. A key documented nowhere fails the run by name. Output is padded exactly the way Prettier formats a table, so the drift check and the hygiene gate agree instead of undoing each other. Wiring, copied from protocol-verify: `make docs-generate` / `make docs-verify`, a `DOCS_VERIFY` step in `check:server` and the generator in `generate` (`scripts/run.mjs`), a CI step on the ubuntu leg of `server-build-test`, and a `.githooks/pre-commit` block on router, handler, migration, config and generator paths. Everything hand-written in the three documents is untouched. The new `cmd/gendocs` file imports `db` for the catalog, so it takes a boundary row in the B3-0 inventory and `server-boundaries.md` is regenerated with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * docs(b3-6): evidence block for item 9 (machine-readable contract drift) Records the three RED controls and their restore, the counts (111 routes, 34 tables, 56 config keys, 0 undocumented), and two corrections to the item's spec: the configuration reference table lives in docs/server-configuration.md, not docs/deployment.md, and sqlc exposes no catalog — the migrated in-memory schema is the catalog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * fix(b3-6): gendocs — exclude ANALYZE artifacts, honest hook message, admin routes trigger the hook, generate order, width ceiling Review findings on item 9. 1. The table index dropped `sqlite_stat1` / `sqlite_stat4`. `db.Migrate` runs ANALYZE after applying migrations, so those hold planner statistics, not schema — and `sqlite_stat4` exists only because the current modernc.org/sqlite build has STAT4, so a driver bump would have failed the docs drift check on an unrelated dependency PR. Filtered with GLOB (LIKE's `_` is a wildcard), block regenerated, header line's justification corrected: 34 -> 32 tables. 2. The pre-commit message now covers both failure modes — stale blocks are regenerated and staged, a key the tool named as undocumented is documented in docs/server-configuration.md. 3. `Server/admin/.*\.go` added to the hook's trigger: the 34 `/admin/api/*` routes are registered there, not in api/router.go, so a new admin route could commit stale docs locally. 4. `run.mjs` `generate` runs gendocs after `sqlc generate` — gendocs compiles the api package, which imports db/dbgen. 5. The vacuity guard now requires a traversed `/admin/api/` subroute rather than any `/admin/` path, which the per-method mount catch-alls satisfied on their own, so its message is true. `writeTable` gained a comment naming its ceiling: padding counts runes, Prettier counts display width, so a full-width cell would diverge — none exists in the generated content. Evidence block updated for the new table count. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * fix(b3-6): gendocs — generate the route index from the full-tag build with telemetry on; the hook triggers on every api/ and admin/ Go file (Codex P2s on #1456) 1. `/metrics` was missing from the route index. It mounts only when `telemetry.PrometheusHandler()` returns non-nil (api/router.go:431-437), which needs the otel build tag AND telemetry enabled at runtime; the generator ran in the default build with telemetry unset, so the index omitted a production route. The route index is now the superset build. The scaffold config enables telemetry with the Prometheus exporter and the tool calls telemetry.Init the way main.go does, and every invocation passes -tags otel,wazero: Makefile docs-generate/docs-verify, scripts/run.mjs (DOCS_VERIFY and generate), .githooks/pre-commit, the regenCmd quoted into all three block header lines, and the CLAUDE.md row. ci.yml inherits it through `make docs-verify`. The route block's header line now says which build it came from and what is enabled. Rather than a build-tag constant, the tool checks the condition that actually gates the route: if telemetry.Init leaves no Prometheus handler it exits non-zero naming the tags, so the default build cannot quietly generate a short index. Nothing under Server/api or Server/admin carries a build constraint, so wazero adds and removes no route; it rides along so one build serves the whole repository. Route count 111 -> 121 (ten per-method rows for the /metrics mount, the same shape chi gives /admin and /livekit). 2. The pre-commit trigger named individual api/ files and missed client_update.go, whose MountClientUpdateRoute registers a route directly. It is now the whole of Server/api/ and Server/admin/ — naming files individually is how a trigger goes stale — plus the existing migrations/, config/config.go and cmd/gendocs/ patterns. Evidence block updated: route count and the tagged-build decision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
123 lines
5.3 KiB
Makefile
123 lines
5.3 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).
|
|
# docs-generate Regenerate the route/table/config index blocks in ../docs.
|
|
# docs-verify Fail if those generated blocks 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 docs-generate docs-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/J3vb/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 ; \
|
|
)
|
|
|
|
# Route, table and config-key indexes in ../docs. Same shape as the two
|
|
# generator checks above: regenerate, then fail on any diff. The tool also
|
|
# exits non-zero on its own when a config key is documented nowhere.
|
|
#
|
|
# -tags otel,wazero is not optional: /metrics mounts only when the otel build
|
|
# supplies a Prometheus handler, so the default build would generate an index
|
|
# missing a production route. The tool refuses to run without it.
|
|
docs-generate:
|
|
go run -tags otel,wazero ./cmd/gendocs
|
|
|
|
docs-verify:
|
|
go run -tags otel,wazero ./cmd/gendocs
|
|
@git diff --exit-code ../docs/api.md ../docs/schema.md ../docs/server-configuration.md || ( \
|
|
echo "ERROR: generated documentation blocks are stale. Run 'make docs-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
|