Two CI gaps surfaced on first push:
1. typecheck failed because tsc -b ran before vite build, but
src/routeTree.gen.ts is only generated by the Vite plugin during
build. tsc has nothing to typecheck against.
Fix: install @tanstack/router-cli and chain `tsr generate` before
tsc in the typecheck and build scripts. Now any environment that
runs typecheck cold (CI, fresh clone) generates the route tree
first.
Also added a top-level `route-tree` script so the same command is
reusable elsewhere if needed.
2. format:check would fail on Windows working trees because
git autocrlf (default on Windows) checks files out with CRLF, but
.prettierrc pins endOfLine: "lf". Locally the format:check
intermittently passed/failed depending on whether files had been
recently auto-formatted.
Fix: .gitattributes with `* text=auto eol=lf` enforces LF in every
working tree. Plus explicit overrides for binary blobs (images) and
the route tree file. `git add --renormalize .` brought the index in
line with the new policy; no actual file content changed.
CI on the next push should now see the same green gates the local
working tree shows.
- Dockerfile: three-stage (deps / build / runtime). deps stage runs
pnpm fetch with BuildKit cache mount; build stage runs vite build
to produce dist/; runtime stage is nginx:1.27-alpine serving the
bundle. HEALTHCHECK via wget against localhost.
- nginx.conf: gzip on text assets; /assets/ long-cache (hashed
filenames immutable); /config.json no-cache (volume-mountable
override in stage/prod); /index.html no-cache; SPA routing fallback
via try_files ... /index.html.
- .dockerignore: keeps the context small (node_modules, dist, env,
.git, .gitea, .planning, *.md except README, .claude, .vscode).
- .gitea/workflows/build.yml: matches trm/processor shape with
format:check added between lint and test. Path filter excludes
.planning and pure-markdown changes. Steps: checkout, Node 22,
pnpm@latest-9, install --frozen-lockfile, typecheck, lint,
format:check, test, buildx, registry login, build & push
trm/spa:main, Portainer webhook.
Deviations from spec:
- Push :main tag only (not :main + per-commit SHA). Matches the
other repos; SHA-pinning happens via *_TAG env vars in
trm/deploy. SHA tagging is a cross-repo refactor for later.
- Pin pnpm@latest-9 (matching existing repos), not pnpm@latest
from the spec. Reproducibility win for CI.
Smoke: typecheck/lint/format:check/build all green locally. Local
docker build not run (Docker unavailable on this machine); CI is
the gate.
Required for first deploy (1.10 covers the rest):
- REGISTRY_USERNAME / REGISTRY_PASSWORD / PORTAINER_WEBHOOK_URL
secrets in the Gitea repo settings.
- SPA service block in trm/deploy/compose.yaml.