feat: add full project - backend, frontend, docker, specs and configs
This commit is contained in:
parent
b77c7d5a01
commit
e6cb06255b
24489 changed files with 61341 additions and 36 deletions
114
.specify/features/002-docker-setup/plan.md
Normal file
114
.specify/features/002-docker-setup/plan.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# Implementation Plan: Docker Setup
|
||||
|
||||
**Branch**: `002-docker-setup`
|
||||
**Spec**: `.specify/features/002-docker-setup/spec.md`
|
||||
**Created**: 2026-04-13
|
||||
|
||||
## Constitution Check
|
||||
- ✅ Design-First: não se aplica (infra)
|
||||
- ✅ Separation of Concerns: Flask e React permanecem desacoplados, Docker apenas orquestra
|
||||
- ✅ Spec-Driven: este plano deriva da spec aprovada
|
||||
- ✅ Security: nenhuma secret hardcoded; `.env` no gitignore
|
||||
- ✅ Simplicity: sem multi-stage build, sem nginx — foco em dev environment
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Backend Dockerfile
|
||||
|
||||
**Objetivo**: Containerizar o Flask app usando python:3.12-slim e uv.
|
||||
|
||||
**Arquivos**:
|
||||
- `backend/Dockerfile`
|
||||
|
||||
**Detalhes**:
|
||||
- Base: `python:3.12-slim`
|
||||
- Instalar `uv` via pip
|
||||
- Copiar `pyproject.toml` → `uv sync` → copiar código
|
||||
- Entrypoint: script shell que executa `flask db upgrade && python seeds/seed.py && python run.py`
|
||||
- Porta exposta: 5000
|
||||
|
||||
**Critério de conclusão**: `docker build -t backend ./backend` conclui sem erro.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Frontend Dockerfile
|
||||
|
||||
**Objetivo**: Containerizar o servidor de desenvolvimento Vite com hot-reload.
|
||||
|
||||
**Arquivos**:
|
||||
- `frontend/Dockerfile`
|
||||
|
||||
**Detalhes**:
|
||||
- Base: `node:20-alpine`
|
||||
- Copiar `package*.json` → `npm ci` → copiar código
|
||||
- CMD: `npm run dev -- --host 0.0.0.0` (necessário para expor dentro do container)
|
||||
- Porta exposta: 5173
|
||||
- O `vite.config.ts` já tem proxy `/api → http://localhost:5000`; atualizar para `http://backend:5000` (nome do serviço Docker)
|
||||
|
||||
**Critério de conclusão**: `docker build -t frontend ./frontend` conclui sem erro.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — docker-compose.yml
|
||||
|
||||
**Objetivo**: Orquestrar db + backend + frontend com dependências e healthchecks.
|
||||
|
||||
**Arquivos**:
|
||||
- `docker-compose.yml` (raiz)
|
||||
- `.env.example` (atualizar/criar na raiz)
|
||||
|
||||
**Serviços**:
|
||||
```yaml
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
healthcheck: pg_isready -U ${POSTGRES_USER}
|
||||
depends_on: (nenhum)
|
||||
|
||||
backend:
|
||||
build: ./backend
|
||||
depends_on:
|
||||
db: { condition: service_healthy }
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
depends_on: [backend]
|
||||
volumes:
|
||||
- ./frontend/src:/app/src ← hot-reload
|
||||
- ./frontend/public:/app/public
|
||||
```
|
||||
|
||||
**Critério de conclusão**: `docker-compose config` valida sem erro; `docker-compose up` sobe os 3 serviços.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — start.ps1
|
||||
|
||||
**Objetivo**: Script PowerShell de conveniência na raiz.
|
||||
|
||||
**Arquivos**:
|
||||
- `start.ps1` (raiz)
|
||||
|
||||
**Lógica**:
|
||||
1. Verificar se `docker` está disponível no PATH
|
||||
2. Se não: exibir mensagem com link para Docker Desktop e sair
|
||||
3. Se sim: executar `docker-compose up --build`
|
||||
|
||||
**Critério de conclusão**: `.\start.ps1` inicia o ambiente ou exibe erro informativo.
|
||||
|
||||
---
|
||||
|
||||
## Sequência de execução
|
||||
|
||||
```
|
||||
Phase 1 (backend/Dockerfile)
|
||||
↓
|
||||
Phase 2 (frontend/Dockerfile + vite.config proxy update)
|
||||
↓
|
||||
Phase 3 (docker-compose.yml + .env.example)
|
||||
↓
|
||||
Phase 4 (start.ps1)
|
||||
↓
|
||||
Validação: docker-compose up --build → testar endpoints
|
||||
```
|
||||
93
.specify/features/002-docker-setup/spec.md
Normal file
93
.specify/features/002-docker-setup/spec.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Feature Specification: Docker Setup
|
||||
|
||||
**Feature Branch**: `002-docker-setup`
|
||||
**Created**: 2026-04-13
|
||||
**Status**: Approved
|
||||
|
||||
## User Scenarios & Testing
|
||||
|
||||
### User Story 1 — Desenvolvedor sobe todo o ambiente com um comando (Priority: P1)
|
||||
|
||||
Um desenvolvedor que acabou de clonar o repositório deve conseguir subir PostgreSQL, backend Flask e frontend React rodando juntos com um único comando, sem instalar Python ou Node localmente.
|
||||
|
||||
**Why this priority**: É o bloqueio zero de onboarding. Sem isso, cada dev configura manualmente, gerando ambientes inconsistentes.
|
||||
|
||||
**Independent Test**: Executar `docker-compose up --build` na raiz e acessar `http://localhost:5173` deve exibir a homepage carregando dados do backend.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** o repositório recém-clonado com Docker instalado, **When** o dev roda `docker-compose up --build`, **Then** os três serviços (db, backend, frontend) sobem sem erro e ficam acessíveis.
|
||||
2. **Given** o ambiente rodando, **When** o dev acessa `http://localhost:5173`, **Then** a homepage é renderizada com dados reais do banco.
|
||||
3. **Given** o ambiente rodando, **When** o dev acessa `http://localhost:5000/api/v1/homepage-config`, **Then** a API retorna JSON 200 com os dados seedados.
|
||||
4. **Given** o ambiente rodando, **When** o dev faz uma alteração num arquivo `.tsx`, **Then** o Vite hot-reload atualiza o browser sem reiniciar o container.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 — Script de conveniência na raiz (Priority: P1)
|
||||
|
||||
Um desenvolvedor Windows deve poder rodar `.\start.ps1` na raiz para ter o ambiente de um clique, sem memorizar comandos Docker.
|
||||
|
||||
**Why this priority**: Reduz fricção para devs Windows que são o público principal.
|
||||
|
||||
**Independent Test**: `.\start.ps1` executa `docker-compose up --build` e exibe mensagens de status claras.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** Docker Desktop instalado, **When** o dev roda `.\start.ps1`, **Then** o script valida que Docker está rodando e executa o compose.
|
||||
2. **Given** Docker não instalado, **When** o dev roda `.\start.ps1`, **Then** o script exibe mensagem clara pedindo para instalar Docker Desktop.
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- O que acontece se a porta 5432/5000/5173 já estiver em uso? → `docker-compose` retorna erro; o script deve informar.
|
||||
- O que acontece se o banco ainda não estiver pronto quando o backend inicializar? → `depends_on` com `healthcheck`; backend deve aguardar ou fazer retry.
|
||||
- Como rodar as migrations no primeiro boot? → Entrypoint do backend executa `flask db upgrade` antes de `python run.py`.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional
|
||||
- FR1: `docker-compose up --build` na raiz sobe 3 serviços: `db` (PostgreSQL 16), `backend` (Flask), `frontend` (React/Vite)
|
||||
- FR2: Backend aguarda PostgreSQL estar saudável antes de inicializar (healthcheck)
|
||||
- FR3: Backend executa `flask db upgrade` + seeder automaticamente no primeiro boot
|
||||
- FR4: Frontend tem hot-reload via bind mount do código-fonte
|
||||
- FR5: Variáveis de ambiente devem estar em `.env` na raiz (não hardcoded no compose)
|
||||
- FR6: `.\start.ps1` na raiz é o ponto de entrada único para Windows
|
||||
|
||||
### Non-Functional
|
||||
- NFR1: `docker-compose up --build` deve completar em menos de 5 min com cache
|
||||
- NFR2: Imagens devem usar variantes slim/alpine para minimizar tamanho
|
||||
- NFR3: Nenhuma secret hardcoded nas imagens — tudo via env vars
|
||||
- NFR4: `.env` não deve ser commitado; `.env.example` deve existir
|
||||
|
||||
## Design / Architecture
|
||||
|
||||
```
|
||||
raiz/
|
||||
├── docker-compose.yml ← orchestração dos 3 serviços
|
||||
├── .env.example ← template de variáveis (db, secret key)
|
||||
├── .env ← valores locais (gitignored)
|
||||
├── start.ps1 ← script Windows de conveniência
|
||||
├── backend/
|
||||
│ └── Dockerfile ← python:3.12-slim, uv, flask
|
||||
└── frontend/
|
||||
└── Dockerfile ← node:20-alpine, vite dev server
|
||||
```
|
||||
|
||||
**Serviços docker-compose:**
|
||||
- `db`: postgres:16-alpine, volume persistente, healthcheck
|
||||
- `backend`: build ./backend, porta 5000, DATABASE_URL apontando para `db`
|
||||
- `frontend`: build ./frontend, porta 5173, bind mount src/ para hot-reload, proxy vite → backend
|
||||
|
||||
## Out of Scope
|
||||
- Build de produção (multi-stage, nginx servindo static) — feature futura
|
||||
- CI/CD pipeline
|
||||
- Deploy em cloud
|
||||
- HTTPS/TLS local
|
||||
|
||||
## Success Criteria
|
||||
1. `docker-compose up --build` funciona do zero em máquina limpa
|
||||
2. `http://localhost:5173` carrega homepage com dados reais
|
||||
3. `http://localhost:5000/api/v1/properties?featured=true` retorna array JSON com imóveis seedados
|
||||
4. Alteração em `.tsx` reflete no browser sem restart do container
|
||||
5. `.env` está no `.gitignore`; `.env.example` documenta todas as variáveis necessárias
|
||||
109
.specify/features/002-docker-setup/tasks.md
Normal file
109
.specify/features/002-docker-setup/tasks.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Tasks: Docker Setup
|
||||
|
||||
**Branch**: `002-docker-setup`
|
||||
**Plan**: `.specify/features/002-docker-setup/plan.md`
|
||||
**Created**: 2026-04-13
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Backend Dockerfile
|
||||
|
||||
### T001 — Criar backend/Dockerfile
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: nenhuma
|
||||
- **Spec ref**: FR1, FR3
|
||||
- **Files**: `backend/Dockerfile`, `backend/entrypoint.sh`
|
||||
- **Done when**: `docker build -t imob-backend ./backend` conclui sem erro
|
||||
|
||||
### T002 — Criar entrypoint.sh com migrations + seed + server
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: T001
|
||||
- **Spec ref**: FR3
|
||||
- **Files**: `backend/entrypoint.sh`
|
||||
- **Done when**: Script executa `flask db upgrade`, seeder, e sobe Flask na porta 5000
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Frontend Dockerfile
|
||||
|
||||
### T003 — Criar frontend/Dockerfile
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: nenhuma [P] paralelo com T001
|
||||
- **Spec ref**: FR1, FR4
|
||||
- **Files**: `frontend/Dockerfile`
|
||||
- **Done when**: `docker build -t imob-frontend ./frontend` conclui sem erro
|
||||
|
||||
### T004 — Atualizar vite.config.ts para proxy Docker
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: T003
|
||||
- **Spec ref**: FR1
|
||||
- **Files**: `frontend/vite.config.ts`
|
||||
- **Done when**: Proxy aponta para `http://backend:5000` (nome do serviço Docker); local dev ainda funciona via variável de ambiente
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Orquestração
|
||||
|
||||
### T005 — Criar docker-compose.yml
|
||||
- **Complexity**: M
|
||||
- **Dependencies**: T001, T003
|
||||
- **Spec ref**: FR1, FR2, FR4, FR5
|
||||
- **Files**: `docker-compose.yml`
|
||||
- **Done when**: `docker-compose config` valida; 3 serviços definidos com healthcheck no db
|
||||
|
||||
### T006 — Criar .env.example na raiz
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: T005
|
||||
- **Spec ref**: FR5, NFR4
|
||||
- **Files**: `.env.example` (raiz)
|
||||
- **Done when**: Todas as variáveis usadas no compose estão documentadas com valores de exemplo
|
||||
|
||||
### T007 — Verificar .gitignore cobre .env
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: T006
|
||||
- **Spec ref**: NFR3, NFR4
|
||||
- **Files**: `.gitignore`
|
||||
- **Done when**: `.env` está no .gitignore e não aparece em `git status`
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Script de conveniência
|
||||
|
||||
### T008 — Criar start.ps1 na raiz
|
||||
- **Complexity**: S
|
||||
- **Dependencies**: T005
|
||||
- **Spec ref**: FR6
|
||||
- **Files**: `start.ps1`
|
||||
- **Done when**: `.\start.ps1` valida Docker e executa compose; exibe erro claro se Docker não estiver instalado
|
||||
|
||||
---
|
||||
|
||||
## Validação
|
||||
|
||||
### T009 — Testar docker-compose up --build end-to-end
|
||||
- **Complexity**: M
|
||||
- **Dependencies**: T005, T008
|
||||
- **Spec ref**: Todos os Acceptance Scenarios
|
||||
- **Done when**:
|
||||
- `http://localhost:5173` carrega homepage
|
||||
- `http://localhost:5000/api/v1/homepage-config` retorna 200
|
||||
- `http://localhost:5000/api/v1/properties?featured=true` retorna array
|
||||
- Editar um `.tsx` reflete no browser via hot-reload
|
||||
|
||||
---
|
||||
|
||||
## Resumo
|
||||
|
||||
| Task | Fase | Complexidade | Paralelo? |
|
||||
|------|------|-------------|-----------|
|
||||
| T001 | Backend Dockerfile | S | - |
|
||||
| T002 | entrypoint.sh | S | - |
|
||||
| T003 | Frontend Dockerfile | S | ✅ com T001 |
|
||||
| T004 | vite proxy Docker | S | - |
|
||||
| T005 | docker-compose.yml | M | - |
|
||||
| T006 | .env.example raiz | S | - |
|
||||
| T007 | .gitignore check | S | - |
|
||||
| T008 | start.ps1 | S | - |
|
||||
| T009 | Validação E2E | M | - |
|
||||
|
||||
**MVP**: T001–T008 = ambiente Docker funcional.
|
||||
Loading…
Add table
Add a link
Reference in a new issue