Compare commits

...
6 Commits
14 changed files with 42 additions and 73 deletions

No files matched your search

+1 -1
View File
@@ -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
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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
+3 -1
View File
@@ -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
+3
View File
@@ -4,3 +4,6 @@
docker-compose.override.yml
.DS_Store
.idea
# Local playground
/t/
+13 -8
View File
@@ -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
+4 -9
View File
@@ -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
+1 -12
View File
@@ -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
+1 -1
View File
@@ -1,2 +1,2 @@
.env
Caddyfile
/Caddyfile
+1 -20
View File
@@ -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_`.
+3 -1
View File
@@ -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.*
+1 -11
View File
@@ -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
@@ -5,6 +5,8 @@ services:
caddy:
aliases:
- lodge-frontend
# ports:
# - "127.0.0.1:3000:3000"
networks:
caddy:
+6 -6
View File
@@ -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",