diff --git a/.copier/backend.yml b/.copier/backend.yml index a2ed819..c5d2d45 100644 --- a/.copier/backend.yml +++ b/.copier/backend.yml @@ -1,4 +1,4 @@ -_commit: v0.1.0 +_commit: v0.3.0 _src_path: https://git.kotikot.com/templates/blank.git layout: part part: backend diff --git a/.copier/caddy.yml b/.copier/caddy.yml index 1613101..51ca6a9 100644 --- a/.copier/caddy.yml +++ b/.copier/caddy.yml @@ -1,4 +1,4 @@ -_commit: v0.1.2 +_commit: v0.1.4 _src_path: https://git.kotikot.com/templates/caddy.git project_slug: lodge routes: diff --git a/.copier/frontend.yml b/.copier/frontend.yml index 0504345..91a189b 100644 --- a/.copier/frontend.yml +++ b/.copier/frontend.yml @@ -1,8 +1,8 @@ -_commit: v0.3.1 +_commit: v0.6.0 _src_path: https://git.kotikot.com/templates/frontend-svelte.git -include_impeccable: true install_deps: true layout: part +linter: biome project_name: lodge project_slug: lodge serve: api diff --git a/.copier/infra.yml b/.copier/infra.yml index b6e0e21..030ae13 100644 --- a/.copier/infra.yml +++ b/.copier/infra.yml @@ -1,7 +1,9 @@ -_commit: v0.4.0 +_commit: v0.6.0 _src_path: https://git.kotikot.com/templates/infra.git init_git: true layout: parts +mcp_servers: +- svelte parts: - backend - frontend diff --git a/.gitignore b/.gitignore index 817009b..e9d0980 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ docker-compose.override.yml .DS_Store .idea + +# Local playground +/t/ diff --git a/Makefile b/Makefile index 59a9fb0..07ff450 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,19 @@ PARTS := $(patsubst %/Makefile,%,$(wildcard */Makefile)) -.PHONY: env recreate rebuild restart logs down deploy fmt check build pre-deploy post-deploy +.PHONY: env recreate rebuild restart logs down fmt check build env: - @test -f .env || awk 'FNR == 1 && NR > 1 { print "" } 1' .env.example $(addsuffix /.env.example,$(PARTS)) > .env - @for part in $(PARTS); do test -f $$part/docker-compose.override.yml || cp $$part/docker-compose.override.yml.example $$part/docker-compose.override.yml; done + @fresh=; test -f .env || { awk 'FNR == 1 && NR > 1 { print "" } 1' .env.example $(addsuffix /.env.example,$(PARTS)) > .env; fresh=1; }; \ + for part in $(PARTS); do \ + override=$$part/docker-compose.override.yml; \ + test -f $$override && continue; \ + cp $$override.example $$override; \ + for port in $$(sed -n 's/.*127\.0\.0\.1:\([0-9]*\):.*/\1/p' $$override | sort -u); do \ + random=$$((20000 + $$(od -An -N2 -tu2 /dev/urandom) % 40000)); \ + sed "s/127\.0\.0\.1:$$port:/127.0.0.1:$$random:/" $$override > $$override.tmp && mv $$override.tmp $$override; \ + test -z "$$fresh" || { sed "s|localhost:$$port/|localhost:$$random/|" .env > .env.tmp && mv .env.tmp .env; }; \ + done; \ + done recreate: docker compose up -d --force-recreate @@ -21,9 +30,5 @@ logs: down: docker compose down -deploy: pre-deploy - docker compose up -d - $(MAKE) post-deploy - -fmt check build pre-deploy post-deploy: +fmt check build: @for part in $(PARTS); do $(MAKE) -C $$part $@ || exit 1; done diff --git a/README.md b/README.md index 7075f2a..03238cf 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,13 @@ sync for files not meant to be in git -Runs in Docker, locally the same way as in production. Each part in `backend/`, `frontend/` brings its own `docker-compose.yml`, included from the root one. `COMPOSE_PROFILES` in `.env` selects the services that run on this machine. `docker-compose.override.yml` in each part holds what differs between machines: published ports and the aliases on the external `caddy` network. - ```sh -make env -make recreate +make env # .env and docker-compose.override.yml from the examples +make recreate # the services in COMPOSE_PROFILES +make check ``` -`make env` creates `.env` from the examples of every part and copies each `docker-compose.override.yml.example`. `make recreate` starts the selected profiles, `make rebuild` builds the images first, `make logs`, `make restart` and `make down` do what they say. - -To deploy, `git pull && make deploy`. It runs `make pre-deploy` in every part, which builds images only when their inputs changed and applies migrations, then `docker compose up -d`, then `make post-deploy`, which restarts the services whose mounted code changed. A deploy system with its own `up` step calls the two hooks around it. What was built and started is remembered as `refs/deploy/*` in the clone. - -`make fmt`, `make check` and `make build` run in every part. Part-specific targets live in the part's own Makefile: `make -C backend ...`. +Parts: `backend/`, `frontend/`, each with its own Makefile. ## How it works diff --git a/backend/Makefile b/backend/Makefile index 73eb346..e10a322 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,10 +1,7 @@ COMPOSE := cd .. && docker compose -IMAGE := lodge/backend LINT := go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.13.2 -changed = ! git diff --quiet $(1) -- $(2) 2>/dev/null -stamp = { git update-ref $(1) HEAD 2>/dev/null || true; } -.PHONY: fmt check test build pre-deploy post-deploy client dev +.PHONY: fmt check test build client dev fmt: go mod tidy @@ -20,14 +17,6 @@ test: build: $(COMPOSE) build api -pre-deploy: - @if $(call changed,refs/deploy/backend,.) || ! docker image inspect $(IMAGE) >/dev/null 2>&1; then \ - $(MAKE) build && $(call stamp,refs/deploy/backend); \ - fi - -post-deploy: - @: - client: go build -trimpath -ldflags "-s -w" -o bin/lodge ./cmd/lodge diff --git a/caddy/.gitignore b/caddy/.gitignore index acd0b35..a9e5752 100644 --- a/caddy/.gitignore +++ b/caddy/.gitignore @@ -1,2 +1,2 @@ .env -Caddyfile +/Caddyfile diff --git a/caddy/README.md b/caddy/README.md index ebd199d..23fce9c 100644 --- a/caddy/README.md +++ b/caddy/README.md @@ -1,22 +1,3 @@ # caddy -`site.caddy` routes `{$LODGE_DOMAIN}` to the project's services over the external `caddy` docker network. It works standalone and inside a shared Caddy that fronts several projects. - -Standalone: - -```sh -docker network create caddy -cp Caddyfile.example Caddyfile -cp .env.example .env -docker compose up -d -``` - -Shared Caddy: mount this directory as `/etc/caddy/projects.d/lodge:ro`, keep `import /etc/caddy/projects.d/*/site.caddy` in its Caddyfile and put `LODGE_DOMAIN` in its environment. - -Rules that keep `site.caddy` portable: - -- the domain comes only from the environment variable -- no `tls` block, certificates are configured by the host Caddy (`acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}` in the global block) -- snippets are prefixed with the project slug because Caddy snippets are global -- mount the directory, not the file: a single-file bind mount goes stale when git replaces the inode -- keep `admin localhost:2019`, `admin off` makes `caddy reload` impossible +`site.caddy` routes `{$LODGE_DOMAIN}` to the project over the external `caddy` network. In a shared Caddy, mount this directory as `/etc/caddy/projects.d/lodge:ro` and set `LODGE_DOMAIN`. Keep it portable: domain only from the env, no `tls`, snippets prefixed with `lodge_`. diff --git a/frontend/.dockerignore b/frontend/.dockerignore index 1048241..ed46f37 100644 --- a/frontend/.dockerignore +++ b/frontend/.dockerignore @@ -1,5 +1,7 @@ node_modules .svelte-kit build -.env +# .env goes into the build: $env/static/public (and static/private) are +# inlined at build time from it. It stays in the builder stage, the runtime +# image gets build/ only. Local overrides (.env.local and the like) stay out. .env.* diff --git a/frontend/Makefile b/frontend/Makefile index 0cef562..484b133 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -1,8 +1,6 @@ COMPOSE := cd .. && docker compose -changed = ! git diff --quiet $(1) -- $(2) 2>/dev/null -stamp = { git update-ref $(1) HEAD 2>/dev/null || true; } -.PHONY: fmt check build pre-deploy post-deploy dev +.PHONY: fmt check build dev fmt: bun run fix @@ -14,13 +12,5 @@ check: build: $(COMPOSE) run --rm frontend-dev sh -c "bun install && bun run build" -pre-deploy: - @if $(call changed,refs/deploy/frontend,.) || ! test -d build; then \ - $(MAKE) build && $(call stamp,refs/deploy/frontend); \ - fi - -post-deploy: - @: - dev: bun run dev diff --git a/frontend/docker-compose.override.yml.example b/frontend/docker-compose.override.yml.example index 8909d52..b2a1248 100644 --- a/frontend/docker-compose.override.yml.example +++ b/frontend/docker-compose.override.yml.example @@ -5,6 +5,8 @@ services: caddy: aliases: - lodge-frontend +# ports: +# - "127.0.0.1:3000:3000" networks: caddy: diff --git a/frontend/package.json b/frontend/package.json index 1ad7820..aba21a0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,17 +1,17 @@ { "name": "lodge", - "type": "module", - "private": true, "version": "0.0.1", + "private": true, + "type": "module", "scripts": { - "dev": "vite dev", "build": "vite build", - "preview": "vite preview", - "prepare": "svelte-kit sync || echo ''", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "dev": "vite dev", + "fix": "ultracite fix", "lint": "ultracite check", - "fix": "ultracite fix" + "prepare": "svelte-kit sync || echo ''", + "preview": "vite preview" }, "devDependencies": { "@biomejs/biome": "2.5.13", diff --git a/frontend/src/routes/r/[key]/+page.svelte b/frontend/src/routes/r/[key]/+page.svelte index a54cc54..b380a3d 100644 --- a/frontend/src/routes/r/[key]/+page.svelte +++ b/frontend/src/routes/r/[key]/+page.svelte @@ -336,7 +336,7 @@ {group === SHARED ? "Shared notes" : `Branch ${spaceName(group)}`}