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 _src_path: https://git.kotikot.com/templates/blank.git
layout: part layout: part
part: backend 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 _src_path: https://git.kotikot.com/templates/caddy.git
project_slug: lodge project_slug: lodge
routes: 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 _src_path: https://git.kotikot.com/templates/frontend-svelte.git
include_impeccable: true
install_deps: true install_deps: true
layout: part layout: part
linter: biome
project_name: lodge project_name: lodge
project_slug: lodge project_slug: lodge
serve: api 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 _src_path: https://git.kotikot.com/templates/infra.git
init_git: true init_git: true
layout: parts layout: parts
mcp_servers:
- svelte
parts: parts:
- backend - backend
- frontend - frontend
+3
View File
@@ -4,3 +4,6 @@
docker-compose.override.yml docker-compose.override.yml
.DS_Store .DS_Store
.idea .idea
# Local playground
/t/
+13 -8
View File
@@ -1,10 +1,19 @@
PARTS := $(patsubst %/Makefile,%,$(wildcard */Makefile)) 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: env:
@test -f .env || awk 'FNR == 1 && NR > 1 { print "" } 1' .env.example $(addsuffix /.env.example,$(PARTS)) > .env @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 test -f $$part/docker-compose.override.yml || cp $$part/docker-compose.override.yml.example $$part/docker-compose.override.yml; done 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: recreate:
docker compose up -d --force-recreate docker compose up -d --force-recreate
@@ -21,9 +30,5 @@ logs:
down: down:
docker compose down docker compose down
deploy: pre-deploy fmt check build:
docker compose up -d
$(MAKE) post-deploy
fmt check build pre-deploy post-deploy:
@for part in $(PARTS); do $(MAKE) -C $$part $@ || exit 1; done @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 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 ```sh
make env make env # .env and docker-compose.override.yml from the examples
make recreate 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. Parts: `backend/`, `frontend/`, each with its own Makefile.
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 ...`.
## How it works ## How it works
+1 -12
View File
@@ -1,10 +1,7 @@
COMPOSE := cd .. && docker compose COMPOSE := cd .. && docker compose
IMAGE := lodge/backend
LINT := go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.13.2 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: fmt:
go mod tidy go mod tidy
@@ -20,14 +17,6 @@ test:
build: build:
$(COMPOSE) build api $(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: client:
go build -trimpath -ldflags "-s -w" -o bin/lodge ./cmd/lodge go build -trimpath -ldflags "-s -w" -o bin/lodge ./cmd/lodge
+1 -1
View File
@@ -1,2 +1,2 @@
.env .env
Caddyfile /Caddyfile
+1 -20
View File
@@ -1,22 +1,3 @@
# caddy # 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. `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_`.
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
+3 -1
View File
@@ -1,5 +1,7 @@
node_modules node_modules
.svelte-kit .svelte-kit
build 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.* .env.*
+1 -11
View File
@@ -1,8 +1,6 @@
COMPOSE := cd .. && docker compose 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: fmt:
bun run fix bun run fix
@@ -14,13 +12,5 @@ check:
build: build:
$(COMPOSE) run --rm frontend-dev sh -c "bun install && bun run 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: dev:
bun run dev bun run dev
@@ -5,6 +5,8 @@ services:
caddy: caddy:
aliases: aliases:
- lodge-frontend - lodge-frontend
# ports:
# - "127.0.0.1:3000:3000"
networks: networks:
caddy: caddy:
+6 -6
View File
@@ -1,17 +1,17 @@
{ {
"name": "lodge", "name": "lodge",
"type": "module",
"private": true,
"version": "0.0.1", "version": "0.0.1",
"private": true,
"type": "module",
"scripts": { "scripts": {
"dev": "vite dev",
"build": "vite build", "build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"dev": "vite dev",
"fix": "ultracite fix",
"lint": "ultracite check", "lint": "ultracite check",
"fix": "ultracite fix" "prepare": "svelte-kit sync || echo ''",
"preview": "vite preview"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.5.13", "@biomejs/biome": "2.5.13",