diff --git a/template/{{ part_dir }}/Makefile.jinja b/template/{{ part_dir }}/Makefile.jinja index 7f592f7..82567ab 100644 --- a/template/{{ part_dir }}/Makefile.jinja +++ b/template/{{ part_dir }}/Makefile.jinja @@ -4,10 +4,23 @@ {%- if 'taskiq_worker' in backend_services %}{% set _ = svc_modules.append("worker") %}{% endif -%} {%- if 'kurigram_userbot' in backend_services %}{% set _ = svc_modules.append("userbot") %}{% endif -%} {%- if 'scheduler' in backend_services and 'taskiq_worker' not in backend_services %}{% set _ = svc_modules.append("scheduler") %}{% endif -%} +{%- set app_services = [] -%} +{%- if 'api' in backend_services %}{% set _ = app_services.append("api") %}{% endif -%} +{%- if 'aiogram_bot' in backend_services %}{% set _ = app_services.append("bot") %}{% endif -%} +{%- if 'taskiq_worker' in backend_services %}{% set _ = app_services.append("worker") %}{% endif -%} +{%- if 'kurigram_userbot' in backend_services %}{% set _ = app_services.append("userbot") %}{% endif -%} +{%- if 'scheduler' in backend_services %}{% set _ = app_services.append("scheduler") %}{% endif -%} {%- set has_script = dynamic_config and svc_modules -%} +{%- set has_scripts = dynamic_config or 'kurigram_userbot' in backend_services -%} COMPOSE := docker compose{% if layout == 'part' %} --project-directory ..{% endif %} - -.PHONY: {% if layout == 'root' %}env recreate rebuild restart logs down {% endif %}fmt check build{% if database == 'postgres' %} migrate revision{% endif %}{% if has_script %} script{% endif %}{% if 'kurigram_userbot' in backend_services %} session{% endif %} +{% if svc_modules %}IMAGE := {{ project_slug }}/backend +IMAGE_INPUTS := pyproject.toml uv.lock Dockerfile +CODE := src{% if has_scripts %} scripts{% endif %} +SERVICES := {{ app_services | join(' ') }} +changed = ! git diff --quiet $(1) -- $(2) 2>/dev/null +stamp = { git update-ref $(1) HEAD 2>/dev/null || true; } +{% endif %} +.PHONY: {% if layout == 'root' %}env recreate rebuild restart logs down deploy {% endif %}fmt check{% if svc_modules %} build pre-deploy post-deploy{% endif %}{% if database == 'postgres' %} migrate revision{% endif %}{% if has_script %} script{% endif %}{% if 'kurigram_userbot' in backend_services %} session{% endif %} fmt: uv run ruff format @@ -17,10 +30,24 @@ check: uv run ruff format --check uv run ruff check uv run ty check - +{% if svc_modules %} build: $(COMPOSE) build {{ svc_modules[0] }} -{% if layout == 'root' %} + +pre-deploy: + @if $(call changed,refs/deploy/backend,$(IMAGE_INPUTS)) || ! docker image inspect $(IMAGE) >/dev/null 2>&1; then \ + $(MAKE) build && $(call stamp,refs/deploy/backend) && $(call stamp,refs/deploy/backend-code); \ + fi +{% if database == 'postgres' %} @$(COMPOSE) config --services | grep -qx postgres && $(COMPOSE) up -d postgres || true + $(MAKE) migrate +{% endif %} +post-deploy: + @if $(call changed,refs/deploy/backend-code,$(CODE)); then \ + running=$$($(COMPOSE) ps --services --status running | grep -x $(addprefix -e ,$(SERVICES))); \ + [ -z "$$running" ] || $(COMPOSE) restart $$running; \ + $(call stamp,refs/deploy/backend-code); \ + fi +{% endif %}{% if layout == 'root' %} env: @test -f .env || cp .env.example .env @test -f docker-compose.override.yml || cp docker-compose.override.yml.example docker-compose.override.yml @@ -39,12 +66,16 @@ logs: down: $(COMPOSE) down -{% endif %}{% if database == 'postgres' %} +{% if svc_modules %} +deploy: pre-deploy + $(COMPOSE) up -d + $(MAKE) post-deploy +{% endif %}{% endif %}{% if database == 'postgres' %} migrate: - $(COMPOSE) --profile external run --rm migrator + $(COMPOSE) run --rm migrator revision: - $(COMPOSE) --profile external run --rm migrator revision --autogenerate -m "$(m)" + $(COMPOSE) run --rm migrator revision --autogenerate -m "$(m)" {% endif %}{% if has_script %} script: @$(COMPOSE) run --rm {{ svc_modules[0] }} scripts.$(word 2,$(MAKECMDGOALS)) $(wordlist 3,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) diff --git a/template/{{ part_dir }}/docker-compose.yml.jinja b/template/{{ part_dir }}/docker-compose.yml.jinja index 5ff06c2..0d1e3a1 100644 --- a/template/{{ part_dir }}/docker-compose.yml.jinja +++ b/template/{{ part_dir }}/docker-compose.yml.jinja @@ -104,6 +104,7 @@ services: depends_on: postgres: condition: service_healthy + required: false networks: database: {% endif %} diff --git a/template/{{ part_dir }}/{% if layout == 'root' %}README.md{% endif %}.jinja b/template/{{ part_dir }}/{% if layout == 'root' %}README.md{% endif %}.jinja index 1d6d656..e666e1a 100644 --- a/template/{{ part_dir }}/{% if layout == 'root' %}README.md{% endif %}.jinja +++ b/template/{{ part_dir }}/{% if layout == 'root' %}README.md{% endif %}.jinja @@ -15,4 +15,6 @@ make recreate `make env` creates `.env` and `docker-compose.override.yml` from their examples. `make recreate` starts the selected profiles, `make rebuild` builds the image first, `make logs`, `make restart` and `make down` do what they say. -`make fmt` formats, `make check` runs ruff and ty.{% if targets %} Also {{ targets | join(", ") }}.{% endif %} +{% if backend_services %}To deploy, `git pull && make deploy`. It runs `make pre-deploy`, which builds the image only when `pyproject.toml`, `uv.lock` or `Dockerfile` changed{% if database == 'postgres' %} and applies migrations{% endif %}, 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. + +{% endif %}`make fmt` formats, `make check` runs ruff and ty.{% if targets %} Also {{ targets | join(", ") }}.{% endif %}