Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ENV=development
DATABASE_URL=postgresql+psycopg://user:password@localhost:5432/template_db
REDIS_URL=redis://localhost:6379/0
CELERY_BROKER_URL=redis://localhost:6379/1
SECRET_KEY=change-me
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ENV=development
DATABASE_URL=postgresql+psycopg://user:password@localhost:5432/template_db
REDIS_URL=redis://localhost:6379/0
CELERY_BROKER_URL=redis://localhost:6379/1
SECRET_KEY=change-me
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CI

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.14
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Ruff
run: ruff check .

test:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.14
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-asyncio
- name: Run tests
run: pytest -q
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.18.0"
hooks:
- id: ruff
8 changes: 8 additions & 0 deletions CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Convenções do template

- **Naming:** módulos e arquivos em `snake_case`, classes em `PascalCase`.
- **Camadas:** prefixos `services`, `repositories`, `models`, `schemas`.
- **Schemas:** pydantic models com sufixo `Schema` (ex: `UserSchema`).
- **Repos:** interfaces nomeadas `*Repository` e implementações em `infrastructure`.
- **Settings:** usar `pydantic.BaseSettings` e carregar `.env`.
- **DI:** preferir injeção por factory ou passagem explícita de dependências.
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM python:3.14-slim AS base
ENV PYTHONUNBUFFERED=1
WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
&& rm -rf /var/lib/apt/lists/*

COPY requirements.txt ./
RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt

COPY . /app

CMD ["uvicorn", "--factory", "src.app.factory:create_app", "--host", "0.0.0.0", "--port", "8000"]
25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.PHONY: dev test lint format migrate worker up down

dev:
uvicorn --factory src.app.factory:create_app --reload

test:
pytest -q

lint:
ruff check .

format:
ruff format .

migrate:
./scripts/migrate.sh

worker:
celery -A src.app.worker.app worker --loglevel=info

up:
docker-compose up -d --build

down:
docker-compose down
26 changes: 26 additions & 0 deletions alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[alembic]
script_location = alembic

[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console

[handler_console]
class = StreamHandler
args = (sys.stdout,)
level = NOTSET

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s

# sqlalchemy.url can be overridden by ENV when running alembic
sqlalchemy.url = driver://user:pass@localhost/dbname
49 changes: 49 additions & 0 deletions alembic/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from __future__ import with_statement

import os
import sys
from pathlib import Path
from logging.config import fileConfig

from sqlalchemy import engine_from_config, pool
from alembic import context

# ensure repo root is on path so `src` package can be imported
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))

from src.app.db.base import Base # type: ignore # noqa: E402

# Alembic Config object (access to ini file values)
config = context.config

# Interpret the config file for Python logging.
if config.config_file_name is not None:
fileConfig(config.config_file_name)

target_metadata = Base.metadata


def run_migrations_offline():
url = os.environ.get("DATABASE_URL") or config.get_main_option("sqlalchemy.url")
context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
with context.begin_transaction():
context.run_migrations()


def run_migrations_online():
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()


if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
21 changes: 21 additions & 0 deletions alembic/versions/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""empty initial migration

Revision ID: 0001_initial
Revises:
Create Date: 2026-04-24
"""

revision = "0001_initial"
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# Add schema changes here (initial migration placeholder)
pass


def downgrade():
# Revert schema changes here
pass
47 changes: 47 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
services:
app:
build: .
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
- redis
networks:
- internal

worker:
build: .
command: celery -A src.app.celery_app.celery_app worker --loglevel=info
env_file:
- .env
depends_on:
- redis
- db
networks:
- internal

redis:
image: redis:7-alpine
restart: unless-stopped
networks:
- internal

db:
image: postgres:17-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: template_db
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- internal

volumes:
pgdata:

networks:
internal:
driver: bridge
4 changes: 4 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[mypy]
python_version = 3.14
ignore_missing_imports = True
strict = False
Loading
Loading